← Roadmap

EffectiveCommand

Commands

Why

Paper moved to Brigadier, and command registration now goes through lifecycle events in onLoad. Argument completion has to be described separately from execution.

EffectiveCommand registers the command itself and uses one CommandNode tree for both execution and completion: choice is a literal, dynamic a runtime list, executes the action.

Minimal example

Command
object ArenaCommand : EffectiveCommand() {
    override fun getNamespacedData() = MyPlugin.instance to "arena"
    override fun getDescription() = "Arena control"
    override fun getPermission() = "myplugin.arena"

    override fun commandTree() = CommandNode.build {
        choice("start") {
            executes { Arena.start(); sendMessage("started") }
        }
        choice("kick") {
            dynamic({ Bukkit.getOnlinePlayers().map { it.name } }) {
                executes { args -> Bukkit.getPlayer(args[1])?.kick() }
            }
        }
    }

    fun init() {}
}

ArenaCommand.init() is called from onLoad.

What to override

  • getNamespacedData() *
    Plugin and command name
  • getDescription() *
    Description for /help
  • getPermission() *
    Permission; empty string — none
  • commandTree() *
    Argument tree

* required

Pitfalls

  • Created the command in onEnable — it does not exist. onLoad only.
  • executes runs on the deepest matching node; args is the whole argument array from zero.