This page describes the concept of Command Attributes
Command Attributes
Command attributes are objects that enhance the functionality of commands. They come in various forms such as
Arguments
Actions
Properties
Subcommands
Etc.
A command can have an unlimited amount of attributes. To make sure Delegate can distinguish between command attributes, each attribute must have a unique identifier associated with it. Normally, these identifiers are assigned automatically (no intervention needed), but in some cases it is useful for the developer to provide these (as we will see later when arguments are covered).
Chaining Command Attributes
As said previously, a command can have an unlimited amount of attributes assigned to it. When creating a command using Delegate.create() , an implementation of an ICommandBuilder is returned. The implementation of this builder depends on your platform. Different platforms will return different types of builders:
Paper: PaperCommandBuilder
Bukkit: BukkitCommandBuilder
Velocity: VelocityCommandBuilder
...
Fluent Interface
public class DelegateExample extends JavaPlugin implements Listener {
@Override
public void onEnable() {
// Event registration
getServer().getPluginManager().registerEvents(this, this);
// Hook Delegate into the plugin
Delegate.hook(this);
// Create example with sub-commands
Delegate.create("math", "Implementation of a arithmetic operations such as addition and subtraction.")
.withIgnoreNull()
.withSubcommand(new SubcommandDefinition(Delegate.create("+", "Adds two numbers together")
.withFloat("a", "The first number to add")
.withFloat("b", "The second number to add")
.withFunctionAction("addition", (sender, context) -> {
// Get the arguments. On purpose, we're not using type-safe methods,
// to demonstrate that the arguments are in fact of the correct type.
float a = context.find("a");
float b = context.find("b");
// Some command logic
float sum = a + b;
// Since this action is a function, we return a result
// which will be captured by Delegate. The type is
// automatically inferred.
return sum;
})
))
.withSubcommand(new SubcommandDefinition(Delegate.create("-", "Subtracts two numbers from each other")
.withFloat("a", "The first number to subtract")
.withFloat("b", "The second number to subtract")
.withFunctionAction("subtraction", (sender, context) -> {
// Get the arguments. On purpose, we're not using type-safe methods,
// to demonstrate that the arguments are in fact of the correct type.
float a = context.find("a");
float b = context.find("b");
// Some command logic
float difference = a - b;
// Since this action is a function, we return a result
// which will be captured by Delegate. The type is
// automatically inferred.
return difference;
})
))
.build();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onCommand(DelegateCommandEvent event) {
// Get some information from the event such as the sender and the capture.
CommandSender sender = event.getSender();
CommandCapture capture = event.getCapture();
// From the capture, we can get the result returned by a sub-command or action.
// In this case, we retrieve the capture of the most deeply nested sub-command.
// For the example, this is "+" or "-".
//
// Note: If type inference fails, null will be returned!
Float result = capture.getResultOf("subtraction");
// Further processing of the command can be handled.
if (result != null)
sender.sendMessage(Component.text("Result: " + result));
}
}
Please note that this example is drastically overcomplicated. Delegate can achieve the same functionality with cleaner and less nested code. This is example is for illustration purposes only. Please check the second tab for a simplified version of the command.
public class DelegateExample extends JavaPlugin implements Listener {
public void createSimplifiedExample() {
// Create a new Delegate command
Delegate.create("math", "Implementation of a arithmetic operations such as addition and subtraction.")
.withIgnoreNull()
.withString("operation", "The operation to perform.")
.withFloat("a", "The first number to add.")
.withFloat("b", "The second number to add.")
.withAction((sender, context) -> {
String operation = args.context("operation");
float a = context.find("a");
float b = context.find("b");
if (operation.equals("+")) {
sender.sendMessage("Result: %s".formatted(a + b));
} else if (operation.equals("-")) {
sender.sendMessage("Result: %s".formatted(a - b));
} else {
sender.sendMessage("Unknown operation: %s".formatted(operation));
}
})
.build();
}
}
In the next few tutorials, we will go over the four built-in command attributes:
The ICommandBuilder interface follows the design pattern. This is a type of design pattern that allows proper chaining. In the case of Delegate, it is used to chain command attributes. In the next sections, we will build up to the following command (which has been deliberately overcomplicated):