Skip to content

Thoughts on CommandAPI (from Zachery)

skyezer ✨ edited this page Feb 27, 2021 · 3 revisions

Initial Setup

Read the documentation carefully, because if you're anything like me you'll somehow miss the documentation for the maven repo... Other than that setup was really easy.

Be sure to call CommandAPI's onLoad() and onEnable() methods in your plugin.

Registering Commands

The documentation states that you have to load your commands in the onLoad() method, this is not true, just call CommandAPI.onEnable(plugin) after registering your commands in your plugin's onEnable() method.

NOTE: CommandAPI does not support /reload, you must restart your server to register your commands.

Building Commands

I prefer the builder style rather than class, so that's what I will be using in the example below. Building commands is pretty straight forward - the only issue I ran into was trying to use the lambda function. I did not specify which interface the lambda was meant to use, which can be solved simply defining the interface explicitly:

executesPlayer { player, _ -> }
// into
executesPlayer(PlayerCommandExecutor { player, _ -> })

Subcommands

These are really simple, just call withSubcommand on your command and write the code for your subcommand.

CommandAPICommand("ping")
    .withSubcommand(
        CommandAPICommand("boop").executesPlayer(PlayerCommandExecutor { player, _ -> player.sendMessage("boop!") })
    ).executesPlayer(PlayerCommandExecutor { player, _ -> player.sendMessage("pong!") })

Arguments

This is by far my favorite feature of this API - it does all the syntax highlighting, checks, and tab completion automatically. If there isn't an argument for a given type, you can add one! It's stupid easy... I made this, so I could have tab completion for all of Bukkit's registered commands and filter them if the sender does not have permission to execute them.

Custom Arguments Example
internal fun commandArgument(node: String?): Argument {
    return CustomArgument(node, CustomArgumentParser { input: String ->
        val command = Bukkit.getCommandMap().getCommand(input)
        if (command == null) {
            throw CustomArgumentException(MessageBuilder("Unknown command: ").appendArgInput())
        } else {
            return@CustomArgumentParser command
        }
    }).overrideSuggestions { sender: CommandSender ->
        Bukkit.getCommandMap().knownCommands.filter { sender.hasPermission(it.value.permission.toString()) }.entries.map { it.key }.toTypedArray()
    }
}

Optional Arguments

To create optional arguments, just register the same command with different arguments, as seen in the sell command.

Optional Arguments Example
    CommandAPICommand("sell")
    .withPermission(Constants.Permissions.SELL)
        .withSubcommand(
            commandStub("log", Constants.Permissions.SELL_LOG)
            .executesPlayer(PlayerCommandExecutor { sender, args ->
                // prints first page of sell logs
            })
        )
        .withSubcommand(
            commandStub("log", Constants.Permissions.SELL_LOG)
                .withArguments(IntegerArgument("page"))
                .executesPlayer(PlayerCommandExecutor { sender, args ->
                    // prints specified page of sell logs
                })
        )
        .withSubcommand(
            commandStub("log", Constants.Permissions.SELL_LOG)
                .withArguments(StringArgument("player"))
                .executesPlayer(PlayerCommandExecutor { sender, args ->
                    // prints the first page of a player's sell logs
                })
        )        .withSubcommand(
            commandStub("log", Constants.Permissions.SELL_LOG)
                .withArguments(StringArgument("player"))
                .withArguments(IntegerArgument("page"))
                .executesPlayer(PlayerCommandExecutor { sender, args ->
                    // prints specific page of a player's sell logs
                })
        ).register()

Class Based Commands

These do not work in Kotlin...

This is just documenting my experience with CommandAPI, the actual documentation can be found here, and it is much more useful than this.