NotEnoughItems 兼容
事实基准:
harvestcraft-1.3.14-GTNH.jar(MC 1.7.10 / Forge 10.13.4.1614)CFR 0.152 反编译源码。
触发方式与安全性
| 属性 | 值 | 来源 |
|---|---|---|
| 依赖 modid | NotEnoughItems |
HarvestCraft.java:141-142,157 |
| 判定方式 | 没有任何 if / Loader.isModLoaded |
HarvestCraft.java:131-142 |
| 调用位置 | sendIMCMessages(),在 init() 第 116 行 |
HarvestCraft.java:116 |
| 注入方式 | FMLInterModComms.sendMessage(IMC) |
HarvestCraft.java:141,142,157 |
| 未安装时 | IMC 目标不存在,消息被丢弃,安全 | — |
本模组无条件发送 6 条 IMC 消息(4 条 registerHandlerInfo + 2 条 registerCatalystInfo)。由于 IME 接收方不存在时消息被丢弃,“无条件"在效果上等价于"装了 NEI 才生效”。
IMC 注入:4 个 handler + 2 个 catalyst
全部由 HarvestCraft.sendIMCMessages()(HarvestCraft.java:127-143)发出,辅助方法 sendNEIHandler(...)(HarvestCraft.java:145-158)。
4 个 registerHandlerInfo
sendNEIHandler 写入的 NBT 字段固定为 9 个(HarvestCraft.java:146-156):handler、modName、modId、modRequired(true)、itemName、handlerWidth、handlerHeight、maxRecipesPerPage、showOverlayButton(false)、showFavoritesButton(false)。
| # | handler ID | itemName(delegate.name()) |
宽 | 高 | 每页最大配方数 | 调用点 |
|---|---|---|---|---|---|---|
| 1 | harvestcraftAnimalTrapDrops |
BlockRegistry.pamanimalTrap |
170 | 70 | 5 | HarvestCraft.java:131 |
| 2 | harvestcraftFishTrapDrops |
BlockRegistry.pamfishTrap |
170 | 105 | 5 | HarvestCraft.java:132 |
| 3 | com.pam.harvestcraft.GardenRecipeHandler |
BlockRegistry.pamberryGarden |
166 | 100 | 5 | HarvestCraft.java:133 |
| 4 | harvestcraftGardenDrops |
BlockRegistry.pamberryGarden |
166 | 100 | 5 | HarvestCraft.java:134 |
不一致点:handler #3 的 ID 是完整类名,而 #1/#2/#4 是自定义字符串。delegate.name() 是 ItemPamBlockTool/方块物品的 getUnlocalizedName() 族方法(SRG → 未解析;语义佐证:BlockRegistry.pamanimalTrap.delegate 是某对象的 delegate 字段,.name() 返回字符串并被塞进 NBT 的 itemName)。
2 个 registerCatalystInfo
HarvestCraft.java:135-142 手工构造两个 NBTTagCompound,各含 2 个字段(handlerID、itemName),再发 registerCatalystInfo:
| # | handlerID |
itemName |
来源 |
|---|---|---|---|
| 1 | harvestcraftAnimalTrapDrops |
BlockRegistry.pamanimalTrap.delegate.name() |
HarvestCraft.java:135-137,141 |
| 2 | harvestcraftFishTrapDrops |
BlockRegistry.pamfishTrap.delegate.name() |
HarvestCraft.java:138-140,142 |
这两条的 handlerID 与上表 #1/#2 对应,作用是把动物诱捕机/鱼 Trap 标为 NEI 的"催化剂"(合成必需物)。
func_74778_a / func_74757_a / func_74768_a 均为 SRG → 未解析(NBTTagCompound.setString / setBoolean / setInteger 族方法;语义佐证:入参分别是 String、boolean、int)。
两份 NEIHarvestcraftConfig:都不由本模组注册
源码里有两个同名类,分属不同包,作用完全不同:
| # | 路径 | 行数 | 内容 | 是否被本模组引用 |
|---|---|---|---|---|
| 1 | com/pam/harvestcraft/NEIHarvestcraftConfig.java |
33 | implements IConfigureNEI,在 loadConfig() 里注册 3 组 handler |
否 |
| 2 | com/pam/harvestcraft/compat/NEIHarvestcraftConfig.java |
138 | 同接口,但 loadConfig() 全是 API.hideItem(...) |
否 |
两者都没有 @Mod 注解,也没有任何代码 new NEIHarvestcraftConfig() 或按类名加载它们。 因此这两个类要生效必须由外部(NEI 的配置扫描或别的模组)主动加载。本模组不主动注册。
版本 1:注册 3 组 recipe + usage handler
NEIHarvestcraftConfig.loadConfig()(NEIHarvestcraftConfig.java:16-23)共 6 次 API 调用:
| 类别 | 类 | 调用 |
|---|---|---|
API.registerRecipeHandler |
AnimalTrapRecipeHandler |
:17 |
API.registerRecipeHandler |
FishTrapRecipeHandler |
:18 |
API.registerRecipeHandler |
GardenRecipeHandler |
:19 |
API.registerUsageHandler |
AnimalTrapRecipeHandler |
:20 |
API.registerUsageHandler |
FishTrapRecipeHandler |
:21 |
API.registerUsageHandler |
GardenRecipeHandler |
:22 |
即 3 个 handler 类,各注册一次配方视图和一次用途视图。
getName() 返回 "Pam's HarvestCraft"、getVersion() 返回 "1.3.14-GTNH"(NEIHarvestcraftConfig.java:25-31)。
这三个 handler 类(AnimalTrapRecipeHandler / FishTrapRecipeHandler / GardenRecipeHandler)在本模组内只被这两个 NEIHarvestcraftConfig 引用,没有其它注册途径。
版本 2:隐藏内部方块
compat/NEIHarvestcraftConfig 带 @Optional.Interface(iface="codechicken.nei.api.API", modid="NotEnoughItems")(compat/NEIHarvestcraftConfig.java:12),其 getName / getVersion / loadConfig 三个方法各带 @Optional.Method(modid="NotEnoughItems")(:15,20,25)。这是 FML 的标准"NEI 缺失时不加载这些方法"标注。
loadConfig()(compat/NEIHarvestcraftConfig.java:26-135)的内容是连续的 API.hideItem(new ItemStack(BlockRegistry.<方块>))。
共 109 次 API.hideItem,109 个互不重复的目标方块(已用集合运算核对:调用点数 = 去重后字段数 = 109)。按源码顺序分 4 组:
| 组 | 条数 | 起始行 | 成员 |
|---|---|---|---|
| 机器方块 | 6 | :27-32 |
pamcuttingBoard、pamPot、pamChurnon、pamQuernon、pamGrinder、pamOvenon |
| 果实方块 | 33 | :33-65 |
pamApple、pamAlmond、pamApricot、pamAvocado、pamBanana、pamCashew、pamCherry、pamChestnut、pamCoconut、pamDate、pamDragonfruit、pamDurian、pamFig、pamGrapefruit、pamLemon、pamLime、pamMango、pamNutmeg、pamOlive、pamOrange、pamPapaya、pamPeach、pamPear、pamPecan、pamPeppercorn、pamPersimmon、pamPistachio、pamPlum、pamPomegranate、pamStarfruit、pamVanillabean、pamWalnut、pamGooseberry |
| 作物方块 | 60 | :66-125 |
pamblackberryCrop … pamwaterchestnutCrop(与 MFR 的 PamCrops 同为 60 项) |
| 蛋糕方块 | 10 | :126-135 |
pamcherrycheeseCake、pamcarrotCake、pamcheeseCake、pampineappleupsidedownCake、pamchocolatesprinkleCake、pamredvelvetCake、pamlamingtonCake、pampavlovaCake、pamholidayCake、pampumpkincheeseCake |
6 + 33 + 60 + 10 = 109。
注意:没有隐藏树苗(pam*Sapling)、花园、诱捕机、鱼 Trap、盐矿、市场方块——即上面 IMC 那 4 个 handler 所对应的方块在 NEI 中仍然可见。
源码缺陷 / 观察
| 位置 | 问题 |
|---|---|
NEIHarvestcraftConfig.java(根)与 compat/NEIHarvestcraftConfig.java |
同名类、不同包、两份实现,且行为完全不同(一份注册 handler,一份隐藏方块)。若外部按简单类名加载,只会命中其中一份。 |
HarvestCraft.java:133-134 |
handler #3 的 ID 是类名 com.pam.harvestcraft.GardenRecipeHandler,#4 才是 harvestcraftGardenDrops,两者 itemName 相同(都是 pamberryGarden)且宽高一致。ID 命名不统一。 |
HarvestCraft.java:131-142 |
全部无条件发送,无 Loader.isModLoaded 保护,也无配置开关(与 Crayfish 的 enablemrcrayfishcompatibility 不同)。 |
两个 NEIHarvestcraftConfig |
均无 @Mod、无主动注册点 —— 属于"写了但本模组不接线"的状态。 |