26 February 2021

SimpleCommandExecutor is a simple API for declaring commands using a fluid builder pattern. This project is best suited for commands with advanced functionality, especially those that use subcommands.

This project is licensed under the GLPv3. Source code can be found on my GitLab repository.



Install into project

In your pom.xml add the following repository and dependency.


Defining a command

To define a command, we need to know the following:

  • Command name

  • List of subcommands

  • List of arguments for each subcommand

For this example, we’ll use the /shape command with two subcommands: sphere and cube.

The cube subcommand will have explicit parameters turned off, meaning that we’ll have to call it like this:

/shape cube 21 empty yellow

The sphere subcommand will have explicit parameters turned on. It will allow to specify the parameters in any order we like, with the added downside of writing each parameter’s name. The auto-complete functionality helps a lot here. It also supports omitting arguments if there is a default value.

/shape sphere -radius 10 -density 23.5 (1)
/shape sphere -density 40.1, -radius 3 (2)
/shape sphere -density 2.1 (3)
/shape sphere (4)
1 Radius 10, Density 23.5
2 Radius 3, Density 40.1
3 Radius 1, Density 2.1
4 Radius 1, Density 1.0

The code

First we need to create a builder for our command and give it a name. Then, we list the subcommands with their respective parameters.

public class BasicCommandPlugin extends JavaPlugin {

    public void onEnable() {
        SimpleCommandExecutor executor = SimpleCommandExecutor.build().name("shape")
                .subcommand() (1)
                .name("sphere").explicitParameters(true) (2)
                .parameter("-radius", new IntegerParser(1, () -> IntStream.range(1, 10))) (3)
                .parameter("-density", new DoubleParser(1.0))
                .endSubcommand().subcommand() (4)
                .name("cube").explicitParameters(false) (5)
                .parameter("size", new IntegerParser(1, () -> IntStream.rangeClosed(1, 10))) (6)
                .parameter("fill", new BooleanParser(true, "fill", "empty"))
                .parameter("color", new EnumParser("none",
                    () -> Stream.of("red", "blue", "green", "yellow", "none")))
                .endSubcommand() (7)
                .endCommand(); (8)
        // ...
    // ...
1 Give the first subcommand a name
2 Set a name for the subcommand and turn on explicit parameters
3 List the subcommand’s parameters
4 End the subcommand and start another
5 Set another name for the second subcommand and turn off explicit parameters
6 List parameters for the second subcommand
7 End the second subcommand
8 End the command builder

Activating the command

Now we need to set a handler to receive command executions. For simplicity of this example, we are going to use the plugin class as a handler. For each subcommand, we are going to use the @SubcommandHandler("subcommand") annotation.

The selfInstall method sets this executor for the server command. It can, optionally, overwrite the usage string that is shown to the player when a wrong command format is given. This behaviour is controlled by the second parameter.

public class BasicCommandPlugin extends JavaPlugin {

    public void onEnable() {
        // ...
        executor.setHandler(this, BasicCommandPlugin.class); (1)
        executor.selfInstall(this, true); (2)

    @SubcommandHandler("sphere") (3)
    public void onSphere(CommandSender sender, ParameterMap param) {
        Integer radius = param.get("-radius", Integer.class); (4)
        Double density = param.get("-density", Double.class); (5)
        // Do something

    @SubcommandHandler("cube") (6)
    public void onCube(CommandSender sender, ParameterMap param) {
        // ...
1 Set the command handler
2 Call selfInstall to activate the handler
3 Annotate handler method for first subcommand
4 Get first parameter
5 Get second parameter
6 Annotate handler method for second subcommand


A paramter is defined by a name and a parser (interface ParameterParser). The parser defines the parameter’s type, default value (in case the user omitted this parameter) and how it is parsed, including possible tab completions.

Currently there are 5 parsers available:

Class name Description Generated type


Parses an integer number



Parses a floating-point number



Parses a boolean value, supports replacing 'true' and 'false' with any strings



Reads a string argument



Allows choice between a list of strings


This website is open-source. The source code is available on my GitLab repository

© 2021 | Mixed with Bootstrap v5.0.0 | Baked with JBake v2.6.7