命令 API 参考
命令 API 位于 org.coffeepop.betterPlugin.api.command 包,入口是 CommandBuilder。
示例所需 import
java
import org.bukkit.plugin.java.JavaPlugin;
import org.coffeepop.betterPlugin.api.command.CommandBuilder;
import io.papermc.paper.command.brigadier.Commands; // 子命令示例需要
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import java.time.Duration; // 冷却示例需要
import java.util.List; // 补全示例需要工厂方法
create()
创建命令 Builder,命令默认归属于 BetterPlugin。
java
CommandBuilder builder = CommandBuilder.create();第三方插件请改用 create(this) 或 .plugin(this),避免命令挂到 BetterPlugin 名下。
create(JavaPlugin plugin)
创建命令 Builder,命令归属于指定插件。
java
CommandBuilder builder = CommandBuilder.create(this);方法速查
| 方法 | 类型 | 说明 |
|---|---|---|
name(String name) | 配置 | 设置命令名 |
permission(String permission) | 配置 | 设置所需权限 |
aliases(String... aliases) | 配置 | 设置命令别名 |
plugin(JavaPlugin plugin) | 配置 | 设置命令归属插件 |
description(String description) | 配置 | 设置命令描述 |
usage(String usage) | 配置 | 设置 usage 元数据(只有回调参数 command 能读,不影响 Paper 命令注册) |
permissionMessage(String message) | 配置 | 设置缺少权限时发送的提示 |
playerOnly() | 配置 | 仅玩家可执行 |
consoleOnly() | 配置 | 仅控制台可执行 |
cooldown(Duration duration) | 配置 | 设置根命令的玩家冷却 |
cooldownMessage(String message) | 配置 | 设置冷却提示(默认固定英文) |
argument(String name, ArgumentType type) | 配置 | 添加一个带类型的参数 |
suggestions(String... values) | 配置 | 给最近的参数添加静态补全 |
suggestOnlinePlayers() | 配置 | 给最近的参数添加在线玩家名补全 |
suggest(Function) | 配置 | 根据命令发送者动态计算补全 |
optional() | 配置 | 让最近的参数变为可选(必须是最后一个参数) |
then(ArgumentBuilder) | 配置 | 添加子命令/子节点(添加后 tabCompleter 不生效) |
context(CommandContext) | 执行器 | 复用已有 Brigadier Context 中的 Command |
executes(Command) | 执行器 | 设置 Brigadier 执行器 |
executes(CommandExecutor) | 执行器 | 设置 Bukkit 执行器 |
arguments(CommandArgumentsExecutor) | 执行器 | 设置接收类型化参数的执行器 |
placeholder(String key, Function) | 配置 | 注册自定义消息占位符 |
messageFormatter(BiFunction) | 配置 | 完全替换默认消息格式化 |
tabCompleter(TabCompleter) | 配置 | 设置 Tab 补全(无子节点时生效) |
register() | 动作 | 校验并登记命令(真正注册发生在 COMMANDS 事件) |
执行器
executes(CommandExecutor)
Bukkit 风格执行器,适合大多数场景:
java
CommandBuilder.create(this)
.name("ping")
.executes((sender, command, label, args) -> {
sender.sendPlainMessage("pong");
return true;
})
.register();executes(Command<CommandSourceStack>)
底层 Brigadier 执行器:
java
CommandBuilder.create(this)
.name("raw")
.executes(ctx -> {
ctx.getSource().getSender().sendPlainMessage("raw");
return 1;
})
.register();context(CommandContext<CommandSourceStack>)
复用某个已解析上下文中的 Brigadier Command,属于高级用法。可用的 CommandContext<CommandSourceStack> 通常来自 CommandDispatcher.parse(...).getContext().build(...);绝大多数场景直接使用上面两种 executes 即可。
java
// someContext 来自已解析的 Brigadier 上下文,例如
// dispatcher.parse("...", source).getContext().build("...")
CommandBuilder.create(this)
.context(someContext)
.register();返回值语义
- Bukkit 风格执行器返回
boolean:true映射为成功(Command.SINGLE_SUCCESS,即1),false映射为失败(0) - Brigadier 执行器直接返回
int:1为成功、0为失败
优先级
如果同时设置了多个执行器,生效顺序为:context > executes(Command) > executes(CommandExecutor)。不建议混用。
类型化参数
用 argument(...) 声明参数,再用 arguments(...) 处理:
java
CommandBuilder.create(this)
.name("give")
.argument("player", StringArgumentType.word())
.suggestOnlinePlayers()
.argument("amount", IntegerArgumentType.integer(1))
.arguments((sender, command, label, args) -> {
String player = args.getString("player");
int amount = args.getInt("amount");
sender.sendPlainMessage("给了 " + player + " " + amount + " 个");
return true;
})
.register();suggestions(...)给最近的参数添加静态补全suggest(provider)根据命令发送者动态计算补全suggestOnlinePlayers()自动补全在线玩家名optional()让最近的参数变为可选;args.contains("name")判断是否提供CommandArguments提供getString、getInt、getDouble、getBoolean、contains
消息格式化
冷却和权限提示支持占位符:
java
CommandBuilder.create(this)
.name("pay")
.permission("myplugin.pay")
.permissionMessage("{prefix} 你没有权限使用这个命令")
.cooldown(Duration.ofSeconds(10))
.cooldownMessage("{prefix} 请等待 {cooldown} 秒")
.placeholder("prefix", sender -> getConfig().getString("message-prefix", "[MyPlugin] "))
.executes(...)
.register();- 内置占位符包括
{player}和{cooldown}(仅冷却消息) .placeholder(key, resolver)注册或覆盖占位符;resolver 接收命令发送者.messageFormatter((template, sender) -> ...)完全替换默认格式化
Tab 补全
java
.tabCompleter((sender, command, alias, args) -> List.of("a", "b"))command是轻量Command适配器,非nullalias是用户输入的命令别名args是当前参数数组- 添加
.then(...)子节点后,.tabCompleter(...)会被忽略;子节点补全请使用 Brigadier 自身的suggests/ 参数类型
命令限制
playerOnly()
仅 Player 可执行:
java
CommandBuilder.create(this)
.playerOnly()
.executes((sender, command, label, args) -> {
// sender 一定是 Player
return true;
})
.register();consoleOnly()
仅控制台可执行:
java
CommandBuilder.create(this)
.consoleOnly()
.executes((sender, command, label, args) -> true)
.register();限制条件会叠加:同时设置多个条件时,发送者必须全部满足。例如
permission(...)加playerOnly()表示“有权限的玩家”。playerOnly()与consoleOnly()不要同时设置,否则所有发送者都被拒绝。
冷却
java
CommandBuilder.create(this)
.cooldown(Duration.ofSeconds(60))
.executes((sender, command, label, args) -> true)
.register();- 冷却仅对
Player生效 - 冷却只作用于根命令执行路径;
.then(...)添加的子命令使用自己的执行器,不受该冷却影响 - 冷却期间命令返回失败(Bukkit 风格相当于
false),执行器不会执行,并向玩家发送冷却提示(默认:"Please wait before using this command again.")
子命令
子命令必须保留父命令执行器:
java
CommandBuilder.create(this)
.name("parent")
.executes((sender, command, label, args) -> true)
.then(Commands.literal("sub")
.executes(ctx -> 1))
.register();校验规则
调用 register() 时:
- 命令名不能为
null或空白 - 别名不能为
null、空白,也不能与命令名相同 - 必须设置
context、executes(Command)、executes(CommandExecutor)之一 - 使用
context时,其中必须包含执行器 - 同一个 builder 不能注册两次
否则抛出 CommandException。
已知限制
usage目前只作为元数据挂在Command适配器上(可通过执行器 / 补全回调的command参数读取),不参与 Paper 的 Brigadier 注册permissionMessage会在发送者缺少所需权限时发送,同时也会暴露在Command适配器上tabCompleter与then同时设置时:有子节点则 Bukkit 补全被忽略- 冷却只包裹根执行路径,子命令会绕过冷却
- 冷却提示默认是固定英文,可用
cooldownMessage(String)修改 register()只能在LifecycleEvents.COMMANDS之前调用(即onEnable()阶段),之后调用会记录警告且不会生效