repositories {
maven ( "https://repo.bluecolored.de/releases" )
}
dependencies {
implementation("de.bluecolored.bluecommands:bluecommands-core:1.1.3")
implementation("de.bluecolored.bluecommands:bluecommands-brigadier:1.1.3") // Optional
}
class MyCommands {
private Command<CommandSender, Object> commands;
public MyCommands() {
BlueCommands<CommandSender> commandFactory = new BlueCommands<>();
this.commands = commandFactory.createCommand(this);
}
public void runCommand(CommandSender sender, String input) {
// parse the command
ParseResult<CommandSender, Object> parseResult = this.commands.parse(sender, new InputReader(input));
// get the match with the highest priority
ParseMatch<CommandSender, Object> match = parseResult.getMatches().stream()
.max(Comparator.comparing(ParseMatch::getPriority))
.orElse(null);
if (match == null) {
// handle no command found
return;
}
// execute the command (the result is whatever the command-method returns)
Object executionResult = match.execute();
}
@Command("foo <arg1> [optionalArg2]")
public void fooCommand(
CommandSender sender,
@Argument("arg1") String stringArgument,
@Argument("optionalArg2") Double optionalDoubleArgument
) {
// do something
}
}
Example here for creating an argument parser which accepts online Bukkit-Players:
public class PlayerArgument<S> extends SimpleArgumentParser<S, Player> {
public PlayerArgument() {
super(false, false);
}
@Override
public Player parse(S context, String name) throws CommandParseException {
Player player = Bukkit.getPlayerExact(name);
if (player == null) {
throw new CommandParseException("'" + name + "' is not an online player!");
}
return player;
}
@Override
public List<Suggestion> suggest(S context, InputReader input) {
return Bukkit.getOnlinePlayers().stream()
.map(player -> (Suggestion) new SimpleSuggestion(player.getName()))
.toList();
}
}
Then register the new Parser before creating your commands:
BlueCommands<CommandSender> commandFactory = new BlueCommands<>();
// register the custom argument-parser
commandFactory.setArgumentParserForArgumentType(Player.class, new PlayerArgument<>());
this.commands = commandFactory.createCommand(this);
With context-resolvers you can add other parameters to your command-method that should be resolved from the context.
BlueCommands<CommandSender> commandFactory = new BlueCommands<>();
commandFactory.setContextResolverForType(Server.class, CommandSender::getServer);
Then in a command you can add a Server
parameter which will be filled based on the current command-context:
@Command("foo <arg1> [optionalArg2]")
public void fooCommand(
Server server,
@Argument("arg1") String stringArgument,
@Argument("optionalArg2") Double optionalDoubleArgument
) {
// ...
}
Here an example to create a Permission annotation and use it to validate commands for a context.
Create the new Annotation:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
String value();
}
Label your commands with this new annotation:
@Command("foo <arg1> [optionalArg2]")
@Permission("foo.bar.bazz")
public void fooCommand(
CommandSender sender,
@Argument("arg1") String stringArgument,
@Argument("optionalArg2") Double optionalDoubleArgument
) {
// ...
}
Register a context-predicate for this Annotation:
BlueCommands<CommandSender> commandFactory = new BlueCommands<>();
commandFactory.setAnnotationContextPredicate(Permission.class, (permission, commandSender) -> {
return commandSender.hasPermission(permission.value());
});
When the annotation is present, the command will now only be available if the registered predicate returns true
.
You can merge multiple commands into one. E.g. if you have multiple objects that hold command-methods:
BlueCommands<CommandSender> commandFactory = new BlueCommands<>();
Command<CommandSender, Object> root = new Command<>();
root.tryMerge(commandFactory.createCommand(object1));
root.tryMerge(commandFactory.createCommand(object2));
root.tryMerge(commandFactory.createCommand(object3));