矿辞典注册

[!INFO] Git Commit: d3dbd5f | Updated: 2026-10-01

OreDict.register() 是本 mod 唯一的实际功能(由 init 阶段调用,见 mod 元信息与打包数据)。它把 其它 mod 的植物 登记到 crop* 前缀的矿辞典名字下, 使下游作物 mod(BerriesPP)能通过 OreDict.BSget(name, cropCard) 把这些植物注册为 IC2 作物的基础种子。

全仓共 70 次 registerOre 调用、34 个不同的矿辞典名字,其中 20 个以 crop 开头。

注册流程与门控

OreDict.register() 用 isregistered 静态标志保证幂等(OreDict.java:88),执行顺序固定:

顺序 目标 门控方式 生效条件
1 Tinkers’ Construct OreDictRegistrator.register() Loader.isModLoaded("TConstruct")
2 Thaumcraft 同上 Loader.isModLoaded("Thaumcraft")
3 Biomes O’ Plenty 同上 Loader.isModLoaded("BiomesOPlenty")
4 Natura 同上 Loader.isModLoaded("Natura")
5 Witchery OreDict.java:93 显式 if Loader.isModLoaded("witchery")
6 Thaumic Bases OreDictRegistrator.register() Loader.isModLoaded("thaumicbases")
7 浆果聚合(5 个) 无 源矿辞典名非空
8 原版 无门控 总是执行

OreDictRegistrator 是一个只有 2 个方法的接口(OreDictRegistrator.java):

public interface OreDictRegistrator extends Runnable {
    String getModWhichRegisters();
    default void register() {
        if (Loader.isModLoaded(getModWhichRegisters())) run();
    }
}

Witchery 被双重门控:OreDict.java:93 先用 if 判断,RegisterWitchery 自己又实现了 OreDictRegistrator——但 OreDict.java 调用的是 new RegisterWitchery().register(),而 register() 是接口的 default 方法,会再查一次 isModLoaded("witchery")。结论一致,只是多查一次。

原版与浆果聚合不走 OreDictRegistrator,因为它们不依赖任何 mod。

各 mod 登记的具体内容

原版(RegisterVanilla,9 次)

全部用数字 item id,不使用 Item.getItemByName:

矿辞典名 物品 id 1.7.10 对应
cropVine 106 藤蔓
cropVines 106 藤蔓(复数形式,与 cropVine 指向同一条)
cropGrass 32:0 玫瑰丛
cropGrass 31:2 枯萎的灌木
cropGrass 31:1 蕨
cropGrass 175:2 巨型蘑菇(红)
cropGrass 175:3 巨型蘑菇(褐)
cropCacti 81:0 仙人掌
cropCactus 81:0 仙人掌(单数别名)

注意 3 处成对别名:cropVine/cropVines、cropCacti/cropCactus 是同物品的两个名字。 这是为了兼容不同下游 mod 的命名习惯(cropCacti 供 Berry 类 mod,cropCactus 供通用用途)。

Tinkers’ Construct(2 次)

矿辞典名 内容
cropGrass TinkerWorld.slimeGrass meta 0
cropGrass TinkerWorld.slimeTallGrass meta 0

Thaumcraft(3 次)

用 thaumcraft.api.ItemApi.getBlock(name, meta) 取方块:

矿辞典名 内容
cropShimmerleaf blockCustomPlant meta 2
cropCinderpearl blockCustomPlant meta 3
cropGrass blockTaintFibres meta 1

cropGrass 收集的是污秽纤维,不是草——Thaumcraft 没有真正的草方块。

Biomes O’ Plenty(23 次,本 mod 最大的 Register 类)

矿辞典名 内容 次数
cropGrass BOPCBlocks.plants meta 0–3 4
cropGrass BOPCBlocks.foliage meta 1, 2, 5, 7, 9, 10, 11, 12, 13 9
cropVine / cropFloweringVines BOPCBlocks.flowerVine meta 0 各 1
cropVine / cropIvy BOPCBlocks.ivy meta 0 各 1
cropCacti / cropSmallCactus BOPCBlocks.plants meta 12 各 1
cropBerry / listAllberry BOPCItems.food meta 0 各 1
cropEyebulb BOPCBlocks.flowers meta 13 与 14 2

BoP 的 plants 方块 meta 12 同时被登记为 cropCacti(仙人掌)与 cropSmallCactus(小仙人掌), 与原版的 cropCacti/cropCactus 别名策略一致。

Natura(7 次)

矿辞典名 内容
cropSaguaroBerry / listAllberry NContent.seedFood meta 0
cropGooseberry NContent.berryItem meta 3
cropCacti / cropSaguaro NContent.saguaro(不指定 meta,默认 0)
cropVine / cropThornVines NContent.thornVines(不指定 meta)

Witchery(20 次)

分 5 组,全部用 com.emoniph.witchery.Witchery 的常量,物品类以 GENERIC + metadata 区分:

