-
Notifications
You must be signed in to change notification settings - Fork 2
Subcommands and Advanced Arguments
Rarely are commands as simple as one base command with a handful of primitive-typed arguments. Thankfully, Ordinate supports much more than that. Subcommands are as simple as base commands - to define them, you just nest command bodies:
basecommand {
help = Base command
subcommand {
help = Subcommand
}
}
This defines two commands: basecommand
and basecommand subcommand
, each with their own help entries. Ordinate will automatically detect when a player has used a command wrong, and will show the help page as well as an error about what they did wrong.
But let's define some cooler commands than this. Going back to our add
example before, we can enhance it with a new type of argument: The variable-length argument, or vararg. These arguments take a list of entries - any number of them - and pass them to your hook as an array. Using this, we can improve our add
command to be able to add more than two numbers together:
add int[]:nums {
help = Adds numbers together
hook = add
}
With this defined, let's change our hook to support this:
@CommandHook("add")
public void add(CommandSender sender, int[] nums) {
int sum = Arrays.stream(nums).sum();
sender.sendMessage(String.valueOf(sum));
}
But there are a lot of other ways we can get fancy with our arguments. Another common use case is making them optional, which we can do quite easily too:
helloworld int:times? {
help = Says hello world the given number of times, or once if times is not specified
hook = helloworld
}
The value of this argument will be passed as null if the command is run as helloworld
, so we'll need to account for that in our code by changing the type from int
to Integer
.
@CommandHook("helloworld")
public void helloWorld(CommandSender sender, Integer times) {
if (times == null) {
times = 1;
}
for (int i = 0; i < times; i++) {
sender.sendMessage("Hello, world!");
}
}
But this is a bit tedious, since if we had multiple optional parameters, we would need to add null checks for all of them. It's much more convenient if we can specify a default, which we can:
helloworld int:times?(1) {
hook = helloworld
}
Now if the argument isn't passed, its default value will be 1 without us needing to do anything in our code. Since it's not nullable anymore, we can change the type back from Integer
to int
and remove the null check.
The last way we can change how an argument works is by making it consuming. Consuming arguments work somewhat like variable-length arguments, but rather than parsing each argument individually, and putting them in an array, it parses the entire argument as one value. This is rarely used for anything other than strings, but it's still quite useful for messaging commands:
echo string...:message {
hook = echo
help = Echoes a message back to you
}
@CommandHook("echo")
public void echo(CommandSender sender, String message) {
sender.sendMessage(message);
}
Now, if this command is run as echo Hello world!
, the entire string Hello world!
will be passed as a single argument instead of being treated as two.
There are still more ways to use arguments. Next, learn about Custom Argument Types.