无限催化剂配方替换(核心机制)

基本信息

属性 值
所属 Eternal Singularity(modid eternalsingularity)
发生阶段 postInit(CommonProxy.postInit,CommonProxy.java:66-127)
作用对象 Avaritia 的 Grinder.catalyst(无限催化剂)配方
产物 交给 Eternal Singularity 的 ShapelessOreRecipe

这是本 mod 的唯一实质功能:把散落在 Avaritia 无限催化剂配方里的 各种奇点抽走,改造成一个需要「集齐全部奇点」的聚合配方。

执行步骤

1. 前置判定(CommonProxy.java:67-70)

if (classSet.isEmpty() || craftingOnly) {
    classSet = null; // Destroy reference
    return;
}

两个条件都会直接 return,不打任何日志:

条件 含义
classSet.isEmpty() 名单里的奇点物品类一个都没找到(见 奇点物品类名单)
craftingOnly Avaritia 的 fox.spiteful.avaritia.Config.craftingOnly 为真(仅合成模式)

⚠️ 早退时 eternalSingularityRecipe 保持 null, 但 preInit 已注册的 EternalSingularityItem 仍在创造栏里 —— 物品存在但无配方。

2. 抽取奇点(CommonProxy.java:71-81)

遍历 Grinder.catalyst.getInput(),对每个 ItemStack 取 getItem().getClass(), 若该类在 classSet 中则 iterator.remove() 移除,并 .copy() 存入 singularities。

细节 说明
匹配依据 物品的 Java 类,不是注册名、不是 ItemStack 相等
meta / NBT .copy() 保留原 meta;判定只看类
重复项 若无限催化剂里同一奇点出现多次,每份都单独收集

因为是移除,Avaritia 原无限催化剂配方里就不再有这些奇点了。

3. 构建聚合配方(CommonProxy.java:98-101)

(eternalSingularityRecipe = new ShapelessOreRecipe(
        new ItemStack(EternalSingularityItem.instance,
                easyMode ? MathHelper.clamp_int(compoundMax, 1, 64) : 1)))
    .getInput().addAll(singularities);

无序配方,输出 1 个(或 easyMode 下 16 个)永恒奇点。

4. 挂载与回填(CommonProxy.java:123-124)

ExtremeCraftingManager.getInstance().getRecipeList().add(eternalSingularityRecipe);
Grinder.catalyst.getInput().add(new ItemStack(EternalSingularityItem.instance));

聚合配方进 Avaritia 终极合成管理器;同时把永恒奇点本身 加回无限催化剂配方,形成「聚合 ↔ 无限」的双向闭环。

最后 classSet = null(行 126)主动断开引用。

依赖

代码直接 import Avaritia 内部类(CommonProxy.java:3,22-23):

类 用途
fox.spiteful.avaritia.Config.craftingOnly 仅合成模式判定
fox.spiteful.avaritia.crafting.ExtremeCraftingManager 挂载聚合配方
fox.spiteful.avaritia.crafting.Grinder 无限催化剂配方本体

@Mod 声明 required-after:Avaritia(EternalSingularityMod.java:30), 所以 Avaritia 缺失时 FML 直接拒绝加载,本 mod 无法单独运行。

已知源码问题

  • 早退完全静默:行 67-70 两个失败条件都不打日志。 表现是「创造栏里有永恒奇点但怎么都做不出来」,玩家无从判断原因。
  • 配方为 null 时脚本 API 会 NPE:EternalRecipeTweaker 在 preInit 就注册(CommonProxy.java:56,仅判 Loader.isModLoaded("MineTweaker3")), 而脚本动作在 postInit 之后才 apply。若本 mod 在行 67 早退, getEternalSingularityRecipe() 返回 null, Add.apply()(EternalRecipeTweaker.java:48)会对 null 调 getInput() 抛 NPE。 源码未做判空。
  • EternalRecipeTweaker.Remove 构造时即遍历:Remove 的构造函数 (EternalRecipeTweaker.java:81-90)在构造阶段就遍历当前输入列表查找匹配项, 而 apply() 在之后才真正 remove(行 94)。若两者之间有其它脚本改动输入, this.itemStack 会是 null,此时 canUndo() 尚返回 false(行 98-100), 但 apply() 已在 remove(null) 上执行 —— 对 ArrayList 而言无害, 源码却未做此防护。
  • craftingOnly 来自 Avaritia 的静态配置字段(行 3 的静态 import), 读取时机在 postInit。若 Avaritia 之后才加载该配置,本 mod 读到的是旧值。

相关条目