RFBCeleritasBlockTransformer

基本信息

属性 值
类 com.gtnewhorizons.angelica.loading.rfb.transformers.RFBCeleritasBlockTransformer
路径 src/main/java/com/gtnewhorizons/angelica/loading/rfb/transformers/RFBCeleritasBlockTransformer.java
行数 100
类型 public class ... implements RfbClassTransformer(:18)
id() "sodiumblocktransform"(:30-32)
内部实现 CeleritasBlockTransform + TileEntityMarkerTransform

它是什么

3 个 RFB transformer 中最复杂的。与 FML 侧 CeleritasBlockTransformer 驱动同样的两个内部对象,但用 RFB 的 shouldTransformClass / transformClassIfNeeded 两段式 API 重写。

排序声明(:34-42)

方法 返回
sortAfter() {"*", "mixin:mixin"}
sortBefore() {"lwjgl3ify:redirect"}

即必须排在 所有 transformer 与 mixin:mixin 之后、lwjgl3ify:redirect 之前。id() 标注 @Pattern("[a-z0-9-]+")(:28)。

构造(:23-26)

inner = new CeleritasBlockTransform(isObf);
tileEntities = new TileEntityMarkerTransform(isObf, RetroFuturaBootstrap.API.newestAsmVersion());

isObf 由 AngelicaRfbPlugin :29 计算(找不到 net.minecraft.world.World 的类元数据即为混淆环境)传入。

关键差异:asmApi 参数用 RetroFuturaBootstrap.API.newestAsmVersion(),而 FML 侧 CeleritasBlockTransformer :22 写死 Opcodes.ASM5。RFB 侧能处理 javac 为嵌套类生成的 NestMember 属性(见 TileEntityMarkerTransform :41-43 注释),FML 侧不能。

additionalExclusions(:44-47)

直接转发 inner.getTransformerExclusions() —— 4 项:org.lwjgl、glsm.、angelica.transform、me.eigenraven.lwjgl3ify。这是 RFB 侧唯一声明 classloader 排除的地方(对比 AngelicaRfbPlugin.onConstruction :19 只排除 glsm.redirect.)。

shouldTransformClass(:49-72)

行 动作
:53-55 !classNode.isPresent() → false
:57-60 getOriginalMetadata() == null → false
:62-64 取 binaryThisName / binarySuperName / getOriginalBytes()
:66 无条件 inner.trackBlockSubclasses(thisName, superName)
:67-70 仅当 context == LCL_WITH_TRANSFORMS 时才 tileEntities.track(...) 并按 marker 决定
:71 回落 inner.shouldTransform(originalBytes)

transformClassIfNeeded(:74-93)

marker 处理(:80-86)→ inner.transformClassNode()(:87)→ 变更时 classNode.computeMaxs() + dumpRFBClass(:88-91)。

transformClass(:95-99)无条件转发给 transformClassIfNeeded——即 RFB 的「无条件变换」钩子在此退化为「条件变换」。

与 FML 侧的行为差异

FML 侧 RFB 侧
asmApi Opcodes.ASM5 API.newestAsmVersion()
排除检查时机 transform 开头逐类比对 additionalExclusions() 一次性声明
跟踪调用 排除检查之后、无条件(:37-40) shouldTransformClass 里,metadata 非空即调用(:66)
TileEntity 跟踪 无条件(:40) 仅 LCL_WITH_TRANSFORMS 上下文(:68)
ClassWriter flag COMPUTE_MAXS classNode.computeMaxs()

已知问题

  1. computeMaxs() 而非重算 frames:FML 侧同样只重算 maxs。CeleritasBlockTransform 的 PUTFIELD 分支插入的 DUP2_X1/POP2/DUP_X2/POP 不改变帧结构,故安全——但源码无断言保护。
  2. tileEntities.track() 受上下文门控(:68):在非 LCL_WITH_TRANSFORMS 上下文里,TileEntity 子类不会被记录。若某条加载路径不走该上下文,后续 TileEntity 的 marker 判定会漏。
  3. id() 名为 "sodiumblocktransform"(:31)——RFB 的 transformer 标识符来自 Sodium 上游,本类名却是 RFBCeleritasBlockTransformer,命名与 id 不一致,排障时容易困惑。
  4. 重复计算 marker:shouldTransformClass:69 与 transformClassIfNeeded:81 各调一次 markersFor(...),后者会重新 new ClassReader(classBytes).accept(scanner, SCAN_FLAGS)(见 TileEntityMarkerTransform :69-71)。同一个类被扫描两次,无缓存。这是真实的性能浪费。
  5. 无 Javadoc,与 FML 侧 @see 风格不一致。

相关条目