Skip to content

从 21.1.2 升级 ​

Applies to after 21.1.2

MBD2 21.1.2 之后,哪些变化可能让整合包、脚本、蓝图或附属模组出错,或者表现不同。大多数整合包什么都不用改:只有一个配方逻辑、槽位使用默认设置的机器,保存、加载和运行都与以前相同。新增内容见新内容。

依赖要求 ​

依赖21.1.2之后
NeoForge21.1.217+不变
LDLib22.2.39.a+2.2.46+
KilaGraph21.1.0.12+,内置21.1.0.16+,内置
Photon(可选)2.2.5+不变
Astral Sorcery(可选)—2.0.3,它本身需要 Curios 9.5.1+

KilaGraph 打包在 MBD2 的 jar 里,所以每个整合包都会拿到它的新版本,也就带来了下面的蓝图变化。

世界与整合包 ​

这些变化不需要任何代码就会出现。

变化需要检查什么
配方完成时产出放不下,会以满进度等待,直到放得下。21.1.2 及以前放不下的部分会被销毁。产出满了的机器会停下等待,而不是吞掉物品。清空产出,或交给自动 IO。
开启 Consume inputs after working 时,完成时会再检查一遍输入:缺了就丢弃这次配方,不产出。产出放不下时,会先取走输入,再等待。依赖“输入没了也能完成”的机器。
空闲的机器只在有变化时才搜索——槽位、储罐、runtime value、配方重载——否则每 100 tick 搜索一次。配方最多会早约 5 tick 开始。一般无需处理,除非脚本原地修改堆叠(见 KubeJS)。asyncRecipeSearching 现在只对自带搜索的附属模组和 MBD2 无法索引的输入(如 ME 接口)有意义。
随配方一起工作的 handler——Create 转速、热源——在配方停下时总会收到通知:暂停、中断、卸载都算。加载时正在运行配方的机器会重新通知它们开始。Create 机器暂停时会停止转动。
流体储罐的 GUI IO 现在也作用于对它点击的桶。设为仅输出的储罐不再接受倒入的流体。
代理了不存在类型的配方类型,不再阻止其他被代理类型的加载。可能会多出一些被代理的配方。
配方时长至少为 1 tick。修饰器把时长降到 0 时,机器不会再永远工作下去。

存档与降级 ​

  • 主配方逻辑仍保存在原来的位置,所以 21.1.2 的世界照常加载。
  • 额外的线程和额外配方逻辑保存在 recipeLogics.<name>.<thread> 下。删除或改名、减少线程数、或退回 21.1.2,都会丢掉它正在运行的配方,而输入已经被取走了。
  • 超过一组的槽位把超过 99 的数量存在 21.1.2 不读取的字段里:降级后这样的槽位只剩 1 个。
  • 带有保留的 Trait 数据的机器物品,使用了 21.1.2 不认识的数据组件。
  • 工程文件会为新设置增加键。21.1.2 会忽略它们,相当于悄悄关掉了这些功能。

KubeJS 脚本 ​

变化怎么做
每个配方事件都带有 event.recipeLogic;在有多个配方逻辑的机器上,每个逻辑各触发一次。onRecipeStatusChanged 报告的是该逻辑自己的状态;机器状态跟随所有逻辑汇总后的状态。只有一个逻辑的机器无需处理。有多个时,先检查 event.recipeLogic 再行动。见事件页。
onFuelBurningFinish 会触发了,以前它从未到达脚本。原本是死代码的处理函数现在会运行。
原地修改堆叠——getStackInSlot(0).shrink(1)、增加 FluidStack 的数量——不会报告变化,空闲的机器要到下一次 100 tick 的搜索才会发现。使用 insertItem、extractItem、setStackInSlot,或流体 handler 的 fill/drain。
配方等待产出空间时,onRecipeWaiting 每个 tick 都触发,onAfterRecipeWorking 也会推迟。在 onAfterRecipeWorking 里中断会丢弃这次配方、不产出;以前它会反复重入这个事件,直到服务器崩溃。假定“完成就一定有产出”的处理函数。
recipeLogic.setStatus(...) 会让随配方工作的 handler 开始和停止。强制设置状态现在也会停掉 Create 转速之类。
开启 Ignore item stack limit 时,getStackInSlot 可能返回超过物品堆叠上限的堆叠;extractItem 每次最多取一组。从这些槽位读取数量的脚本。

配方 schema 新增:inputLumen、outputLumen、inputStarlight 以及三个 Astral Sorcery 条件。

蓝图 ​

