StacksOnStacksCompatHandler

基本信息

属性 值
类 com.gtnewhorizons.angelica.loading.fml.compat.handlers.StacksOnStacksCompatHandler
路径 src/main/java/com/gtnewhorizons/angelica/loading/fml/compat/handlers/StacksOnStacksCompatHandler.java
行数 33
类型 public class ... implements ICompatHandler(:10)
门控 CompatConfig.fixStacksOnStacks(CompatHandlers.java:16)

它是什么

Stacks on Stacks(模组包 tierzero)的兼容数据提供者。是 5 个 handler 里覆写方法最多的一个(4 个),也是 extraTransformers() 的两个实现之一。

覆写的 4 个方法

方法 行 数据
getFieldLevelTessellator() :14-16 com.tierzero.stacksonstacks.util.ClientUtils → [drawQuad, drawRectangularPrism]
getTileEntityNullGuard() :18-20 com.tierzero.stacksonstacks.client.render.RenderTilePile → [renderWorldBlock]
getThreadSafeISBRHAnnotations() :22-24 com.tierzero.stacksonstacks.client.render.RenderTilePile → true
extraTransformers() :26-31 ImmutableList.of("...transformers.specific.StacksOnStacksTransformer")

RenderTilePile 同时出现在 3 张表里(null 守卫 + 线程安全标注),是本 mod 唯一被三重处理的目标类。

4 张表如何变成字节码改动

RenderTilePile 走的 3 条路径最终会叠加在同一个类上:

表 transformer 效果
ThreadSafeISBRH=true ThreadSafeISBRHAnnotationTransformer 加 @ThreadSafeISBRH(perThread=true) → 允许 Celeritas 把它挪到构建线程
TileEntityNullGuard TileEntityNullGuardTransformer renderWorldBlock 里 getTileEntity 结果为 null 时提前 return false
extraTransformers StacksOnStacksTransformer 把 3 个 static PileRender 字段改成实例字段

ClientUtils 则只走 FieldLevelTessellator 与 StacksOnStacksTransformer(后者把 pushMatrix/popMatrix 清空成 no-op)。

已知问题

StacksOnStacksTransformer 把 RenderTilePile 的 PileRender 字段从 static 改为实例字段,代价是每个 RenderTilePile 实例都要新建 3 个 PileRender 对象(buildPilerRenderInitializer 在 <init> 里各 NEW 一次)。源码注释解释了动机:static 字段在多线程下不安全。另一个副作用是 StacksOnStacksTransformer 删除了整个 <clinit> 方法 —— 注释 :132-134 声明「除了字段初始化外没有别的东西」,若上游版本给 <clinit> 加了逻辑,这段删除会静默丢失它。

相关条目