Skip to content

权限系统

文档版本:基于 2026-06-01 代码分析

概述

逃走中MOD的权限系统采用三层等级体系,通过 NfaPermissionService 统一提供权限查询与修改服务。核心特性包括主控互斥(同时最多一个 MASTER_ADMIN)、引导期机制(无主控时 OP 玩家可设首任主控)和命令方块无条件最高权限

权限系统与玩家身份系统完全解耦,独立持久化于 PersistentNfaPermissionSavedData


核心概念

三层权限等级

等级ordinalid 字符串含义
MASTER_ADMIN0(最高)"master_admin"唯一主控管理员,可修改他人权限
GAME_ADMIN1"game_admin"游戏管理员,可管理游戏流程
PLAYER2(默认)"player"普通玩家

权限比较使用 ordinal() 大小:MASTER_ADMIN.isAtLeast(GAME_ADMIN)0 <= 1true

引导期(Bootstrap Phase)

当服务器中没有 MASTER_ADMIN 时进入引导期:

  • OP 玩家(level >= 2)临时获得 GAME_ADMIN 权限
  • OP 玩家可通过 /nfa permission set 设置首任主控
  • 首任主控设置后引导期自动退出

主控互斥

设置新 MASTER_ADMIN 时旧主控自动降级为 GAME_ADMIN。降级当前主控时 masterAdminUuid 置 null,系统重新进入引导期。


架构设计

权限检查流程图

mermaid
flowchart TD
    A[CommandSourceStack 来源] --> B{来源类型?}
    B -->|命令方块/控制台| C[返回 MASTER_ADMIN<br/>无条件通过]
    B -->|玩家| D{PersistentNfaPermissionSavedData<br/>getLevel uuid}
    D -->|存储等级 != PLAYER| E[返回存储等级]
    D -->|存储等级 == PLAYER| F{引导期?<br/>hasMasterAdmin == false?}
    F -->|是 且 OP| G[返回 GAME_ADMIN<br/>临时权限]
    F -->|否| H[返回 PLAYER]

    E --> I{谓词检查<br/>isAtLeast 阈值?}
    G --> I
    H --> I
    C --> I

    I -->|true| J[指令可执行]
    I -->|false| K[指令不可见/不可执行]

权限设置守卫流程

mermaid
flowchart TD
    A[canManagePermissions<br/>server, data, caller] --> B{caller 类型?}
    B -->|null 系统调用| C[通过]
    B -->|玩家| D{引导期?}
    D -->|是 且 OP| E[通过<br/>允许设置首任主控]
    D -->|否| F{caller == masterAdminUuid?}
    F -->|是| G[通过<br/>当前主控可修改]
    F -->|否| H[拒绝]

关键文件

文件说明
com/chenxi/chenxi_rfm/common/permission/NfaPermissionLevel.java三层权限等级枚举
com/chenxi/chenxi_rfm/common/permission/NfaPermissionApi.java对外稳定公开 API 层
com/chenxi/chenxi_rfm/server/permission/NfaPermissionService.java权限服务核心(全部静态方法)
com/chenxi/chenxi_rfm/server/config/rfm/PersistentNfaPermissionSavedData.java权限持久化存储(NBT)
com/chenxi/chenxi_rfm/server/command/NfaCommandPredicates.java7 种权限谓词定义
com/chenxi/chenxi_rfm/server/command/permission/PermissionSetCommand.java/nfa permission set
com/chenxi/chenxi_rfm/common/network/payload/permission/SyncPermissionLevelPayload.java权限同步网络包
com/chenxi/chenxi_rfm/common/network/handler/permission/PermissionPayloadHandler.java客户端权限状态更新
com/chenxi/chenxi_rfm/client/permission/NfaPermissionClientState.java客户端权限缓存(仅 UI 控制)

关键流程

7 种权限谓词

谓词最低权限命令方块/控制台典型应用
MASTER_OR_CBMASTER_ADMIN通过/nfa basic, /nfa rfm coin
MASTER_PLAYER_ONLYMASTER_ADMIN拒绝/nfa rfm hub
GAME_ADMIN_OR_CBGAME_ADMIN通过/nfa reload, /nfa rfm box
GAME_ADMIN_PLAYER_ONLYGAME_ADMIN拒绝/nfa rfm manager, /nfa rfm identity
PLAYER_ONLY任何玩家拒绝/nfa phone hand_id
ANYONE通过未使用
PERMISSION_SET特殊拒绝/nfa permission set

PERMISSION_SET 的特殊逻辑

  • MASTER_ADMIN 玩家 → 通过
  • 引导期 + OP → 通过
  • 其他 → 拒绝

二级权限检查(二次守卫)

RfmIdentityCommandRfmHunterTypeCommand 采用双层设计:

  • 父级挂载 GAME_ADMIN_PLAYER_ONLY —— GAME_ADMIN 可查看
  • 写操作内部检查 isAtLeast(MASTER_ADMIN) —— 仅 MASTER_ADMIN 可修改

权限变更同步

PermissionSetCommand.setPermission()
  → NfaPermissionService.setPermission()
  → PersistentNfaPermissionSavedData.setLevel()
  → setDirty()
  → PacketDistributor.sendToPlayer(target, SyncPermissionLevelPayload)
  → PermissionPayloadHandler.handleSyncPermissionLevel()
  → NfaPermissionClientState.update(level)

客户端的 NfaPermissionClientState 仅用于 UI 显隐控制,所有实际操作在服务端二次验证。


数据持久化

PersistentNfaPermissionSavedData

文件:<world>/data/nfa_rfm/nfa_permission_data.dat

json
{
  "MasterAdminUuid": "550e8400-...",
  "Permissions": [
    { "Uuid": "660e8400-...", "Level": "game_admin" }
  ]
}

存储策略

  • 仅存储非 PLAYER 等级,减少数据体积
  • MasterAdminUuid 为 null 表示无主控(引导期)
  • setLevel() 方法内置主控互斥逻辑

注意事项 / 限制

  1. 命令方块无条件最高权限resolveCommandSourceLevel() 对非玩家源直接返回 MASTER_ADMIN,数据包/命令方块不受任何权限限制。
  2. 客户端权限不可信NfaPermissionClientState 仅用于 UI,所有权限判断在服务端执行。
  3. 主控互斥是硬性的:同一时间有且仅有一个 MASTER_ADMIN。设新主控会自动降级旧主控。
  4. 引导期可逆:降级当前主控后 masterAdminUuid 置 null,系统重新进入引导期。
  5. 外部 API 稳定NfaPermissionApi 位于 common 包,可供扩展模组引用。
  6. PLAYER 不持久化:默认 PLAYER 等级不写入 NBT,加载时自动返回 PLAYER。

相关文档