ArgumentProvider<T> is a functional interface that converts command input arguments into specific types. It provides the core argument parsing mechanism in Blade, handling everything from simple types like integers to complex custom objects.
Interface Definition
@FunctionalInterface
public interface ArgumentProvider<T> {
@Nullable
T provide(@NotNull Context ctx, @NotNull InputArgument arg) throws BladeParseError;
}
Core Method
provide()
Converts a command input argument into the target type.
The command execution context containing sender information and metadata
The input argument containing the raw value and parameter metadata
The converted value, or null if conversion failed
Throws: BladeParseError if an error occurs during conversion
Example Implementation
public class IntArgument implements ArgumentProvider<Integer> {
@Override
public Integer provide(@NotNull Context ctx, @NotNull InputArgument arg)
throws BladeParseError {
try {
return Integer.parseInt(arg.requireValue());
} catch (NumberFormatException e) {
throw BladeParseError.fatal(
"'" + arg.value() + "' is not a valid whole number."
);
}
}
}
Default Methods
Determines whether this provider should be called when the argument value is null.
default boolean handlesNullInputArguments() {
return false;
}
true if the provider handles null arguments, false otherwise (default)
This is useful for providers that implement logic for optional arguments, particularly when handling @Opt(Type.SENDER) where the argument might default to the command sender.
Example
public class PlayerArgument implements ArgumentProvider<Player> {
@Override
public boolean handlesNullInputArguments() {
return true; // Handle @Opt(Type.SENDER) case
}
@Override
public Player provide(@NotNull Context ctx, @NotNull InputArgument arg)
throws BladeParseError {
// Handle case where argument is not provided but defaults to sender
if (arg.isOptionalWithType(Opt.Type.SENDER) && !arg.status().isPresent()) {
return ctx.sender().parseAs(Player.class);
}
// Handle explicit null for @Opt arguments
if (arg.value() == null && arg.isOptionalAcceptingNull()) {
return null;
}
// Normal parsing logic
return getPlayer(arg.requireValue());
}
}
alwaysParseQuotes()
Determines whether this provider should always parse quoted strings from input.
default boolean alwaysParseQuotes() {
return false;
}
true if quotes should always be parsed, false otherwise (default)
When true, the input argument will have quotes parsed even if the command method or parameter is not annotated with @Quoted. This is useful for string-based providers that commonly handle multi-word inputs.
Example
public class StringArgument implements ArgumentProvider<String> {
@Override
public boolean alwaysParseQuotes() {
return true; // Always handle "quoted strings" for String parameters
}
@Override
public String provide(@NotNull Context ctx, @NotNull InputArgument arg) {
return arg.requireValue(); // Will contain unquoted content
}
}
defaultArgName()
Provides a default argument name for this provider when not explicitly specified.
default String defaultArgName(@NotNull AnnotatedElement element) {
return null;
}
The annotated parameter element from the command method
The default argument name, or null to use the parameter name
This name appears in usage messages and error messages when the parameter is not annotated with @Name.
Example
public class PlayerArgument implements ArgumentProvider<Player> {
@Override
public String defaultArgName(@NotNull AnnotatedElement element) {
return "player"; // Usage: /command <player> instead of /command <arg0>
}
}
Suggestion Methods
suggest()
Provides tab completion suggestions for the argument.
default void suggest(@NotNull Context ctx,
@NotNull InputArgument arg,
@NotNull SuggestionsBuilder suggestions)
throws BladeParseError {
}
The command execution context
The input argument being completed
suggestions
SuggestionsBuilder
required
Builder for adding string suggestions
Throws: BladeParseError if an error occurs during suggestion generation
Example
public class PlayerArgument implements ArgumentProvider<Player> {
@Override
public void suggest(@NotNull Context ctx,
@NotNull InputArgument arg,
@NotNull SuggestionsBuilder suggestions) {
Player sender = ctx.sender().parseAs(Player.class);
String input = arg.requireValue();
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getName().toLowerCase().startsWith(input.toLowerCase())
&& (sender == null || sender.canSee(player))) {
suggestions.suggest(player.getName());
}
}
}
}
suggestRich()
Provides enhanced tab completion suggestions with tooltips and metadata.
default void suggestRich(@NotNull Context ctx,
@NotNull InputArgument arg,
@NotNull RichSuggestionsBuilder suggestions)
throws BladeParseError {
suggest(ctx, arg, suggestions.legacyView());
}
The command execution context
The input argument being completed
suggestions
RichSuggestionsBuilder
required
Builder for adding rich suggestions with tooltips and numeric values
Throws: BladeParseError if an error occurs during suggestion generation
The default implementation delegates to suggest() for backwards compatibility. Override this method to provide richer suggestions for Brigadier-based platforms.
Example
public class WorldArgument implements ArgumentProvider<World> {
@Override
public void suggestRich(@NotNull Context ctx,
@NotNull InputArgument arg,
@NotNull RichSuggestionsBuilder suggestions) {
for (World world : Bukkit.getWorlds()) {
String tooltip = String.format(
"Players: %d | Time: %d",
world.getPlayerCount(),
world.getTime()
);
suggestions.suggest(world.getName(), SuggestionTooltip.of(tooltip));
}
}
}
Error Handling
Use BladeParseError to report parsing errors:
Fatal Errors
Fatal errors always stop command execution:
throw BladeParseError.fatal("Invalid input: " + arg.value());
Recoverable Errors
Recoverable errors allow execution to continue if the parameter is optional:
if (player == null) {
throw BladeParseError.recoverable(
"No online player found with name '" + arg.value() + "'"
);
}
For optional parameters, recoverable errors result in null values and silent failure. For required parameters, they behave like fatal errors.
Registration
Register argument providers with the Blade instance:
Blade.of()
.bind(Integer.class, new IntArgument())
.bind(Player.class, new PlayerArgument())
.build();