指令系统

基本信息

属性 值
指令名 minetweaker
别名 mt、crafttweaker、ct(MineTweakerImplementationAPI.java:653)
权限 仅 OP(MineTweakerImplementationAPI.java:677-684)
注册时机 每次 reload() 时按需注册,已存在则跳过(MineTweakerImplementationAPI.java:649)
注册位置 IServer.addCommand → MCServer.addCommand(api/server/IServer.java:14-16、mc1710/server/MCServer.java:44-48)
1.7.10 底层 net.minecraft.command.ICommand 实现类 MCServer.MCCommand(mc1710/server/MCServer.java:83-149,文件共 193 行)
本模组自带子命令 1 个:help(+ 脚本通过 addMineTweakerCommand 注册的自定义命令)
脚本可注册自定义命令 是,server.addMineTweakerCommand(name, description, function)

/minetweaker 主指令

reload() 内的匿名 ICommandFunction(MineTweakerImplementationAPI.java:656-676)实现分发:

参数 行为 源码行
无参数 回一句 Please provide a command. Use /mt help for more info. :658-659
help 列出所有已注册自定义命令的描述文本(键名先 Arrays.sort 排序) :660-667
其他 在 minetweakerCommands 查找;命中则 command.function.execute(args[1..], player),未命中回 No such minetweaker command available :668-675

注意 help 打印的是每个命令的 description 字符串数组内容,不打印命令名本身。

权限校验由配套的匿名 ICommandValidator(MineTweakerImplementationAPI.java:677-684)完成:

public boolean canExecute(IPlayer player) {
    return server.isOp(player);
}

非 OP 玩家在 Forge 指令层即被拦下,不会进入分发逻辑。isOp 的 1.7.10 实现见 MCServer(mc1710/server/MCServer.java),最终查 Minecraft 服务器的 op 列表。

两种自定义命令注册

API 脚本名 效果 源码行
IServer.addCommand(name, usage, aliases, function, validator, completion) server.addCommand(...) 注册为原版指令,走 CommandHandler,支持别名、权限校验、Tab 补全 IServer.java:14-16
IServer.addMineTweakerCommand(name, usage, function) server.addMineTweakerCommand(...) 注册为 /minetweaker 的子命令 IServer.java:18-19

AbstractServer(api/server/AbstractServer.java:14-17)把 addMineTweakerCommand 声明为 final 并直接转发到 MineTweakerImplementationAPI.addMineTweakerCommand(:710-712),后者包一层 AddMineTweakerCommandAction 存入 minetweakerCommands 静态 Map。

AddMineTweakerCommandAction(MineTweakerImplementationAPI.java:738-772)是 IUndoableAction:apply()(:747-750)仅在键不存在时 put,undo()(:759)是空实现 —— 子命令注册不可撤销,重载后仍留在表里。同名重复注册时 describe()(:762-767)返回空串、describeUndo()(:769-772)返回 "tried to remove command: <name> failed. THIS IS NOT AN ERROR!"(:771)。

回调与校验器类型

三个脚本类型(均在 api/server/):

脚本名 Java 接口 抽象方法 注解
minetweaker.server.ICommandFunction ICommandFunction.java:10 void execute(String[] arguments, IPlayer player) 无 @ZenMethod
minetweaker.server.ICommandValidator ICommandValidator.java boolean canExecute(IPlayer player) —
minetweaker.server.ICommandTabCompletion ICommandTabCompletion.java Tab 补全 —

ICommandFunction.execute 没有 @ZenMethod(ICommandFunction.java:12-14)—— 与 IEventHandle.close() 形成对照,说明并非所有回调都标注了。

内置校验器

api/server/CommandValidators.java 全文提供 1 个:

@ZenClass("minetweaker.server.CommandValidators")
public class CommandValidators {
    public static final ICommandValidator ISOP = player -> MineTweakerAPI.server.isOp(player);

    @ZenGetter
    public static ICommandValidator isOp() {
        return ISOP;
    }
}

即脚本写 CommandValidators.isOp(属性形式)拿到 OP 校验器,传给 server.addCommand(...)。

1.7.10 的命令发送者适配

MCServer.getPlayer(ICommandSender)(mc1710/server/MCServer.java:67-81)把 4 种发送者映射为 IPlayer:

发送者类型 包装类
EntityPlayer MCPlayer
DedicatedServer —
RConConsoleSource RconPlayer(mc1710/player/RconPlayer.java)
CommandBlockLogic CommandBlockPlayer(mc1710/player/CommandBlockPlayer.java)
其他 往 stdout 打两行警告(:77-78),player 保持 null

因此 /minetweaker 从命令方块执行时 player 不会是真实玩家,脚本里取玩家名需自行判空。

相关条目