变化怎么做
KilaGraph 21.1.0.16:纯节点会为每个读取它的执行节点各运行一次,以前每次执行只运行一次;在流程、循环或子图之后的读取会看到最后一次写入。在同一次执行里根据自己修改的东西计算值的图——例如把 n + 1 写回一个被多个节点读取的标签——结果会不同。先把值存进变量。
KilaGraph 21.1.0.16:NBT 设置节点直接写入传给它的标签,并有 copy 引脚;新增 NBT Copy 节点用来复制标签。修改不属于自己的标签前先复制。
Recipe Info → Data 和实体材料的 NBT 节点给出的是副本,修改它不再改变所有机器共用的配方。要修改配方:Copy Recipe,修改副本,再 Set Event Recipe。
Machine Info → Custom Data 有了 copy 输入。默认关闭,给出机器自己的标签,与以前相同。图要修改这个标签、又不能改动机器的标签时开启它。
逻辑输入不连线的配方逻辑节点,作用于正在处理的配方事件的逻辑,否则作用于机器的所有逻辑;读取逻辑的节点读取事件的逻辑,否则读取主逻辑。只有一个逻辑的机器无需处理。见配方逻辑节点。
Fuel Burning Finish 入口节点会触发了。连到它的图会开始运行。
内置的 mbd2:auto_io_panel 图针对 KilaGraph 21.1.0.16 做了修复。使用内置图的机器自动获得修复;从 21.1.2 复制出来的副本不会,需要重新复制内置图。

Java 附属模组 ​

为 21.1.2 编写的自定义配方 capability、Trait 和 handler 无需任何修改就能照常工作;想让它们搜索得更快可以加些什么,见配方搜索与自定义扩展。

破坏性变化 ​

变化怎么做
ItemSlotCapabilityTrait.storage 的类型是 LargeItemStackTransfer;createStorage() 返回它,shouldSyncStorage 接受它。重新编译。已编译的附属读取这个字段会抛出 NoSuchFieldError,旧的 createStorage() 重写会被悄悄跳过。
配方匹配和 IO 收到的 IRecipeCapabilityHolder 是 RecipeLogic,而不是机器:matchRecipe、matchTickRecipe、handleRecipeIO、applyParallel。把 holder 强转为 IMachine 的代码会失败:先判断是否为 RecipeLogic,再用它的 getMachine()。
MBDRecipe.ActionResult.FAIL_NO_REASON 是失败,以前被当成成功。依赖它通过的代码。没有任何 handler 的机器上,没有内容需要匹配的配方仍然通过。

行为变化 ​

变化怎么做
MachineRecipeStatusChangedEvent 由新增的 onRecipeLogicStatusChanged(logic, old, new) 发布,每个逻辑一次。旧的 notifyRecipeStatusChanged(old, new) 只在机器的汇总状态变化时运行,它负责设置机器状态。IMultiPart.notifyControllerRecipeStatusChanged(controller, old, new) 收到的也是汇总状态,新增的重载收到每个逻辑的状态。通过不调用 super 来屏蔽事件的旧 hook 重写不再有效。
handler 通过 MBDRecipe.preWorking(RecipeLogic) / postWorking(RecipeLogic, List) 开始和停止,在取走输入之后,且各恰好一次。基于 holder 的 preWorking(holder) / postWorking(holder) 不再被调用。自己调用旧方法的 RecipeLogic 子类会让 handler 收到两次通知。
搜索通过配方索引进行。重写了 RecipeLogic.searchRecipe() 或 MBDRecipeType.searchRecipe(...) 的附属保留原来的完整搜索。内置物品、流体、能量或化学品 Trait 的子类会继承 notifiesAllChanges() == true 以及从 storage 读取的查找键。如果它修改内容时不发通知,或从别处消耗,就把两者重写为返回 false / null。见配方搜索与自定义扩展。
主逻辑有了名字:MBDMachine.createRecipeLogic(Object...) 用定义里的名字创建它,createRecipeLogic(settings, name, thread) 创建其余的逻辑。返回 new MyLogic(this) 的重写会以 main 运行,即使编辑器给主逻辑改了名,作用域和 UI 地址就对不上了。把名字传下去。
IMultiController 把配方所属的逻辑交给 modifyControllerRecipe 和 getMaxControllerParallel。MBDMultiblockMachine.initCapabilitiesProxy 最后会调用 rebuildRecipeLogicProxies()。不调用 super 的重写必须自己调用它。
MBDRecipe.toBuilder() 不再从配方类型的模板开始,所以模板的内容和条件不会再被加两次。构建出的配方不再与 builder 共享列表,copy() 会保留 tier chance boost、XEI 隐藏和优先级。依赖重复模板的代码。

新增 ​

IMachine 的每个配方 hook 都有一个以 RecipeLogic 为首个参数的重载;默认实现调用旧 hook,所以为单个逻辑编写的机器类照常工作。附属类里如果有同名但返回类型不同的方法,将无法再编译。事件实现了 RecipeLogicEvent,旧的构造函数保留。新的 hook 见在 Java 中使用多个配方逻辑、自定义 Trait 和自定义配方能力。

Released under the MIT License.