TileEntityNullGuardTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类 | ...loading.fml.compat.transformers.generic.TileEntityNullGuardTransformer |
| 路径 | src/main/java/com/gtnewhorizons/angelica/loading/fml/compat/transformers/generic/TileEntityNullGuardTransformer.java |
| 行数 | 94 |
| 类型 | public class(:20),不实现 IClassTransformer |
| 入口签名 | public static void transform(ClassNode cn, List<String> patchMethods)(:22) |
| 公开辅助 | public static void injectGetTileEntityNullGuard(MethodNode mn)(:28) |
| 数据来源 | ICompatHandler.getTileEntityNullGuard() |
它是什么 / 挂在哪个阶段
静态工具,被 GenericCompatTransformer :76-78 调用;该 transformer 由 CompatHandlers.getTransformers() 在 handler 非空时注册。跑在 LaunchWrapper 类加载期,RFB 路径不提供。
injectGetTileEntityNullGuard 是 public,是 4 个 generic/ transformer 里唯一一个把核心逻辑暴露为公开方法的(ThreadSafeISBRHAnnotationTransformer 等都是私有)。
它改写什么
:31-53 有一段完整的字节码模式注释,是理解本类最直接的文档:
匹配模式:
L0 { ... INVOKEINTERFACE IBlockAccess.getTileEntity(III)TileEntity; CHECKCAST *; ASTORE x }
L1 { ... }
注入后:
L0 { ASTORE x; ALOAD x; IFNONNULL L1; ICONST_0; IRETURN }
L1 { ... }
Java 层的等价:
MyTileEntity tile = (MyTileEntity) world.getTileEntity(x, y, z);
if (tile == null) { return false; } else { doSomethingWith(tile); }
匹配条件(:57-90,四层嵌套)
| 层 | 条件 | 行 |
|---|---|---|
| 1 | INVOKEINTERFACE + owner == "net/minecraft/world/IBlockAccess" + name == obf("getTileEntity","func_147438_o") |
:58-61 |
| 2 | 下一条指令是 CHECKCAST |
:62-65 |
| 3 | 再下一条是 ASTORE |
:66-69 |
三条必须紧邻(getNext() 链式)。任何在 CHECKCAST 与 ASTORE 之间插入的指令(DUP、CHECKCAST 两次等)都会导致漏匹配。
返回类型分派(:71-79)
| 方法描述符结尾 | 注入 |
|---|---|
Z 或 I |
ICONST_0 + IRETURN |
V |
RETURN |
其他(对象/数组/J/F/D) |
打 warn 日志并 return |
已知问题(真实缺陷):
return而非continue会在遇到第一个未知返回类型的方法时放弃该方法的剩余全部指令(:76-79)。injectGetTileEntityNullGuard是对mn.instructions的单趟for循环,一旦在循环体内return,同一个方法里后续的getTileEntity调用点全部得不到补丁。同类问题也出现在 HUDCachingEarlyReturnTransformer(结构相同)。J/F/D/L返回类型无解且无兜底:这四种返回类型下守卫被静默跳过,只有日志。对这些类型正确的做法是注入0L/0.0f/aconst_null,但源码只实现了Z/I/V。CHECKCAST缺失即漏匹配:很多 ISBRH 写法是TileEntity te = world.getTileEntity(...)(无 cast),本 transformer 不处理。- 只守卫
IBlockAccess:IBlockAccessExtended(Angelica 自己的 API,见 API 层)派生的其他访问路径不在覆盖范围。
耦合点
数据提供方有 2 个 handler:ImmersiveEngineeringCompatHandler(6 个类)与 StacksOnStacksCompatHandler(1 个类)。
相关条目
- ICompatHandler -
getTileEntityNullGuard()定义 - GenericCompatTransformer - 唯一调用点
- HUDCachingEarlyReturnTransformer - 结构几乎相同的孪生类
- ImmersiveEngineeringCompatHandler - 最大数据提供方
- FML Transformers - 4 个
generic/transformer 的分派表