命令执行器
命令是玩家在聊天框输入的、以 / 开头的字符串,用来触发功能。注册命令后,玩家敲 /你的命令 就能调用插件逻辑。
命令的结构
一个命令字符串按空格切分:
/give Steve diamond 3- 命令名:
give - 参数数组
args:args[0]="Steve"、args[1]="diamond"、args[2]="3"
在 plugin.yml 注册命令
定义命令第一步是在 plugin.yml 声明:
yml
name: HelloWorld
main: tdiant.helloworld.HelloWorld
version: 1
commands:
rua:
description: RUA!RUA!RUA!
aliases: [hi, hello]
permission: helloworld.use
permission-message: "你没有权限!"
usage: "/<command> <玩家名>"plugin.yml 别写中文
plugin.yml 里出现中文容易出问题。提示语、用法都建议用英文,权限判断的提示在代码里自己处理(见下)。
commands 的子键
| 键 | 用途 |
|---|---|
description | 描述,显示在 /help |
aliases | 别名数组,如 [l, log] |
permission | 所需权限 |
permission-message | 无权限时的提示 |
usage | 用法说明 |
不推荐用 plugin.yml 的 permission
plugin.yml 里中文易出问题,且权限控制不够灵活。推荐在代码里用 player.hasPermission(...) 自己判断(见下)。
CommandExecutor 处理命令
类似监听器,命令处理也用一个接口——CommandExecutor。最简单的方式是让主类实现它:
java
public class HelloWorld extends JavaPlugin implements CommandExecutor {
@Override
public void onEnable() {
// 把 rua 命令的处理者设为本类
getCommand("rua").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("只有玩家能用这个命令!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
player.sendMessage(ChatColor.RED + "用法:/rua <玩家名>");
return false; // 返回 false 会显示 plugin.yml 里的 usage
}
// 权限判断
if (!player.hasPermission("helloworld.use")) {
player.sendMessage(ChatColor.RED + "你没有权限!");
return true;
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
player.sendMessage(ChatColor.RED + "玩家不在线或不存在");
return true;
}
target.sendMessage(ChatColor.GOLD + player.getName() + " 对你 RUA 了!");
return true;
}
}参数说明
| 参数 | 含义 |
|---|---|
sender | 命令发送者(玩家/控制台/命令方块),用 CommandSender 统一表示 |
command | 命令对象 |
label | 实际使用的命令名(可能是别名) |
args | 参数数组 |
返回值
- 返回
true:命令执行成功 - 返回
false:用法错误,服务端会显示plugin.yml里的usage
区分"用法错误"和"业务失败"
参数缺失、格式不对 → 返回 false(让用户看用法)。业务逻辑失败(如玩家不在线)→ 自己发提示、返回 true(别再弹 usage,否则刷屏)。
拆分到单独的类
主类实现 CommandExecutor 适合小插件。大了就拆:
java
public class RuaCommand implements CommandExecutor {
private final HelloWorld plugin;
public RuaCommand(HelloWorld plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
// ... 逻辑
return true;
}
}注册:
java
getCommand("rua").setExecutor(new RuaCommand(this));Tab 自动补全
实现 TabCompleter 让玩家输命令时按 Tab 能补全参数:
java
public class RuaTabCompleter implements TabCompleter {
@Override
public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
if (args.length == 1) {
// 补全在线玩家名
List<String> names = new ArrayList<>();
for (Player p : Bukkit.getOnlinePlayers()) {
if (p.getName().toLowerCase().startsWith(args[0].toLowerCase())) {
names.add(p.getName());
}
}
return names;
}
return Collections.emptyList();
}
}注册:
java
getCommand("rua").setTabCompleter(new RuaTabCompleter());返回空列表而非 null
没补全内容时返回 Collections.emptyList(),别返回 null——null 会让服务端回退到默认补全(通常是所有玩家名),可能不是你要的。
至此你掌握了插件四大基础:主类、事件、配置、命令。能写出绝大多数常用插件了。接下来进入进阶内容做更复杂的东西。
