Appearance
指令总览
文档版本:基于 2026-06-01 代码分析
概述
逃走中MOD使用 Minecraft Brigadier 框架构建指令系统,以 /nfa 为唯一根指令,下设 6 个一级分支,覆盖 reload、permission、phone、basic、test、rfm 六大功能域。指令树包含约 58 个叶子指令,通过 7 种权限谓词 实现细粒度权限控制。
指令注册入口在 ServerCommandEvents.onRegisterCommands() 中,该方法调用 NfaCommand.register(dispatcher) 将完整指令树挂载到 CommandDispatcher。
核心概念
权限等级体系
| 等级 | ordinal | 说明 |
|---|---|---|
| MASTER_ADMIN | 0(最高) | 主控管理员,唯一且互斥 |
| GAME_ADMIN | 1 | 游戏管理员,可管理游戏流程 |
| PLAYER | 2(默认) | 普通玩家 |
权限比较通过 ordinal() 大小判定(ordinal 越小等级越高),方法 isAtLeast(threshold) 使用 ordinal() <= threshold.ordinal() 比较。
7 种权限谓词
定义于
NfaCommandPredicates.java
| 谓词常量 | 最低权限 | 非玩家源(命令方块/控制台) | 用途 |
|---|---|---|---|
MASTER_OR_CB | MASTER_ADMIN | 通过(视为MASTER_ADMIN) | 仅主控+系统可执行 |
MASTER_PLAYER_ONLY | MASTER_ADMIN | 拒绝 | 仅主控玩家可执行 |
GAME_ADMIN_OR_CB | GAME_ADMIN | 通过(视为MASTER_ADMIN) | 管理员+系统可执行 |
GAME_ADMIN_PLAYER_ONLY | GAME_ADMIN | 拒绝 | 仅管理员玩家可执行 |
PLAYER_ONLY | 不限(只需在线玩家) | 拒绝 | 任何玩家可执行 |
ANYONE | 无(所有人) | 通过 | 无限制 |
PERMISSION_SET | 特殊规则 | 拒绝 | 见下方说明 |
PERMISSION_SET 的特殊逻辑:
- 非玩家源 → 拒绝
- MASTER_ADMIN 玩家 → 通过
- 引导期(系统中无主控)+ 玩家是 OP(level >= 2)→ 通过
- 其他情况 → 拒绝
二级权限检查(二次守卫)
RfmIdentityCommand 和 RfmHunterTypeCommand 采用双层权限设计:
- 父级挂载
GAME_ADMIN_PLAYER_ONLY—— GAME_ADMIN 即可进入菜单查看 - 执行写操作时内部二次检查
isAtLeast(MASTER_ADMIN)—— 仅 MASTER_ADMIN 可修改
命令方块/数据包执行
当执行源为命令方块或控制台时(source.getEntity() == null 或不是 ServerPlayer),resolveCommandSourceLevel() 方法直接返回 MASTER_ADMIN,即命令方块/控制台拥有无条件最高权限。
架构设计
完整指令树
mermaid
graph TD
NFA["/nfa"] --> RELOAD["reload<br/>(>=GAME_ADMIN)"]
NFA --> PERM["permission<br/>(PERMISSION_SET)"]
NFA --> PHONE["phone<br/>(各子指令独立)"]
NFA --> BASIC["basic<br/>(>=MASTER_ADMIN 或 CB)"]
NFA --> TEST["test<br/>(>=MASTER_ADMIN 或 CB)"]
NFA --> RFM["rfm<br/>(各子指令独立)"]
PERM --> PERM_SET["set target level"]
PHONE --> PH_HAND["hand_id<br/>(玩家)"]
PHONE --> PH_RATE["rate value<br/>(玩家)"]
PHONE --> PH_CLEAN["clean target<br/>(>=GAME_ADMIN)"]
PHONE --> PH_CLR["clear_call_history<br/>(>=GAME_ADMIN)"]
PHONE --> PH_LIST["list target<br/>(>=GAME_ADMIN)"]
PHONE --> PH_DEL["del target phone_id<br/>(>=GAME_ADMIN)"]
BASIC --> BS_START["start"]
BASIC --> BS_PAUSE["pause"]
BASIC --> BS_RESUME["resume"]
BASIC --> BS_STOP["stop"]
TEST --> T_RING_START["ring start"]
TEST --> T_RING_STOP["ring stop"]
RFM --> R_MGR["manager<br/>(>=GAME_ADMIN 玩家)"]
RFM --> R_NOTICE["notice clear<br/>(>=MASTER_ADMIN)"]
RFM --> R_HUB["hub<br/>(>=MASTER_ADMIN 玩家)"]
RFM --> R_PRISON["prison<br/>(>=GAME_ADMIN 玩家)"]
RFM --> R_COIN["coin<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_BOX["box<br/>(>=GAME_ADMIN 或 CB)"]
RFM --> R_BOXLOCK["boxlock<br/>(>=GAME_ADMIN 或 CB)"]
RFM --> R_ROUND["round<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_DETECT["detect<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_ALARM["alarm<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_TRACK["track<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_HSPAWN["hunterspawn<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_HTYPE["huntertype<br/>(>=GAME_ADMIN 玩家+内部MASTER)"]
RFM --> R_HENTITY["hunterentity<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_RES["resurrect<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_ABSTAIN["abstain<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_ID["identity<br/>(>=GAME_ADMIN 玩家+内部MASTER)"]
RFM --> R_TRAITOR["traitor<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_TW["titlewriter<br/>(>=MASTER_ADMIN 或 CB)"]
RFM --> R_PAIR["pairing<br/>(>=MASTER_ADMIN 或 CB)"]
style NFA fill:#1a1a2e,stroke:#e94560,color:#fff
style RELOAD fill:#16213e,stroke:#0f3460,color:#fff
style PERM fill:#16213e,stroke:#0f3460,color:#fff
style PHONE fill:#16213e,stroke:#0f3460,color:#fff
style BASIC fill:#16213e,stroke:#0f3460,color:#fff
style TEST fill:#16213e,stroke:#0f3460,color:#fff
style RFM fill:#16213e,stroke:#0f3460,color:#fff关键文件
| 文件 | 说明 |
|---|---|
com/chenxi/chenxi_rfm/server/command/NfaCommand.java | 根指令注册类,注册 /nfa 和所有 6 个一级子指令 |
com/chenxi/chenxi_rfm/server/command/NfaCommandPredicates.java | 7 种权限谓词定义 |
com/chenxi/chenxi_rfm/server/command/NfaCommandMessages.java | 统一的 [NFA] 前缀消息广播系统 |
com/chenxi/chenxi_rfm/server/command/NfaReloadCommand.java | reload 指令实现 |
com/chenxi/chenxi_rfm/server/event/ServerCommandEvents.java | 指令注册事件入口 |
com/chenxi/chenxi_rfm/server/permission/NfaPermissionService.java | 权限服务(resolveCommandSourceLevel) |
com/chenxi/chenxi_rfm/common/permission/NfaPermissionLevel.java | 权限等级枚举 |
网络包
NfaCommandMessages 消息工具
NfaCommandMessages 提供统一的指令反馈消息广播,不使用原版 sendCommandFeedback,而是通过聊天栏向玩家输出彩色文本组件。
广播目标枚举 FeedbackTarget:
| 枚举值 | 行为 |
|---|---|
SELF | 仅发送给执行者 |
ALL_ADMINS | 发送给执行者 + 所有在线且 >= GAME_ADMIN 权限的玩家 |
ALL | 发送给所有在线玩家 |
消息方法(各有 FeedbackTarget 参数版本,默认为 ALL_ADMINS):
| 方法 | 颜色 | 格式 |
|---|---|---|
info(source, text) | 绿色 | [NFA] text |
warn(source, text) | 黄色 | [NFA] text |
error(source, text) | 红色 | [NFA] text |
完整指令详解
所有 ~100 个指令的完整参数、权限、反馈消息格式和实现类名,见 指令详解。
数据持久化
指令系统的反馈消息不持久化。权限系统的修改通过 PersistentNfaPermissionSavedData 持久化,配置修改通过 ConfigManager 持久化。详见:
注意事项 / 限制
- 不使用 sendCommandFeedback:所有指令反馈通过
NfaCommandMessages向聊天栏输出[NFA]前缀的彩色文本组件,不受sendCommandFeedback游戏规则限制。 - 命令方块无条件最高权限:
resolveCommandSourceLevel()对非玩家源直接返回MASTER_ADMIN,确保数据包和命令方块不受权限限制。 - 主控互斥:
MASTER_ADMIN是唯一且互斥的——系统中同时最多只能有一个主控管理员。 - 引导期机制:当系统中尚无主控时(引导期),OP 玩家(level >= 2)可临时获得
GAME_ADMIN权限并通过PERMISSION_SET设置首个主控。 - 各指令类独立:每种指令攥写到单独的类中(如
RfmCoinAddCommand.java),在NfaCommand总指令类中统一注册。新增指令时需在对应容器 Command 中注册。 - 权限继承:子指令通常继承父级
.requires()的权限约束,除非子指令显式覆盖。例如rfm根未设.requires(),但各子节点独立设置。