| .idea | ||
| kencommandapi-bukkit | ||
| kencommandapi-core | ||
| kencommandapi-velocity | ||
| third_party | ||
| .bazelrc | ||
| .gitignore | ||
| MODULE.bazel | ||
| README.md | ||
Build
after installing bazel:
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 <user>:
- feed is the root literal
<user>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.
literal:coins/balance
- has argument:user
- has executor:getCoins
As code
/**
* 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<User> rootLiteral;
private final CommandArgumentSpec<User, User> userArg;
public CoinsCommand() {
userArg = CommandArgumentSpec.builder("user", new UserArgumentType<User>())
.withRequirement(p -> !p.hasPermission("economy.immune.getcoins"),
"you can't see that player's balance")
.withDefaultValue(CommandContext::getSender)
.build();
rootLiteral = Literal.<User>builder("coins", "balance")
.withStyle(MessageStyle.PLAIN)
.withPermission("economy.command.coins")
.withArgument(userArg)
.withSyncExecutor(this::getCoins)
.build();
}
private Result<Object, String> getCoins(CommandContext<User> 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.
CommandAPI api = new CommandAPI();
register(new CoinsCommand().getRootLiteral());