MixinBlock

基本信息

属性 值
Mixin 目标 net.minecraft.block.Block
Phase EARLY
角色 把 Block.harvestTool[] / harvestLevel[] 大小 16 的固定数组换成 HashMap
依赖 it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap + Int2ObjectOpenHashMap

解决的问题

Forge 给 Block 加了一个"按 metadata 指定挖掘工具+等级"的系统:

  • vanilla + Forge:String[16] harvestTool + int[16] harvestLevel,每个 Block 实例预分配 16 个槽(即使只用了 1 个)。
  • NEID 把 metadata 上限扩到 16-bit (65536),如果沿用 Forge 方案,单个 Block 实例就是 65536 个 String + 65536 个 int → 数十 GB 级内存。

NEID 改用 HashMap 仅在用到的 metadata 上分配,节省 GB 级内存(注释中 Cleptomania 写 “classdump of full GTNH shows nothing else ASMing/mixin to this”)。

注入字段

@Unique private String neid$defaultHarvestTool = null;   // 没有 metadata 时的默认工具
@Unique private int neid$defaultHarvestLevel = -1;       // 默认挖掘等级(-1 = 不限制)

@Unique private Int2ObjectOpenHashMap<String> harvestToolMap = new Int2ObjectOpenHashMap<>();
@Unique private Int2IntOpenHashMap harvestLevelMap = new Int2IntOpenHashMap<>();

@Shadow(remap = false) private String[] harvestTool = null;     // 屏蔽原版字段(防止误读)
@Shadow(remap = false) private int[] harvestLevel = null;

@Overwrite 方法

方法 行为
setHarvestLevel(String toolClass, int level) 设默认工具/等级(写入 neid$defaultHarvest* 字段)
setHarvestLevel(String toolClass, int level, int metadata) 设指定 metadata 的工具/等级(写入 HashMap)
getHarvestTool(int metadata) harvestToolMap.getOrDefault(metadata, neid$defaultHarvestTool)
getHarvestLevel(int metadata) harvestLevelMap.getOrDefault(metadata, neid$defaultHarvestLevel)
isToolEffective(String type, int metadata) 先硬编码三例外:pickaxe + (redstone_ore | lit_redstone_ore | obsidian) → false;否则查 getHarvestTool(metadata) 是否等于 type

兼容性

  • API 兼容:所有 public 方法签名一致,外部 mod 沿用 Forge API 即可。
  • 反射/ASM/私有访问的破坏:直接读 Block.harvestTool / harvestLevel 私有字段的代码会拿到 null/-1。注释明确指出 GTNH 全量 classdump 没有发现此类访问方。

相关条目