CommandArguments
The CommandArguments
class was introduced in CommandAPI 9.0.0 and provides a much more powerful way of accessing arguments than just an array of arguments which existed until 9.0.0.
While the argument array just gives the possibility to access the arguments via the array notation (args[0]
), the CommandArguments
class offers much more, including:
- Access the inner structure directly
- Access arguments
- Access raw arguments
- Access unsafe arguments
- Access safe arguments
Access the inner structure directly
To access the inner structure of the CommandArguments
class directly, it provides various methods which you can learn about below:
Get the argument array
Object[] args();
This returns the array of arguments as defined when creating your command.
Get the arguments mapped to their node name
Map<String, Object> argsMap();
This returns an unmodifiable map which contains the arguments mapped to their node names.
Get the raw argument array
String[] rawArgs();
This returns the array of raw arguments. An explanation of what raw arguments are can be found in the section about accessing raw arguments.
Get the raw arguments mapped to their node name
Map<String, String> rawArgsMap();
This returns an unmodifiable map which contains the raw arguments mapped to their node names. An explanation of what raw arguments are can be found in the section about accessing raw arguments.
Other useful methods
String fullInput(); // Returns the full command input (including the / character)
int count(); // Returns the amount of arguments
Access arguments
The CommandArguments
class provides its arguments in a way similar to how a List
or Map
let you access their contents. When using these methods, you need to cast the arguments to their respective type. The CommandArguments
class also provides a way to access unsafe arguments.
You can choose to access arguments by their node name or by their index.
Access arguments by node name
Accessing arguments by their node name is the recommended way of accessing arguments.
There are four methods you can use to access arguments by their node name:
Object get(String nodeName);
Object getOrDefault(String nodeName, Object defaultValue);
Object getOrDefault(String nodeName, Supplier<?> defaultValue);
Optional<Object> getOptional(String nodeName);
Access arguments by index
Accessing arguments by their index is the original way of accessing arguments. However, we recommend to access arguments by node name.
Similar to the four methods of accessing arguments by their node name, there also are four methods you can use to access arguments by their index:
Object get(int index);
Object getOrDefault(int index, Object defaultValue);
Object getOrDefault(int index, Supplier<?> defaultValue);
Optional<Object> getOptional(int index);
Example - Access arguments by node name and index
To demonstrate the different ways of accessing arguments, we want to register a command /mycommand
like this:
/mycommand <name> <amount>
/mycommand <name> <amount> <player>
/mycommand <name> <amount> <player> <target>
/mycommand <name> <amount> <player> <target> <message>
This is how these commands are implemented:
new CommandAPICommand("mycommand")
.withArguments(new StringArgument("name"))
.withArguments(new IntegerArgument("amount"))
.withOptionalArguments(new PlayerArgument("player"))
.withOptionalArguments(new PlayerArgument("target"))
.withOptionalArguments(new GreedyStringArgument("message"))
.executesPlayer((player, args) -> {
String name = (String) args.get(0); // Access arguments by index
int amount = (int) args.get("amount"); // Access arguments by node name
Player p = (Player) args.getOrDefault("player", player); // Access arguments using the getOrDefault(String, Object) method
Player target = (Player) args.getOrDefault("target", () -> player); // Access arguments using the getOrDefault(String, Supplier<?>) method
String message = (String) args.getOptional("message").orElse("Hello!"); // Access arguments using the getOptional(String) method
// Do whatever with these values
})
.register();
CommandAPICommand("mycommand")
.withArguments(StringArgument("name"))
.withArguments(IntegerArgument("amount"))
.withOptionalArguments(PlayerArgument("player"))
.withOptionalArguments(PlayerArgument("target"))
.withOptionalArguments(GreedyStringArgument("message"))
.executesPlayer(PlayerCommandExecutor { player, args ->
val name = args[0] as String // Access arguments by index
val amount = args["amount"] as Int // Access arguments by node name
val p = args.getOrDefault("player", player) as Player // Access arguments using the getOrDefault(String, Object) method
val target = args.getOrDefault("target") { player } as Player // Access arguments using the getOrDefault(String, Supplier<?>) method
val message = args.getOptional("message").orElse("Hello!") as String // Access arguments using the getOptional(String) method
// Do whatever with these values
})
.register();
Access raw arguments
A "raw argument" is the String
form of an argument as written in a command. For example:
A user defines a command /mycommand
that accepts a double
as the first argument and an entity selector as the second argument. It could be executed with the values 15.3
as the double
value and @e
as the entity selector:
/mycommand 15.3 @e
When accessing the raw arguments of this command there are 15.3
and @e
available as String
s.
However, when accessing the arguments of this command there is 15.3
available as double
and @e
available as Collection<Entity>
.
Raw arguments are accessed basically the same way you would access arguments. You can access them by their node name and their index in the argument array.
Access raw arguments by node name
Accessing raw arguments by their node name is the recommended way of doing it.
To access raw arguments by their node name, you can use these methods:
String getRaw(String nodeName);
String getOrDefaultRaw(String nodeName, String defaultValue);
String getOrDefaultRaw(String nodeName, Supplier<String> defaultValue);
Optional<String> getRawOptional(String nodeName);
Access raw arguments by index
Of course, if you don't want to access raw arguments by their node name, we also provide the option to access them by index with these methods:
String getRaw(int index);
String getOrDefaultRaw(int index, String defaultValue);
String getOrDefaultRaw(int index, Supplier<String> defaultValue);
Optional<String> getRawOptional(int index);
Example - Access raw arguments by node name and index
To demonstrate how to access raw arguments, we are going to implement the /mycommand
again, this time with the following syntax:
/mycommand <entities>
We want to find out which entity selector is being used when the command is executed.
new CommandAPICommand("mycommand")
.withArguments(new EntitySelectorArgument.ManyEntities("entities"))
.executesPlayer((player, args) -> {
String entitySelector = args.getRaw("entities"); // Access the raw argument with getRaw(String)
// Do whatever with the entity selector
})
.register();
CommandAPICommand("mycommand")
.withArguments(EntitySelectorArgument.ManyEntities("entities"))
.executesPlayer(PlayerCommandExecutor { player, args ->
val entitySelector = args.getRaw("entities")!! // Access the raw argument with getRaw(String)
// Do whatever with the entity selector
})
.register();
Access unsafe arguments
When accessing arguments you need to cast the Object
returned by these methods to the type the argument returns. More about casting arguments here.
Unsafe arguments provide the ability to access an argument without needing to cast it to the argument's type. When not using unsafe arguments, your code looks like this:
String name = (String) args.get("name");
When using unsafe arguments you can make your code look like this:
String name = args.getUnchecked("name");
Unsafe arguments can also be accessed by their node names and their indices.
Access arguments by node name
Unsafe arguments can also be accessed by node name which, again, is the recommended way of doing it.
Use these methods when accessing unsafe arguments by their node name:
T getUnchecked(String nodeName);
T getOrDefaultUnchecked(String nodeName, T defaultValue);
T getOrDefaultUnchecked(String nodeName, Supplier<T> defaultValue);
Optional<T> getOptionalUnchecked(String nodeName);
Access arguments by index
If you want to access unsafe arguments by index, you can do that by using these methods:
T getUnchecked(int index);
T getOrDefaultUnchecked(int index, T defaultValue);
T getOrDefaultUnchecked(int index, Supplier<T> defaultValue);
Optional<T> getOptionalUnchecked(int index);
Example - Access unsafe arguments by node name and index
Finally, we want to implement the /mycommand
again. This time we use this syntax:
/mycommand <player>
Here, we don't actually want to cast the argument, so we use unsafe arguments to remove that cast:
new CommandAPICommand("mycommand")
.withArguments(new PlayerArgument("player"))
.executesPlayer((player, args) -> {
Player p = args.getUnchecked("player");
// Do whatever with the player
})
.register();
CommandAPICommand("mycommand")
.withArguments(PlayerArgument("player"))
.executesPlayer(PlayerCommandExecutor { player, args ->
val p: Player = args.getUnchecked("player")!!
// Do whatever with the player
})
.register();
Access safe arguments
Developer's Note:
The following methods cannot be used to access a value returned by a CustomArgument
as its return type depends on the base argument for it.
Lastly, the CommandArguments class offers you a way to access your arguments in a more safe way by using internal casts. Again, methods are offered to access arguments by their index or their node name:
T getByClass(String nodeName, Class<T> argumentType);
T getByClassOrDefault(String nodeName, Class<T> argumentType, T defaultValue);
T getOptionalByClass(String nodeName, Class<T> argumentType);
T getByClass(int index, Class<T> argumentType);
T getByClassOrDefault(int index, Class<T> argumentType, T defaultValue);
T getOptionalByClass(int index, Class<T> argumentType);
Compared to the other methods the CommandArguments
class offers, these methods take an additional parameter of type Class<T>
where T
is the return type
of the argument with the given node name or index.
For example, say you declared a new StringArgument("value")
and you now want to access the return value of this argument using safe casting. This would be done as follows:
String value = args.getByClass("value", String.class);
val value = args.getByClass("value", String::class.java)
Access safe arguments using an argument instance
Finally, there is one more, even safer way of accessing safe arguments: by using an argument instance:
T getByArgument(Argument<T> argumentType);
T getByArgumentOrDefault(Argument<T> argumentType, T defaultValue);
T getOptionalByArgument(Argument<T> argumentType);
However, while safer, this also introduces the need to first initialize your arguments before you can start implementing your command. To visualize this, we want to implement the command from Access arguments by node name and index again, but this time using safe arguments with an argument instance:
Example - Access safe arguments using an argument instance
StringArgument nameArgument = new StringArgument("name");
IntegerArgument amountArgument = new IntegerArgument("amount");
PlayerArgument playerArgument = new PlayerArgument("player");
PlayerArgument targetArgument = new PlayerArgument("target");
GreedyStringArgument messageArgument = new GreedyStringArgument("message");
new CommandAPICommand("mycommand")
.withArguments(nameArgument)
.withArguments(amountArgument)
.withOptionalArguments(playerArgument)
.withOptionalArguments(targetArgument)
.withOptionalArguments(messageArgument)
.executesPlayer((player, args) -> {
String name = args.getByArgument(nameArgument);
int amount = args.getByArgument(amountArgument);
Player p = args.getByArgumentOrDefault(playerArgument, player);
Player target = args.getByArgumentOrDefault(targetArgument, player);
String message = args.getOptionalByArgument(messageArgument).orElse("Hello!");
// Do whatever with these values
})
.register();
val nameArgument = StringArgument("name")
val amountArgument = IntegerArgument("amount")
val playerArgument = PlayerArgument("player")
val targetArgument = PlayerArgument("target")
val messageArgument = GreedyStringArgument("message")
CommandAPICommand("mycommand")
.withArguments(nameArgument)
.withArguments(amountArgument)
.withOptionalArguments(playerArgument)
.withOptionalArguments(targetArgument)
.withOptionalArguments(messageArgument)
.executesPlayer(PlayerCommandExecutor { player, args ->
val name: String = args.getByArgument(nameArgument)!!
val amount: Int = args.getByArgument(amountArgument)!!
val p: Player = args.getByArgumentOrDefault(playerArgument, player)
val target: Player = args.getByArgumentOrDefault(targetArgument, player)
val message: String = args.getOptionalByArgument(messageArgument).orElse("Hello!")
// Do whatever with these values
})
.register();