ImmersiveEngineeringTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类 | ...loading.fml.compat.transformers.specific.ImmersiveEngineeringTransformer |
| 路径 | src/main/java/com/gtnewhorizons/angelica/loading/fml/compat/transformers/specific/ImmersiveEngineeringTransformer.java |
| 行数 | 109 |
| 类型 | public class ... implements IClassTransformer(:23) |
| 注册方 | ImmersiveEngineeringCompatHandler.extraTransformers() :40-42 |
它是什么 / 挂在哪个阶段
真正的 IClassTransformer,与 4 个 generic/ 的静态工具不同。跑在 LaunchWrapper 类加载期(IClassTransformer#transform),排在 GenericCompatTransformer 之后(CompatHandlers.getTransformers() 先收集 extraTransformers() 再追加 GenericCompatTransformer,:48-59)。
RFB 路径不提供本 transformer —— AngelicaRfbPlugin.makeTransformers 只返回 3 个 RFB transformer。
目标类集合(:24-40)
两个静态列表,在 static {} 块里填充:
| 列表 | 内容 | 数量 |
|---|---|---|
transformedClasses |
BlockRenderClothDevices、BlockRenderMetalDevices2、BlockRenderStoneDevices、ClientUtils |
4 |
staticRenderPassPatches |
上列前 3 个(不含 ClientUtils) |
3 |
命名一致地省略了 blusunrize.immersiveengineering.client.render. / .client. 前缀(常量声明在 :24-28)。
:46 早退:if (!transformedClasses.contains(transformedName)) return basicClass;。
它改写什么
transform(:42-66)按目标类分派到两个互斥的补丁:
补丁 A:staticRenderPassPatcher(:68-85)—— 作用于 3 个 BlockRender* 类
在 renderWorldBlock 方法里,把所有 GETSTATIC 且字段名恰为 renderPass 的指令替换为:
INVOKESTATIC net/minecraftforge/client/ForgeHooksClient.getWorldRenderPass()I
即把 IE 缓存下来的静态 render-pass 标志,换成每帧从 Forge 钩子现取。
补丁 B:transformClientUtils(:87-107)—— 作用于 ClientUtils
只处理两个方法:renderStaticWavefrontModelWithIcon 与 renderStaticWavefrontModel,且要求描述符逐字符匹配:
(Lnet/minecraft/world/IBlockAccess;IIILnet/minecraftforge/client/model/obj/WavefrontObject;
Lnet/minecraft/util/IIcon;Lnet/minecraft/client/renderer/Tessellator;
Lblusunrize/immersiveengineering/common/util/chickenbones/Matrix4;
Lblusunrize/immersiveengineering/common/util/chickenbones/Matrix4;IZFFF[Ljava/lang/String;)V
在方法内找到第一条 IFNULL,把它改成 IFEQ 并在其前插入 ICONST_0(:102-104),然后 break。
源码注释 :88-91 解释动机:原代码是 if (world != null) { ... },块内调用 OpenGL 更新光照贴图坐标,在 Angelica 的 ISBRH 里是非法操作;注释断言「让它不发生似乎不会破坏任何东西」。
写出字节码
:60-61 用 MixinClassWriter(MixinClassWriter.COMPUTE_FRAMES) —— 唯一使用 COMPUTE_FRAMES(而非仅 COMPUTE_MAXS)的 transformer。COMPUTE_FRAMES 需要类加载器能解析合并后的公共父类/接口,在 classloader 早期可能抛 TypeNotPresentException。
:63 日志前缀 [AngelicaCompat]Extra Transformers: —— 注意是 AngelicaCompat 而非 Angelica,与 StacksOnStacksTransformer 一致,说明这两个「specific」transformer 是从下游 AngelicaCompat 包移植过来的,日志字符串未随移植改名。这是一个可直接观察到的移植痕迹。
已知问题
- 字段名硬编码为
renderPass(:75)。源码注释:73-74自陈:「目前每一个都恰好叫 renderPass,将来可能需要让名字动态化、并考虑 owner」。上游一旦改名即静默失效。 transformClientUtils描述符硬编码(:96-98):两条完整描述符字面量,且两个方法的描述符内容完全相同(源文件:96与:97只有换行差异)。IE 改签名即漏匹配。break只处理第一条IFNULL(:104):若方法里有多个world != null检查,只有第一个被改写。break在插入后立即退出,而staticRenderPassPatcher是全量扫描——两个补丁的遍历策略不一致。COMPUTE_FRAMES的早期类加载风险:见上。- 日志里的
AngelicaCompat前缀误导排障:用户搜AngelicaCompat找不到这个 mod。
相关条目
- ImmersiveEngineeringCompatHandler - 注册方
- CompatHandlers -
extraTransformers()的消费逻辑 - StacksOnStacksTransformer - 同一目录的孪生 transformer,同样带
AngelicaCompat日志前缀 - AngelicaClassDump -
:64的落盘调用 - FML Transformers - 两套 transformer 体系的关系
- NotFine -
renderPass配置项的另一个消费者(已恒为false)