Skip to content

命令系统 (Command API)

EnderRealmServerCore 提供了统一的命令注册系统,支持动态命令注册、权限管理、命令冷却、子命令嵌套和 Tab 补全。

快速开始

获取 CommandAPI

java
CommandAPI cmdApi = EnderRealmServerCore.getCommandAPI();

基本用法

java
cmdApi.createCommand(plugin)
    .name("mycommand")
    .aliases("mc", "mycmd")
    .description("我的命令")
    .permission("myplugin.command")
    .subCommand("help", new HelpCommand())
    .subCommand("reload", new ReloadCommand())
    .defaultExecutor(new HelpCommand())
    .register();

核心概念

SubCommand 接口

所有子命令必须实现 SubCommand 接口:

java
import cn.enderrealm.core.api.command.CommandContext;
import cn.enderrealm.core.api.command.SubCommand;

public class MyCommand implements SubCommand {
    
    @Override
    public void execute(CommandContext context) {
        // 判断是否为玩家
        if (!context.isPlayer()) {
            context.sendMessage("此命令只能由玩家使用");
            return;
        }
        
        // 获取玩家
        Player player = context.getPlayer();
        
        // 获取参数(不包含子命令名)
        String[] args = context.args();
        String firstArg = context.getArg(0);
        
        // 发送消息
        context.sendMessage("Hello!");
        
        // 发送 i18n 消息
        context.sendI18nMessage("my.message.key", player.getName());
    }
    
    @Override
    public List<String> tabComplete(CommandContext context) {
        List<String> completions = new ArrayList<>();
        String[] args = context.args();
        
        if (args.length == 1) {
            completions.add("option1");
            completions.add("option2");
        }
        
        return completions;
    }
}

CommandContext 方法

方法说明
sender()获取 CommandSender
label()获取使用的命令别名
args()获取参数数组(不包含子命令名)
fullArgs()获取完整参数数组
isPlayer()判断是否为玩家
getPlayer()获取玩家实例(非玩家会抛异常)
getPlayerOrNull()获取玩家实例(非玩家返回 null)
sendMessage(String)发送消息
sendI18nMessage(String, Object...)发送 i18n 消息
getArg(int)获取指定索引的参数
getArgCount()获取参数数量
getJoinedArgs(int)获取合并后的参数字符串

高级功能

权限管理

java
// 简单权限
.permission("myplugin.command")

// 完整权限定义
.permission("myplugin.command", "命令描述", PermissionDefault.TRUE)

// 带子权限
.permission("myplugin.admin", "管理命令", PermissionDefault.OP, 
    Map.of("myplugin.admin.reload", true))

命令冷却

java
// 主命令冷却(100 tick = 5秒)
.cooldown(100)

// 子命令独立冷却
.subCommand("daily", cmd -> cmd
    .permission("myplugin.daily")
    .cooldown(400)  // 20秒冷却
    .executor(new DailyCommand())
)

冷却提示使用 i18n key command.cooldown,参数 {0} 为剩余秒数。

子命令嵌套

java
cmdApi.createCommand(plugin)
    .name("server")
    .subCommand("game", game -> game
        .permission("server.game")
        .subCommand("join", new GameJoinCommand())
        .subCommand("quit", new GameQuitCommand())
    )
    .subCommand("admin", admin -> admin
        .permission("server.admin")
        .subCommand("reload", new AdminReloadCommand())
        .subCommand("player", player -> player
            .permission("server.admin.player")
            .subCommand("kick", new KickCommand())
            .subCommand("ban", new BanCommand())
        )
    )
    .register();

命令路径解析示例:

  • /server game join → 匹配 gamejoin
  • /server admin player kick Notch → 匹配 adminplayerkick,args = ["Notch"]

命令别名

java
.aliases("mc", "mycmd", "my")

完整示例

java
public class MyPlugin extends JavaPlugin {
    
    @Override
    public void onEnable() {
        EnderRealmServerCore.getCommandAPI()
            .createCommand(this)
            .name("bw")
            .aliases("bedwars")
            .description("起床战争命令")
            .permission("bedwars.use", "起床战争主命令", PermissionDefault.TRUE)
            .defaultExecutor(new HelpCommand(this))
            .subCommand("help", cmd -> cmd
                .permission("bedwars.help")
                .executor(new HelpCommand(this))
            )
            .subCommand("join", cmd -> cmd
                .permission("bedwars.join")
                .cooldown(100)  // 5秒冷却
                .executor(new JoinCommand(this))
            )
            .subCommand("admin", cmd -> cmd
                .permission("bedwars.admin")
                .executor(new AdminHelpCommand(this))
                .subCommand("reload", sub -> sub
                    .permission("bedwars.admin.reload")
                    .executor(new ReloadCommand(this))
                )
            )
            .register();
    }
}

注意事项

  1. 命令名唯一性:不同插件不能注册相同命令名,会抛出 IllegalArgumentException
  2. 权限冲突:如果 plugin.yml 已定义权限,代码中不会重复注册
  3. 不依赖 plugin.yml:使用此 API 注册的命令不需要在 plugin.yml 中声明
  4. 参数索引context.args() 不包含子命令名,索引从 0 开始

相关类

  • cn.enderrealm.core.api.CommandAPI - 命令 API 接口
  • cn.enderrealm.core.api.command.SubCommand - 子命令接口
  • cn.enderrealm.core.api.command.CommandContext - 命令上下文
  • cn.enderrealm.core.api.command.CommandBuilder - 命令构建器