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 引用"。

补丁覆盖(默认)

注入算法(injectLocalTessellatorAndReplaceFieldUsage)

  1. 找到 GETSTATIC net/minecraft/client/renderer/Tessellator.instance 指令的第一次出现,记录其位置 firstGetStatic。
  2. 在该指令之前插入:
    • ALOAD varOfTessellatorOrZero(如果当前方法签名中已存在 Lnet/minecraft/client/renderer/Tessellator; 的本地变量则直接复用,否则加载 null 槽位)
    • ASTORE newLvtSlot(申请新的 Tessellator 类型槽位到 LVT 末尾)
  3. 遍历剩余所有指向同一字段的 GETSTATIC 指令,替换为 ALOAD newLvtSlot(VarInsnNode)。
  4. 不修改 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 一个兼容目标。

相关条目