## Build after installing bazel: ```shell bazel build //kencommandapi-bukkit:bukkit bazel build //kencommandapi-core:core ``` can't compile -velocity module yet. ## Limitations & Bugs - argument's can't require specific permissions. - errors are always formatted using the RootLiteral's MessageStyle ## Design Commands are trees of Literals. Literals can have arguments. Literals can also have Executors. arguments can be optional by giving them a default value. arguments can have suggestions. `/feed `: - feed is the root literal - `` is an argument: it's value is a User Object To allow the use of `/feed` without giving a user's name, i.e. to make the argument optional, we need to assign the user-argument a default value. ## An example command Let's say we want to make a command that allows seeing how many coins another User has. If we don't specify a user, it should instead show the coins the sender has. ## As a tree Visualized as a tree, we have a Node/Literal `coins` with an alias `balance` with an optional argument called `user`. To make an argument optional, it must have a default value. ```text literal:coins/balance - has argument:user - has executor:getCoins ``` ## As code ```java /** * Show the amount coins a user has. * If no user is given, it should show the amount the sender of the command has. */ @NoArgsConstructor(access = AccessLevel.NONE) public class CoinsCommand { @Getter private final Literal rootLiteral; private final CommandArgumentSpec userArg; public CoinsCommand() { userArg = CommandArgumentSpec.builder("user", new UserArgumentType()) .withRequirement(p -> !p.hasPermission("economy.immune.getcoins"), "you can't see that player's balance") .withDefaultValue(CommandContext::getSender) .build(); rootLiteral = Literal.builder("coins", "balance") .withStyle(MessageStyle.PLAIN) .withPermission("economy.command.coins") .withArgument(userArg) .withSyncExecutor(this::getCoins) .build(); } private Result getCoins(CommandContext ctx) { var player = ctx.getArg(userArg); ctx.getSender().sendMessage(player.getName() + " has " + player.getCoins() + " coins"); return Results.success(new Object()); } } ``` If we wanted to report an error, we could do for example `return Results.failure("That user doesn't exist")`. However, if we have a smart UserArgumentType, it automatically makes sure that the user exists. Additionally, we can also a Requirement in the CommandArgumentSpec. The registration of the command is platform-dependant. Typically, a class called CommandAPI can be used. ```java CommandAPI api = new CommandAPI(); register(new CoinsCommand().getRootLiteral()); ```