FieldLevelTessellatorTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类名 | com.gtnewhorizons.angelicacompat.asm.transformers.generic.FieldLevelTessellatorTransformer |
| 实现接口 | net.minecraft.launchwrapper.IClassTransformer |
| 数据源 | CompatRegistry.INSTANCE.getFieldLevelTessellatorTransforms() |
| 触发条件 | AngelicaConfig.enableSodium == true 且 Side.CLIENT |
| 注册枚举 | AsmTransformers.FIELD_LEVEL_TESSELLATOR |
| 启用版本 | Minecraft 1.7.10(仅客户端) |
功能
Angelica 的 Sodium 渲染路径为 Tessellator 引入了字段级共享——多个 mod 在渲染管线里都通过静态字段访问 Tessellator.instance,并发生成交叉污染(一个 mod 在 vertex 调用还没结束时,另一个 mod 已经把自己的顶点 push 进去)。
FieldLevelTessellatorTransformer 在指定方法的最前(instructions.insert(list) 之前)注入一段字节码,把 Tessellator.instance(Obf 环境:net/minecraft/client/renderer/Tessellator 字段名为 instance)缓存到一个 LVT(局部变量表)槽位,并在后续 GETSTATIC 读取该字段时改读 LVT 槽位,等价于"为该方法提供独立的 Tessellator 引用"。
补丁覆盖(默认)
com.tierzero.stacksonstacks.util.ClientUtils上的drawQuad与drawRectangularPrism(由 StacksOnStacksCompatHandler 注册)
注入算法(injectLocalTessellatorAndReplaceFieldUsage)
- 找到
GETSTATIC net/minecraft/client/renderer/Tessellator.instance指令的第一次出现,记录其位置firstGetStatic。 - 在该指令之前插入:
ALOAD varOfTessellatorOrZero(如果当前方法签名中已存在Lnet/minecraft/client/renderer/Tessellator;的本地变量则直接复用,否则加载null槽位)ASTORE newLvtSlot(申请新的Tessellator类型槽位到 LVT 末尾)
- 遍历剩余所有指向同一字段的
GETSTATIC指令,替换为ALOAD newLvtSlot(VarInsnNode)。 - 不修改
PUTSTATIC(保留全局静态字段的真实更新,避免破坏其它方法)。
字节码要点
| 字节码位置 | 旧指令 | 新指令 |
|---|---|---|
| 入口首次 GETSTATIC 前 | — | ASTORE newLvtSlot(并复用旧的本地变量或占位 null) |
| 后续 GETSTATIC | GETSTATIC Tessellator.instance:Tessellator |
ALOAD newLvtSlot |
ClassWriter 标志
COMPUTE_MAXS | COMPUTE_FRAMES:自动重算栈帧与最大值。
输出与调试
如果 AngelicaCompatCore.DUMP_CLASSES() 为 true(-Dangelica.dumpClass=true 或非 Obf 环境)且 patchMethods.containsKey(transformedName) 为 true,会将改写前后字节码写出到磁盘供 diff 检查。详见 AngelicaCompatCore。
数值
| 数值 | 默认 | 含义 |
|---|---|---|
| 数据来源 | CompatRegistry.getFieldLevelTessellatorTransforms() |
运行时由各 CompatHandler 注册 |
| 默认目标方法数 | 2(Stacks on Stacks) | ClientUtils.drawQuad + drawRectangularPrism |
| 触发开关 | AngelicaConfig.enableSodium |
Sodium 渲染启用时才装载 |
限制
- 仅替换第一次出现的本地变量复用逻辑;如果一个方法原本就有
Lnet/minecraft/client/renderer/Tessellator;类型的局部变量,且不是缓存instance而是缓存别的字段,会被错误替换为新注入的 LVT 槽位。 - 仅 Patch
GETSTATIC字段访问;不动INVOKESTATIC Tessellator.getInstance()调用。 - 仅在字段名恰好为
instance时匹配;Obf 环境字段名映射在AsmUtil.obf(...)中处理。
第三方 mod 集成
通用 transformer,依赖 CompatRegistry 的运行时填充。当前内置 Stacks on Stacks 一个兼容目标。
相关条目
- CompatRegistry - 该 transformer 的中央注册表
- StacksOnStacksCompatHandler - 为该 transformer 注册目标的 CompatHandler
- AsmTransformers - 装载控制中心
- AngelicaCompatCore - 类转储与字节码操作基础设施