智能工作台背包配方
[!INFO] 注册真源:
RecipeHelper.registerRecipes()末尾GameRegistry.addRecipe(new RecipeIntelligentWorkbenchBackpack())实现类:de.eydamos.backpack.recipes.RecipeIntelligentWorkbenchBackpack
基本信息
给 工作台背包 打上 intelligent NBT 标记的配方。
| 属性 | 值 |
|---|---|
| 配方尺寸 | getRecipeSize() 返回 2 |
| 形状 | 任意 2 格(一个包 + 一本书) |
| 注册条件 | 无条件,不受任何 DISABLE_* 开关控制 |
| NBT 键 | Constants.NBT.INTELLIGENT = "intelligent" |
匹配逻辑(RecipeIntelligentWorkbenchBackpack.matches)
for (int i = 0; i < craftingGridInventory.getSizeInventory(); i++) {
slotStack = craftingGridInventory.getStackInSlot(i);
if (slotStack != null) {
if (slotStack.getItem() instanceof ItemWorkbenchBackpack) {
if (backpack != null) return false; // 不允许两个包
backpack = slotStack;
} else if (slotStack.getItem() == Items.writable_book) {
if (book) return false; // 不允许两本书
book = true;
} else { return false; } // 其它物品一律拒绝
}
}
if (backpack != null && book) {
result = backpack.copy();
NBTItemStackUtil.setBoolean(result, Constants.NBT.INTELLIGENT, true);
}
要点:
- 空槽被静默跳过(
if (slotStack != null)无 else 分支), 所以合成栏里只放这 2 个物品即可,其余 7 格留空。 - 唯一合法的书是
Items.writable_book(可写书,即书与笔), 不是written_book(已写书)。 - 结果是背包的
copy()—— UUID 保留,不丢容器数据。
intelligent 标记是一次性中转,会被事件处理器回收
这是本配方最容易被误解的地方:intelligent 不是写死在物品上的永久标签,
而是在合成瞬间挂到输出栈上、随后由事件处理器转存进背包存档的中转标记。
流程分三步:
- 配方(
RecipeIntelligentWorkbenchBackpack:46)把INTELLIGENT写到result这个刚生成的 ItemStack 上:NBTItemStackUtil.setBoolean(result, Constants.NBT.INTELLIGENT, true);
- 事件(
EventHandlerBackpack.itemCrafted:132,@SubscribeEvent)在ItemCraftedEvent中检测到该标记后,把它转存进BackpackSave:BackpackSave backpackSave = new BackpackSave(craftedItem); backpackSave.setIntelligent(); // 写进存档 NBT NBTItemStackUtil.removeTag(craftedItem, Constants.NBT.INTELLIGENT); // 回收中转标记
- 持久化(
BackpackSave.setIntelligent:125)写入NBTUtil.setBoolean(nbtTagCompound, Constants.NBT.INTELLIGENT, true), 并在非手动保存模式下立即save()。
因此:
- 背包存档 NBT 里长期保留
intelligent,tooltip 由此显示tooltip.intelligent(ItemWorkbenchBackpack:61)。 - 物品栈顶层的那个中转标签在合成完成后即被移除,
直接在物品 NBT 里看到
intelligent的「裸标签」是不该出现的中间态。 - 事件处理器只在物品是
ItemsBackpack.workbenchBackpack时才处理, 所以这个中转标记对本配方是专属的。
⚠️ 死常量:Constants.NBT.RECIPES 与 NBT.RECIPE 从未被使用
Constants.NBT 中声明了:
public static final String INVENTORY_RECIPES = "recipes";
public static final String INVENTORY_RECIPE = "recipe-";
全仓 grep 后没有任何 Java 代码读取或写入这两个键(Constants.NBT.RECIPES
/ NBT.RECIPE 在 src/main/java 下零引用)。
即本模组没有「自动记忆上次摆放的配方」功能 —— 名称中的 intelligent
仅代表上面这个标记机制本身。任何关于配方记忆的说法都与源码不符。
书不被消耗
result 只复制背包,书既不进入结果也不减少数量。
对已带 intelligent 的背包再放一次,只会重复走一次
「转存 → 回收中转标签」的无害流程,最终状态不变。
与其它两个自定义配方的对照
| 配方 | 尺寸 | 是否要求满格 | 是否可递归应用 |
|---|---|---|---|
RecipeEnhanceBackpack |
9 | 是(9 格全满) | 改变 metadata |
RecipeRecolorBackpack |
不限 | 否 | 改变 metadata |
| 本配方 | 2 | 否(空槽跳过) | 幂等,仅置标记 |
三者都无条件或近乎无条件注册,但只有升级配方受 DISABLE_BIG_BACKPACKS 控制。