注册时序

生命周期

GTTweaker 只挂 2 个 FML 事件处理器(GTTweaker.java:77-144):

阶段 事件 方法 动作
FMLInitializationEvent @EventHandler init init MineTweakerAPI.registerClass(...) × 58
FMLPostInitializationEvent @EventHandler onPostInit onPostInit MineTweakerAPI.registerClassRegistry(GTTweakerRegistry.class)

没有 preInit、没有 serverStarting、没有 FMLServerStartingEvent(无命令)、没有 FMLConstructionEvent。

init 阶段注册的 58 个类

MineTweakerAPI.registerClass(AlloySmelter.class);       // 49 个 GT 5 机器
...                                               // (含 Fuels)
if (GTPlusPlus.isModLoaded()) {                   // 6 个 GT++ 机器
    MineTweakerAPI.registerClass(BlastSmelter.class);
    ...
}
MineTweakerAPI.registerClass(RA2Builder.class);    // +1
MineTweakerAPI.registerClass(RecipeRemover.class); // +1

精确计数(grep registerClass 逐行统计):

类别 数量 说明
GT 5 机器类(gregtech/machines/) 49 每个 1 个 ZenClass
Fuels 1 mods.gregtech.Fuels
RA2Builder 1 mods.gregtech.RA2
RecipeRemover 1 mods.gregtech.RecipeRemover
GT++ 机器(gtpp/machines/) 6 条件注册
合计 58

未注册的 2 个类:GTRecipeMap(工具类,无注解)与 AddMultipleRecipeAction(抽象基类,被静态引用)。

postInit 阶段的 ZenExpansion

@ModOnly("gregtech")
public class GTTweakerRegistry {
    public static void getClasses(List<Class> classes) {
        classes.add(OreDictEntryExpansion.class);
    }
}

registerClassRegistry 走的是与 registerClass 不同的注册通道(MineTweaker 的 registry 机制,专供 ZenExpansion / ZenGetter 等扩展)。这是全 mod 唯一走该通道的类,也是 greggedItem 唯一的注册路径。

postInit 未清理 Recipe Map 查找 的缓存 —— 若脚本在 preInit 阶段调用 RA2.addTo("...") 并缓存了 null,GT5 在之后才补全的 map 将永久查不到。

门控机制

门控 位置 判定内容
@ModOnly("gregtech") 53 个类 CraftTweaker 侧:modid gregtech 存在才暴露 ZenClass / ZenExpansion
@ModOnly("miscutils") 6 个类 同上,modid miscutils(GT++ 的真实 modid)
GTPlusPlus.isModLoaded() GTTweaker.init Java 侧:来自 gregtech.api.enums.Mods 枚举,检查同一 modid

双重门控的必要性:Java 侧 isModLoaded() 防止在无 GT++ 时执行 registerClass(虽然注册本身不会崩),@ModOnly 防止脚本侧在无 GT++ 时看到这些类。二者独立。

数值

数值 值
生命周期处理器数 2(init + onPostInit)
registerClass 调用数 58
registerClassRegistry 调用数 1
@ModOnly("gregtech") 类数 53
@ModOnly("miscutils") 类数 6
注册的 ZenClass 数 58(49 机器 + 6 GT++ + Fuels + RA2 + RecipeRemover)
注册的 ZenExpansion 数 1
条件注册分支数 1(GTPlusPlus.isModLoaded())
未注册的类数 2(GTRecipeMap、AddMultipleRecipeAction)
资源文件数 1(mcmod.info)

源码缺陷

  • @Mod 注解缺 version 属性:@Mod(modid = "GTTweaker", useMetadata = true)(:74)。版本号只能来自 mcmod.info 的 ${modVersion}(由 GTNH convention 插件替换)。FML 1.7.10 在 @Mod 无 version 时会记录警告,且依赖 mcmod.info 解析版本的 mod 在某些 FML 版本下会报 Wrong version format。本 mod 能运行是因为 mcmod.info 存在。
  • useMetadata = true 但只有一个根 mcmod.info:src/main/resources 下仅 1 个文件,find src/main/resources -type f 结果只有 mcmod.info。useMetadata 的作用是允许子目录再放一份 mcmod.info 来合并依赖描述 —— 本 mod 完全没用这个能力,纯冗余。
  • mcmod.info 全是构建期占位符:8 个字段中 5 个是 ${modId} / ${modName} / ${modVersion} / ${minecraftVersion} —— 无法从 mcmod.info 实读 modid。权威来源只能是 @Mod 注解(:74)与 gradle.properties(modId = GTTweaker)。
  • mcmod.info 的 dependencies 为空数组 []:源码层面没有声明对 CraftTweaker / GT5 的依赖。虽然 dependencies.gradle 是 api(编译期),但运行时若缺 CraftTweaker,56 个类的 @ZenClass 全部无法工作且无声明。
  • @ModOnly 类数 59 = registerClass 58 + registerClassRegistry 1:53 个 @ModOnly("gregtech")(49 机器 + Fuels + RA2Builder + RecipeRemover + OreDictEntryExpansion)+ 6 个 @ModOnly("miscutils")。唯一带 @ModOnly 但不经 registerClass 的是 OreDictEntryExpansion(走 registerClassRegistry)。计数自洽,不是缺陷,记录在此以免后续核对时误判。
  • onPostInit 参数名 ev 而 init 参数名 event(:78 vs :142):同文件内命名不统一。
  • 无 @SuppressWarnings("unused") 于 GTTweaker 本身:两个事件处理器由 FML 反射调用,IDE 会报未使用。其余 2 个类(RecipeRemover、RA2Builder)都加了该注解,GTTweaker 反而没加。
  • 注册顺序即源码 import 顺序:init 中的 registerClass 顺序基本是 import 顺序,不是逻辑分组顺序。GT++ 6 个类被 if 块隔在中间,使 GT 5 类的列表在视觉上被割裂。

相关条目