-
Notifications
You must be signed in to change notification settings - Fork 3
Command API: Function based
The same result achieved in the Class-based wiki-page can be obtained using the function-based approach. Specifically, this is useful if you have one node command and many children that belong to it.
For example, say we need to create these commands:
/quake create <arena>
/quake delete <arena>
Then, within any class, we can define them this way. Every command takes a function marked with @AsCommand.
public class QuakeArenaCommands { // Could be any class you'd like.
// ================================================================================
// create <arena>
// ================================================================================
@AsCommand(
description = "Creates a new arena.",
aliases = {"c"},
sender = SenderType.PLAYER
)
// The command name will be the same as the function name.
// - The first parameter must be a CommandSender implementation according to the SenderType.
// - The usage of the command goes from the second parameter onwards.
public void create(Player player, String arena) {
// (...) Does some stuff to actually create the arena...
player.sendMessage(GREEN + "Arena created.");
}
// ================================================================================
// arena delete <arena>
// ================================================================================
@AsCommand(
description = "Deletes an arena."
alaises = {"d", "rm", "remove"},
//sender = SenderType.ALL (by default)
)
public void delete(CommandSender sender, String arena) {
// (...) Does some stuff to delete the arena...
player.sendMessage(GREEN + "Arena removed: " + arena.getId());
}There's no way to create a functional node command, we have keep the QuakeCommand we've created before:
public class QuakeCommand extends NodeCommand {
public QuakeCommand() {
super("quake");
setDescription("The main Quake command.");
//setSenderType(SenderType.ALL);
addAliases("q");
// Appends to the node the list of commands returned by FunctionalCommand#load.
append(FunctionalCommand.load(new QuakeArenaCommands())); // <---
}
}Finally, we have to register QuakeCommand the same as we did before.
There are some commands where a parameter could be optional. For example:
/give <item> <amount> [player]
If the player isn't specified the plugin must assume the player wants to give the item to himself. How do we achieve that with the command-api?
@AsCommand(
description = "Gives the specified item to a player."
sender = SenderType.PLAYER,
)
public void give(Player sender, Material item, int amount, @WithOptional String player) {
if (player == null) {
player = sender.getName();
}
Player target = Bukkit.getPlayer(player);
// (...)
sender.sendMessage(GREEN + "Item sent to: " + target.getName());
if (target != sender) {
sender.sendMessage(GREEN + "You received an item from: " + sender.getName());
}
}If the player isn't specified the plugin sets the optional parameter to the default value.
Using this approach is more powerful than creating classes, here some advantages:
- You don't have to take care of args parsing, the API does it for you. Handling also eventual syntax errors.
- Auto-generates the usage that is displayed by the help command.
- Less verbosity, you don't have to create one class for every command you have.
- Embedded management of tab-complete for parameters.
By itself, Uppercore supports the following types of parameters:
- Primitives: boolean, char, byte, float, double, short, int, long, String, String[].
- Some Bukkit's utils: Color, Enchantment, Material, Sound, Vector
It is also possible to include your own parameter parser.