Commands Quick Start
Prerequisites
- The plugin declares a runtime dependency on BetterPlugin (
dependinplugin.yml) - Call it in
onEnable();thisis the current plugin instance (eitherJavaPluginorPluginBaseworks) - Call
register()beforeLifecycleEvents.COMMANDSfires — that means duringonEnable()
Required Imports for the Examples
java
import org.bukkit.plugin.java.JavaPlugin;
import org.coffeepop.betterPlugin.api.command.CommandBuilder;
import io.papermc.paper.command.brigadier.Commands; // Required for the subcommand example
import java.time.Duration; // Required for the cooldown example
import java.util.List; // Required for the completion exampleMinimal Command
java
CommandBuilder.create(this)
.name("ping")
.executes((sender, command, label, args) -> {
sender.sendPlainMessage("pong");
return true;
})
.register();Common Configuration
java
CommandBuilder.create(this)
.name("greet")
.permission("myplugin.greet")
.aliases("hello")
.description("Greets the sender")
.executes((sender, command, label, args) -> {
sender.sendPlainMessage("Hello, " + sender.getName() + "!");
return true;
})
.register();
.usage()and.permissionMessage()are only metadata on the callback parametercommandfor now; they don't affect the command registration result. See API Reference for details.
Completion, Restrictions, and Cooldown
java
CommandBuilder.create(this)
.name("feed")
.playerOnly()
.cooldown(Duration.ofSeconds(30))
.executes((sender, command, label, args) -> {
sender.sendPlainMessage("You are full");
return true;
})
.register();
CommandBuilder.create(this)
.name("give")
.executes((sender, command, label, args) -> true)
.tabCompleter((sender, command, alias, args) ->
args.length == 1 ? List.of("diamond", "iron", "gold") : List.of())
.register();Subcommands
Subcommands must keep the parent command's executor, otherwise register() throws CommandException because validation fails:
java
CommandBuilder.create(this)
.name("admin")
.permission("myplugin.admin")
.executes((sender, command, label, args) -> {
sender.sendPlainMessage("Usage: /admin <reload|status>");
return true;
})
.then(Commands.literal("reload")
.executes(ctx -> {
ctx.getSource().getSender().sendPlainMessage("reloaded!");
return 1;
}))
.register();Note: after you add
.then(...)child nodes,.tabCompleter(...)is ignored. The parent command's.cooldown(...)also applies only to the parent execution path; child nodes are not affected.
For more options, see API Reference; for complete examples, see Examples.