CeleritasBlockTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.gtnewhorizons.angelica.loading.fml.transformers.CeleritasBlockTransformer |
| 路径 | src/main/java/com/gtnewhorizons/angelica/loading/fml/transformers/CeleritasBlockTransformer.java |
| 行数 | 62 |
| 类型 | public class ... implements IClassTransformer(:14),Javadoc :13「IClassTransformer wrapper for CeleritasBlockTransform」 |
| 组合 | 同时驱动 CeleritasBlockTransform 与 TileEntityMarkerTransform |
它是什么
FML 侧最复杂的 transformer:不像 AngelicaRedirectorTransformer 那样把一切交给内部对象,而是在 transform 里手工编排 4 个步骤。两个内部对象各司其职:
| 字段 | 行 | 作用 |
|---|---|---|
inner |
:16、:21 |
new CeleritasBlockTransform(AngelicaClientTweaker.isObfEnv()) |
tileEntities |
:17、:22 |
new TileEntityMarkerTransform(AngelicaClientTweaker.isObfEnv(), Opcodes.ASM5) |
exclusions |
:18、:23 |
inner.getTransformerExclusions() |
挂在哪个阶段
LaunchWrapper 类加载期。与 AngelicaRedirectorTransformer 不同,本类走 AngelicaClientTweaker.getASMTransformerClass() 段 (3) 之外的路径——实际上它由 EarlyRedirectorTransformer 之后的完整替换流程间接管理,见 AngelicaLateTweaker。RFB 路径有对应类 RFBCeleritasBlockTransformer。
transform 的 4 步(:30-60)
| 步 | 行 | 动作 |
|---|---|---|
| 0 | :32-35 |
basicClass == null 返回 null;命中 4 个排除前缀(org.lwjgl、glsm.、angelica.transform、me.eigenraven.lwjgl3ify)则原样返回 |
| 1 | :37-40 |
读 cr.getClassName() / cr.getSuperName(),无条件喂给 inner.trackBlockSubclasses() 与 tileEntities.track() |
| 2 | :42-43 |
markers = tileEntities.markersFor(...);非 0 则 addMarkers 得到 marked |
| 3 | :45-59 |
inner.shouldTransform(marked) 为假 → 返回 marked;否则建 ClassNode、transformClassNode、变更时用 ClassWriter(COMPUTE_MAXS) 写出并 dump |
:50 的三元 (markers == 0 ? cr : new ClassReader(marked)) —— 避免在无标记时重复解析。
关键设计:跟踪 vs 变换必须分离
:37-40 在排除检查之后、无条件执行,这是源码注释强调的约束(CeleritasBlockTransform :80-82):
This method needs to be called for every class, including the ones we don’t want to transform.
原因:mod 提供的 Block 子类必须先被记录,之后其子类才能被识别为「Block 子类」。若只对要变换的类调用 trackBlockSubclasses,子类链会断。
已知问题
Opcodes.ASM5硬编码(:22)。对比 RFB 侧 RFBCeleritasBlockTransformer:25用RetroFuturaBootstrap.API.newestAsmVersion()。TileEntityMarkerTransform的asmApi参数存在的唯一原因就是处理 javac 为嵌套类生成的NestMember属性(见该类:41-43注释)——写死 ASM5 意味着带嵌套类的 TileEntity 会被ClassVisitor拒绝访问新属性。这是一个真实的两路径行为差异。ClassWriter(COMPUTE_MAXS)而非COMPUTE_FRAMES(:53):redirectBlockBoundFields的 PUTFIELD 分支插入了DUP2_X1/POP2/DUP_X2/POP序列([CeleritasBlockTransform](shared-transformer-celeritas-block):152-163`),这些不改变帧结构,所以只重算 maxs 是安全的——但这是隐式依赖。- 无 classloader 排除注册:
exclusions只用于transform内部的早退(:33-35),本类不调用addClassLoaderExclusion。真正的排除注册在 AngelicaClientTweaker 构造函数:50-54。 - 无 Javadoc 说明注册时机:
@see缺失,不像 EarlyRedirectorTransformer 有完整生命周期说明。
相关条目
- CeleritasBlockTransform - 172 行核心变换逻辑
- TileEntityMarkerTransform - 137 行,FML 侧唯一使用者
- RFBCeleritasBlockTransformer - RFB 侧对应类,ASM 版本不同
- AngelicaClassDump -
:56的落盘调用 - FML Transformers - 5 个 FML 侧 transformer 的总览