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() |
已知问题
computeMaxs()而非重算 frames:FML 侧同样只重算 maxs。CeleritasBlockTransform的 PUTFIELD 分支插入的DUP2_X1/POP2/DUP_X2/POP不改变帧结构,故安全——但源码无断言保护。tileEntities.track()受上下文门控(:68):在非LCL_WITH_TRANSFORMS上下文里,TileEntity 子类不会被记录。若某条加载路径不走该上下文,后续 TileEntity 的 marker 判定会漏。id()名为"sodiumblocktransform"(:31)——RFB 的 transformer 标识符来自 Sodium 上游,本类名却是RFBCeleritasBlockTransformer,命名与 id 不一致,排障时容易困惑。- 重复计算 marker:
shouldTransformClass:69与transformClassIfNeeded:81各调一次markersFor(...),后者会重新new ClassReader(classBytes).accept(scanner, SCAN_FLAGS)(见 TileEntityMarkerTransform:69-71)。同一个类被扫描两次,无缓存。这是真实的性能浪费。 - 无 Javadoc,与 FML 侧
@see风格不一致。
相关条目
- CeleritasBlockTransform / TileEntityMarkerTransform - 两个内部实现
- CeleritasBlockTransformer - FML 侧对应类,ASM 版本不同
- AngelicaRfbPlugin - 构造点与
isObf来源 - AngelicaClassDump -
dumpRFBClass落盘 - FML Transformers - 两条路径的差集分析