总览
测试结果
在独立服务器上进行了实时测试(Live test),服务器上有 3 个活跃玩家在线,运行的自定义 Forge 整合包有 200 多个模组外加 [BACAP]BlazeandCave's Advancements Pack(添加了超过 950 个进度)。使用 火花 (spark) 收集了一小时的统计数据。
使用 Icterine,InventoryChangeTrigger 的执行速度大约提高了 2.5 倍(从版本 1.1.0 开始),花费的时间大约占刻时间的 7.5%,不使用 Icterine 时这个数字是 20%。
使用 Icterine 1.0.0 的统计数据比较(快约 2 倍):
原版 InventoryChangeTrigger 的运行逻辑
当游戏检测到玩家物品栏中的堆叠物品(即一格内堆叠的物品)发生改变时,它会为此调用 InventoryChangeTrigger。这种改变包括拾取物品、丢弃物品、丢弃整份堆叠物品(即“清空”,不一定达到堆叠上限)、在物品栏中移动物品。
此外,当你打开容器(箱子、熔炉等)时,游戏会认为物品栏中的所有槽位都发生了改变,并为所有槽位(包括空槽位)调用触发器。
InventoryChangeTrigger 会对物品栏中的槽位进行计数,无论它是空的、非空的、完整堆叠(即“一组”,达到堆叠上限)的。此信息可用于进度触发器,但在原版中没用过。
InventoryChangeTrigger 会检查已注册进度的准则(criterion)。
如果准则具有槽位数要求且它们与步骤 2 中的值不匹配,或准则没有物品要求,则将跳过该准则。
如果准则只有一项要求,则根据此要求检查发生改变的堆叠物品。
如果准则有多项物品要求(例如,“残骸裹身”要求玩家拥有下界合金套),则物品栏中的所有堆叠物品都会根据每个要求进行检查(但已满足的要求将被移除,并且不再检查)。
物品匹配(特别是针对标签的)非常吃性能。但游戏首先检查玩家的物品类型是否符合要求,然后才检查其他参数,如堆叠数、魔咒和其他 NBT 数据。
Icterine 的优化逻辑
在步骤 1 中,丢弃堆叠物品或将它们移出物品栏(例如放入箱子)时,不再调用 InventoryChangeTrigger。此项可由配置文件中的参数 ignore_triggers_for_emptied_stacks 控制。
同样,如果堆叠物品改变的原因是减少堆叠数(例如,玩家从一组物品中丢弃了一件物品)而非清空,也不再调用 InventoryChangeTrigger。可由 ignore_triggers_for_decreased_stacks 控制。
如果堆叠物品的堆叠数增加了,但尚未超过任何进度的阈值,也不再调用 InventoryChangeTrigger。举个例子:泥土的堆叠数从 52 增加到 53,但整合包中并没有进度要求你获得 53 块泥土。可由 optimize_triggers_for_increased_stacks 控制。
修改游戏在玩家打开容器屏幕时,检查发生改变的物品的方式,以便在你打开任何容器时,游戏不会将所有堆叠物品视为已改变。可由 initialize_inventory_last_slots 控制。
在步骤 6 中,首先检查发生改变的槽位是否符合任何要求,然后才检查物品栏中的其他堆叠物品。可由 optimize_multiple_predicate_trigger 控制。
在步骤 7 中,首先比较堆叠物品的堆叠数,以避免不必要的标签匹配。还使用了之前的堆叠数来避免更多不必要的匹配。可由 check_count_before_item_predicate_match 控制。
进一步的优化已在计划中。