IsbrhTessellatorAbuseTransform
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.gtnewhorizons.angelica.loading.shared.transformers.IsbrhTessellatorAbuseTransform |
| 路径 | src/main/java/com/gtnewhorizons/angelica/loading/shared/transformers/IsbrhTessellatorAbuseTransform.java |
| 行数 | 73 |
| 类型 | public final class(:12) |
| 公开常量 | ISBRH = "cpw/mods/fml/client/registry/ISimpleBlockRenderingHandler"(:15) |
| 驱动者 | IsbrhTessellatorAbuseTransformer + RFBIsbrhTessellatorAbuseTransformer |
它是什么
处理「ISBRH 滥用 Tessellator」的核心变换。问题是 1.7.10 的 ISimpleBlockRenderingHandler#renderWorldBlock 运行在区块构建线程上,而 Tessellator 是全局共享单例(Tessellator.instance)。任何在 ISBRH 里直接用 Tessellator.instance.draw() / startDrawingQuads() / startDrawing() 的 mod,在多线程下会互相踩踏缓冲区。
关键常量
| 常量 | 值 | 行 |
|---|---|---|
ISBRH |
cpw/mods/fml/client/registry/ISimpleBlockRenderingHandler |
:15 |
CST_POOL_PARSER |
new ClassConstantPoolParser(ISBRH) |
:18 |
TESSELLATOR |
net/minecraft/client/renderer/Tessellator |
:19 |
RENDER_WORLD_BLOCK_DESC |
(Lnet/minecraft/world/IBlockAccess;IIILnet/minecraft/block/Block;ILnet/minecraft/client/renderer/RenderBlocks;)Z |
:20 |
两个公开方法
shouldTransform(:22-24)
return CST_POOL_PARSER.find(classBytes); —— 扫常量池找 ISBRH 引用。这是预筛选,两个 wrapper 各自在 transform 早期调用。
transformClassNode(:26-73)
第 1 步:定位目标方法(:27-34)
for (int i = 0, n = cn.methods.size(); i < n; i++) {
final MethodNode mn = cn.methods.get(i);
if ("renderWorldBlock".equals(mn.name) && RENDER_WORLD_BLOCK_DESC.equals(mn.desc)) { target = mn; break; }
}
if (target == null) return false;
要求方法名与完整描述符逐字符匹配。找不到就 false。
第 2 步:混淆名解析(:36-38)
| 逻辑名 | 混淆名(isObf = true) |
|---|---|
draw |
func_78381_a |
startDrawingQuads |
func_78382_b |
startDrawing |
func_78371_b |
第 3 步:改写(:40-73)
单趟遍历目标方法的指令,对每个 INVOKEVIRTUAL 且 owner == TESSELLATOR 的调用点,根据其名字与描述符决定插入的栈平衡指令与返回值压栈指令。:48 起用 popOp / pushIntResult 两个变量承载这个决策。
两条路径调用同一个 isObf 参数
| Wrapper | isObf 来源 |
时机 |
|---|---|---|
| IsbrhTessellatorAbuseTransformer | AngelicaClientTweaker.isObfEnv()(:23),每次 transform 现问 |
类加载期 |
| RFBIsbrhTessellatorAbuseTransformer | 构造期存入字段(:19、:23) |
plugin 构造期 |
已知问题
RENDER_WORLD_BLOCK_DESC硬编码为 1.7.10 原版签名:任何以不同描述符覆写renderWorldBlock的 mod(例如自行加了参数)完全不被处理,且无日志。- 只处理
INVOKEVIRTUAL(:42):若某 mod 通过INVOKESTATIC转发或通过Tessellator.getInstance()之类的静态方法获取实例,本变换漏改。 popOp/pushIntResult决策逻辑(:48起)在源文件里跨越 25 行且被截断于我的读取窗口;从可读部分能确认它按被调方法的返回类型决定栈平衡方式,但完整的 4 分支映射未在源码注释中列出,属于可读性较差的 ASM 代码。CST_POOL_PARSER是static final(:18):常量池扫描器全局共享,无状态问题,但线程安全性取决于 gtnhlib 实现。- 无类级 Javadoc:
public final class后直接是常量。文件名已说明用途,但「为什么滥用 Tessellator 会出问题」这一背景在本文件里没有任何记录。
相关条目
- IsbrhTessellatorAbuseTransformer - FML 侧包装
- RFBIsbrhTessellatorAbuseTransformer - RFB 侧包装
- FieldLevelTessellatorTransformer - 解决同一问题的另一条路径(字段级局部 Tessellator)
- ThreadSafeISBRH - 让 ISBRH 真正线程安全的注解式 API
- ThreadSafeISBRHAnnotationTransformer - 通过注解实现同一目标
- shared/package-info - 本包的类加载约束