配方自动完成
了解 Pylon 如何防止物品自动补全到原版配方中
最后更新时间
作者:Vaan1310
为了避免 Pylon 物品被自动补全到原版配方中,我们必须使用 NMS 并覆盖两种行为:
- 物品移入制作台
- 配方的匹配(核算)逻辑
起点
我们监听 PlayerRecipeBookClickEvent 并获取正在处理的 NMS 数据。
修复移动逻辑
HandlerRecipeBookClick 是承载核心逻辑的类。
因为很多其他功能也依赖配方书,所以我们只处理制作台相关的场景。
HandlerRecipeBookClick#handlePylonItemPlacement 方法负责处理物品放置逻辑。我们有自己的实现,但正常情况下这个流程由 AbstractCraftingMenu 中的方法处理,所以我们需要通过反射来调用原有行为,只替换我们需要修改的部分。
为了性能优化,这里的高频调用全部使用了 MethodHandle
ServerPlaceRecipe 处理物品移动和核算的核心逻辑,但大部分方法是私有的,所以我们自己实现了一个版本,把大多数行为委托给 NMS 原有类。
顺着私有方法调用链往下追(这些方法我们没法覆写):tryPlaceRecipe → placeRecipe → moveToGrid → findSlotMatchingCraftingIngredient,最终找到了我们的目标。
目标是在 ItemOrExact.Item 匹配时排除 Pylon 物品。
Minecraft 以 2 种方式匹配物品:
- ItemOrExact.Item(基于 Material 的匹配),
- ItemOrExact.Exact(pdc 和 component,完全匹配)。
修复匹配逻辑
现在物品不会错误地移入制作网格了,但配方也不会报错——这种情况下我们需要发送一个虚影(ghost)配方,这由 StackedItemContents#canCraft 处理。
StackedItemContents 用自己的方式逐个核算库存中的物品。我通过反射给它加了一个临时方法 accountPylonItems,让 Pylon 物品堆栈始终按 ItemOrExact.Exact 方式处理。