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,子类链会断。

已知问题

  1. Opcodes.ASM5 硬编码(:22)。对比 RFB 侧 RFBCeleritasBlockTransformer :25 用 RetroFuturaBootstrap.API.newestAsmVersion()。TileEntityMarkerTransform 的 asmApi 参数存在的唯一原因就是处理 javac 为嵌套类生成的 NestMember 属性(见该类 :41-43 注释)——写死 ASM5 意味着带嵌套类的 TileEntity 会被 ClassVisitor 拒绝访问新属性。这是一个真实的两路径行为差异。
  2. ClassWriter(COMPUTE_MAXS) 而非 COMPUTE_FRAMES(:53):redirectBlockBoundFields 的 PUTFIELD 分支插入了 DUP2_X1/POP2/DUP_X2/POP 序列([CeleritasBlockTransform](shared-transformer-celeritas-block) :152-163`),这些不改变帧结构,所以只重算 maxs 是安全的——但这是隐式依赖。
  3. 无 classloader 排除注册:exclusions 只用于 transform 内部的早退(:33-35),本类不调用 addClassLoaderExclusion。真正的排除注册在 AngelicaClientTweaker 构造函数 :50-54。
  4. 无 Javadoc 说明注册时机:@see 缺失,不像 EarlyRedirectorTransformer 有完整生命周期说明。

相关条目