权限

command/TaskNHPermissions.java + command/TaskNHPermissionsSU.java。权限不是用 Forge PermissionAPI,而是可选地桥接 ServerUtilities(modid serverutilities)的 PermissionAPI 做等级(rank)控制。

10 个权限节点

节点常量 节点名 默认等级 对应子命令
LIST tasknh.list ALL list
GUI tasknh.gui ALL gui
OPEN tasknh.open ALL open
CREATE tasknh.create ALL create
ASSIGN tasknh.assign ALL assign
UNASSIGN tasknh.unassign ALL unassign
DONE tasknh.done ALL done
RELOAD tasknh.reload OP reload
IMPORT tasknh.import OP import
EXPORT tasknh.export OP export

isOpByDefault(node) 的实现是 RELOAD.equals(node) || IMPORT.equals(node) || EXPORT.equals(node)——只有这三个节点默认要 OP,其余七个默认全员可用。这三个正是会写文件(export)或改存档(import)、或强制向全服推送(reload)的操作。

describe(node) 生成 ServerUtilities 等级编辑器里显示的说明:"TaskNH: /tasknh " + 节点名点号后的部分,例如 TaskNH: /tasknh import。

检测与桥接

SU_PRESENT = Loader.isModLoaded("serverutilities") 是 static final、只算一次,注释说明「mod set 加载后不再变化」。

  • 有 ServerUtilities —— init() 中对 10 个节点逐个 TaskNHPermissionsSU.registerNode(node, isOpByDefault(node), describe(node)),映射到 DefaultPermissionLevel.OP 或 DefaultPermissionLevel.ALL;检查走 PermissionAPI.hasPermission(player, node),管理员可在等级编辑器里调。
  • 无 ServerUtilities —— registerNodes() 直接 return(空操作);检查时非 OP 节点直接返回 true,OP 节点用 func_152596_g(player.getGameProfile()) 判 OP 身份。类 Javadoc 原文:“Without ServerUtilities, OP-default nodes require OP and ALL-default nodes are open.”

TaskNHPermissionsSU 是唯一的 ServerUtilities 桥接类,其 serverutils.lib.util.permission.* 的 import 只在 SU 存在时才会被加载——类 Javadoc 与文件头注释都强调「Never loaded unless serverutilities is present」,由 Loader.isModLoaded 守卫。

控制台永远放行

if (!(sender instanceof EntityPlayerMP player)) return true; // console

has() 的第一行就短路返回 true——控制台与命令方块跳过所有检查。因此 TaskNHCommand 的 getRequiredPermissionLevel() 返回 0 是安全的:玩家侧的门槛全部由子命令自己把关。

注册时机

TaskNHPermissions.registerNodes() 在 CommonProxy.init() 末尾调用,即 init 阶段(preInit 只做配置加载与网络注册)。节点注册与网络通道初始化分属两个阶段,顺序是:preInit → TaskNHConfig.load + TaskNHNetwork.init;init → 事件监听器 + registerNodes()。