复合奇点模式(9 合 1 分组)

基本信息

属性 值
所属 Eternal Singularity(modid eternalsingularity)
开关 配置 useCompoundSingularities(见 配置项)
常量 compoundMax = 16(CommonProxy.java:97)
代码位置 CommonProxy.java:102-122

奇点种类多时,聚合配方的输入会过长(原版 GUI 3×3 摆不下)。 复合模式把全部奇点按 每 9 个一组打包成最多 16 个 Compound Singularity, 再用「16 个复合奇点」作为聚合配方的新输入。

分组算法

CommonProxy.java:107-118:

for (int i = 0; i < compoundMax; i++) {          // i = 0..15
    final ShapelessOreRecipe compoundRecipe = new ShapelessOreRecipe(
            new ItemStack(compoundSingularityItem, 1, MathHelper.clamp_int(i, 0, 64)));
    for (int s = 0; s < 9; s++) {
        final int pos = 9 * i + s;
        if (pos > singularityCount - 1) break;
        final Object input = eternalSingularityRecipeInputs.get(pos);
        if (!(input instanceof ItemStack)) continue;
        compoundRecipe.getInput().add(((ItemStack) input).copy());
    }
    if (!compoundRecipe.getInput().isEmpty()) GameRegistry.addRecipe(compoundRecipe);
}
规则 值
每组容量 9 个基础奇点
组数上限 16(compoundMax)
总容量 9 × 16 = 144 个基础奇点
分组依据 抽取顺序(singularities 列表下标),不是按种类,同类可分散在不同组
输入类型 ItemStack.copy(),按物品类型计数,不区分 meta/NBT
空组 if (!compoundRecipe.getInput().isEmpty()) 跳过,不注册空配方(行 117)

替换聚合配方输入(行 119-121):

eternalSingularityRecipeInputs.clear();
for (int i = 0; i < compoundMax; i++)
    eternalSingularityRecipeInputs.add(new ItemStack(compoundSingularityItem, 1, i));

已知源码问题:可合成性缺口

聚合配方无条件要求全部 16 个复合奇点(行 120-121 的循环不看 该档位是否有配方),但只有非空档位才有合成配方(行 117)。 因此当基础奇点数量 singularityCount 不足时, 永恒奇点配方会引用无法获取的复合奇点 → 整条聚合配方做不出来。

按代码推算,meta 15 需要的首个下标是 9*15 = 135, 而循环条件是 pos > singularityCount - 1 才 break, 故需要 singularityCount >= 136 才能让 16 档全部非空。

而自动启用阈值是 singularityCount > 81(CommonProxy.java:84), 81 < 136。即当奇点数量落在 82–135 区间时:

  • useCompoundSingularities 被强制为真(行 90 的 || aboveTheLimit)
  • 只有前 ⌈N/9⌉ 档有配方
  • 聚合配方却要求 16 档 → 永恒奇点不可合成

源码未对「档位总数 < compoundMax」做任何回退或裁剪。 实际整合包通常奇点数量远超 136,故该缺陷不易触发。

其它源码问题

  • 分组顺序依赖抽取顺序:singularities 的顺序来自对 Grinder.catalyst.getInput() 的遍历顺序(见 无限催化剂配方替换), 而该顺序由 Avaritia 及其它 mod 的注册顺序决定。 因此同样的奇点集合在不同整合包/不同加载顺序下可能被分到不同档位, 复合奇点的 meta 与内容不保证稳定对应。
  • 物品在 postInit 才注册(行 103-105), 但 Class/ItemStack 引用在 EternalItemRenderer 注册时判空处理 (ClientProxy.java:15),逻辑上没错,但使该物品无法被其它 postInit 更早的 mod 依赖。
  • MathHelper.clamp_int(i, 0, 64) 是冗余的(行 109): i 来自 for (i = 0; i < compoundMax=16; ...),恒在 0–15 内, clamp 永远不会改变取值。属防御性死代码。

相关条目