组 矿辞典名 内容
草药 listAllherb SEEDS_GARLIC
蔬菜 listAllveggie GENERIC meta 69
植物 cropGlintWeed Blocks.GLINT_WEED
植物 cropSpanishMoss Blocks.SPANISH_MOSS
植物 cropEmberMoss Blocks.EMBER_MOSS
种子 seedWaterArtichoke / seedWolfsBane / seedMandrake / seedSnowbell / seedBelladonna 5 个 SEEDS_* 常量
种子 listAllseed 同上 5 个,各 1 次
物品 cropArtichoke GENERIC meta 69
物品 itemWolfsBane GENERIC meta 156
物品 itemMandrake GENERIC meta 22
物品 itemSnowbell GENERIC meta 78
物品 itemBelladonna GENERIC meta 21

GENERIC:69 同时被 listAllveggie 与 cropArtichoke 登记,即朝鲜蓟既是蔬菜也是作物。 本类中另有 3 条被注释掉的注册(RegisterWitchery.java:40-41、:47、:50)—— itemWaterArtichoke、itemGypsum、dustQuicklime。这三条并未生效,其中 itemWaterArtichoke 与 cropArtichoke 是同一物品(GENERIC:69),看起来是改用 crop 前缀后的遗留。

Thaumic Bases(1 次)

矿辞典名 内容
nuggetThauminite TBItems.resource meta 0

这是全部 34 个名字中唯一与作物无关的——它登记的是锭(nugget)而非植物, 与本 mod 其余部分的 crop* 模式完全不符,属于功能上的离群项。

浆果聚合(OreDict.java:96-119)

5 段结构完全相同的代码,把已有的 crop* 浆果名复制到 listAllberry:

源矿辞典名 目标
cropBlackberry listAllberry
cropBlueberry listAllberry
cropGooseberry listAllberry
cropRaspberry listAllberry
cropStrawberry listAllberry

每段都是「源列表非空 → 遍历 → 目标列表不含该 ItemStack 才 registerOre」,即去重后再登记。 这 5 个源名字不由本 mod 创建——本 mod 只创建 cropGooseberry(Natura), 另外 4 个必须由 BerriesPP 或其它浆果 mod 先注册。因此这是本 mod 与下游 mod 的唯一数据契约。

cropGooseberry 因此被登记两次:一次由 RegisterNatura 指向 NContent.berryItem:3, 一次由本段复制进 listAllberry。

OreDict 的 3 个工具方法

OreDict 除 register() 外还暴露 3 个静态方法供下游 mod 使用:

ISget(String)(OreDict.java:28-32)

返回该矿辞典名列表的最后一个 ItemStack,列表为空时返回 null。 取"最后一个"而非第一个,意味着依赖 mod 的加载顺序。

BSget(String, CropCard)(OreDict.java:34-48)—— 含一处缺陷

本方法把矿辞典中的物品注册为 IC2 基础种子,是 registerBaseSeed 的唯一调用点:

public static void BSget(String name, CropCard crop) {
    String hname;
    if (OreDictionary.getOres(name).size() != 0) for (int i = 0; ...)
        Crops.instance.registerBaseSeed(OreDictionary.getOres(name).get(i), crop, 1, 1, 1, 1);
    if (name.contains("crop")) {
        hname = name.replace("crop", "seed");
        if (OreDictionary.getOres(name).size() != 0) for (int i = 0; ...)
            Crops.instance.registerBaseSeed(OreDictionary.getOres(name).get(i), crop, 1, 1, 1, 1);  // ← 应为 hname
    }
    if (name.contains("seed")) {
        hname = name.replace("seed", "crop");
        if (OreDictionary.getOres(hname).size() != 0) for (int i = 0; ...)
            Crops.instance.registerBaseSeed(OreDictionary.getOres(hname).get(i), crop, 1, 1, 1, 1);
    }
}

OreDict.java:40-41 是复制粘贴缺陷:crop → seed 分支里算出了 hname,却再次遍历 getOres(name) 而非 getOres(hname)。后果是该分支对同一个 name 重复注册了一遍 (内容与第 36-37 行完全相同),而 crop* 到 seed* 的实际查询从未发生。

对比第 43-47 行的 seed → crop 分支:该分支正确地用了 hname。两个分支写法不对称, 说明第 41 行是笔误而非有意设计。

registerBaseSeed(stack, crop, 1, 1, 1, 1) 的 4 个参数全部硬编码为 1—— 基础种子没有产量、成长速度或营养加成修饰,即"完全按该作物卡的默认值生长"。

get_subtypes(List<Item>, boolean)(OreDict.java:50-84)

枚举某个物品的全部 metadata 变体,用于把"一个 Item + N 个 meta"展开成完整物品列表。 CleanList 为 true 时先用 HashSet 去重。

主动跳过 Binnie 与 Forestry 的物品(OreDict.java:66-67):

if (!((cleansubtypes.get(i).getClass().toString().contains("binnie"))
        || (cleansubtypes.get(i).getClass().toString().contains("forestry")))) {

即这两个 mod 的物品整个被排除,不会进入结果列表。源码未给出原因。

对保留下来的物品,用 do...while(!k) 从 meta 0 开始递增,循环条件(OreDict.java:69-77)在满足 任一情况时停止:当前 meta 与上一 meta 显示名相同、显示名含 .、显示名含当前 meta 数字、 或当前与后两 meta 显示名相同。这是靠启发式推断变体数量,没有上界保护—— 若上述条件始终不成立会一直递增。该方法内唯一的日志调用(:51)已被注释掉。