Coremod 引导(ClassTransformer)

基本信息

属性 值
类型 FML coremod 加载插件 + 类字节码转换器
实现类 net.vfyjxf.nechar.core.NechCorePlugin(IFMLLoadingPlugin + IFMLCallHook)<br>net.vfyjxf.nechar.core.NechClassTransformer(IClassTransformer)
来源 NechClassTransformer 基于 Towdium 的 JustEnoughCharacters 1.12.0 版 JechClassTransformer.java 改写(MIT 协议)

NechCorePlugin

成员 值
getASMTransformerClass() new String[] { "net.vfyjxf.nechar.core.NechClassTransformer" }
getModContainerClass() null(不提供 mod 容器)
getSetupClass() "net.vfyjxf.nechar.core.NechCorePlugin"(指向自身)
getAccessTransformerClass() null(不使用 AT)
injectData(Map<String, Object> data) 空实现
public static boolean INITIALIZED 初始 false;在 call() 中置为 true
call() 调用 TransformerRegistry.getTransformer("some.class") 触发注册表静态块(强制初始化两个转换器),随后 INITIALIZED = true,返回 null

关键设计:getSetupClass() 返回自身类名,使 FML 在模组容器构造之前就实例化本类并调用 call()。此时配置文件尚未由模组加载,但 TransformerString / TransformerRegExp 的构造器会各自调用 reload() 读取 NechConfig——后者通过自己的 static 块从 config/NotEnoughCharacters.cfg 读值(见 配置系统),因此配置在 coremod 阶段就已可用。

NechClassTransformer

public byte[] transform(String s, String s1, byte[] bytes) {
    if (NechCorePlugin.INITIALIZED) {
        for (Transformer t : TransformerRegistry.getTransformer(s)) {
            bytes = t.transform(bytes);
        }
        return bytes;
    } else {
        return bytes;
    }
}
要点 说明
开关 仅当 NechCorePlugin.INITIALIZED == true 才改写;否则原样返回字节码
参数 s 为正在加载的类名,作为 getTransformer(s) 的查询键;s1(基本类名)与字节码内容未用于其它判断
链式应用 返回值 bytes 覆盖进循环变量,因此同一类若命中多个转换器,前一个转换器的输出会成为后一个的输入
顺序 迭代顺序即 转换器注册表 中 transformers 的顺序:TransformerString → TransformerRegExp

生命周期总览

阶段 触发者 动作
1. coremod 加载 FML 读取 IFMLLoadingPlugin 实例化 NechCorePlugin,调用 call() → 初始化转换器注册表 → INITIALIZED = true
2. 类加载 LaunchWrapper 遍历 IClassTransformer NechClassTransformer.transform 对每个类查表,命中则用 ASM 改写字节码
3. preInit @Mod.EventHandler preInit 打印 Not Enough Characters - v<VERSION>,调用 onConfigChange() 把配置提交给 PinIn
4. init @Mod.EventHandler init 注册 /nech 客户端指令(见 /nech 命令)
5. 物品列表初始化 NEINecharConfig#loadConfig 注册两个搜索提供者(见 搜索提供者)

NechClassTransformer 类上标注 @SuppressWarnings("SameParameterValue")——因为 s1 参数未被使用。

安全性说明

TransformerRegistry.getTransformer 返回的列表可能为空,此时循环不执行、字节码原样返回——未列入目标列表的类完全不受影响。改写过程只替换特定方法调用点,不改变类结构。

相关条目