EnderStorageRecipe

基本信息

属性 值
类 codechicken.enderstorage.common.EnderStorageRecipe
接口 IRecipe(RecipeSorter.Category.SHAPED,id enderstorage:recolour)
注册点 EnderStorageProxy.init → EnderStorageRecipe.init()
配方数量 49 条(1 条改色 + 16×3 = 48 条颜色基础)+ 0/1 条原版 ender chest 配方
OreDictionary 16 色染料全部按 dyeBlack/Red/Green/.../White 字符串匹配

功能

EnderStorageRecipe 是 EnderStorage 全部合成配方的注册入口,负责三件事:

  1. 注册一个 6 槽的"染色"工作台配方(enderstorage:recolour)。
  2. 注册 16 色 16 条 Ender Chest / 16 条 Ender Tank / 16 条 Ender Pouch 的基础合成。
  3. removeVanillaChest(disable-vanilla=true 时由 proxy.preInit 调用)替换/移除原版 Blocks.ender_chest 的物品并清理所有合成输出为 Blocks.ender_chest 的合成配方。

改色配方(enderstorage:recolour)

工作台布局(6 槽):

. X .   ← 第 row 行放 1 个 Ender Chest/ItemEnderStorage(Pouch 不可染色)
Y D Y   ← 第 row+1 行放 1 个染料(左侧红/中绿/右蓝)
. X .

代码侧只支持"左列 + 染料行"或"右列 + 染料行"两种 layout(offsetMatchesDyes(col=0, row) 双重循环);最终输出是一个 freq 分量被改写、其它分量保留的 Ender Chest/ItemEnderStorage(Pouch 不参与)。Pouch 在合成中只能作为"染色基础物品"的来源:但 stackMatches 检查的是 Item.getItemFromBlock(EnderStorage.blockEnderChest),所以 Pouch 不能被这个配方染色。

matches

for (int row = 0; row < 2; row++) if (offsetMatchesDyes(ic, 0, row)) return true;
return false;

offsetMatchesDyes(ic, col, row)

  • 必须位置 (col+1, row+1) 是 Ender Chest/ItemEnderStorage(任何 freq)。
  • 整张 3×3 网格除了"(col+1, row+1) 这个 Ender Chest"以及"染料行的 3 格"以外必须为空。
  • 染料行(i=row)必须至少有一个染料(16 个 OreDictionary 名字 + Items.dye + EnderStorageDyeTool)。

getCraftingResult

recolour(0, row, freq, ic)、recolour(1, row, freq, ic)、recolour(2, row, freq, ic) 对每个颜色分量取"该位置是否放了染料"决定是替换还是保留,最后输出 getFreqFromColours(colour3, colour2, colour1) | (freqownerDamage & 0xF000)(保留种类 meta)。

注意 getFreqFromColours(c3, c2, c1) 三个参数顺序与 addTraceableCuboids 中的 subHit 顺序一致(subHit=1→c1、subHit=2→c2、subHit=3→c3),但 getCraftingResult 这里传的是 (c3, c2, c1)——这是 EnderStorage 配方设计上的一个反向语义:工作台中"左列染料=subHit 1"(红/高 4-bit)、“右列染料=subHit 3”(蓝/低 4-bit)。

基础合成(addNormalRecipies,16 色 ×3 = 48 条)

Ender Chest

b W b
O C O
b p b
  • b = Items.blaze_rod
  • W = Blocks.wool(meta 0–15,循环 16 次)
  • C = Blocks.chest
  • O = Blocks.obsidian
  • p = Items.ender_pearl
  • 输出:enderstorage:enderChest(meta=0),freq = getFreqFromColours(i, i, i)。

Ender Tank

同 Ender Chest 模板,把 C 换成 Items.cauldron:

  • 输出:enderstorage:enderChest(meta = 1 << 12),freq = getFreqFromColours(i, i, i)。

Ender Pouch

b l b
l p l
p b W
  • b = Items.blaze_powder
  • l = Items.leather
  • p = Items.ender_pearl
  • W = Blocks.wool(meta 0–15)
  • 输出:enderstorage:enderPouch,freq = getFreqFromColours(i, i, i)。

模板字符行数为 4 而工作台只有 3 行——由代码生成的配方面板表示 4 行字符串("blb"/"lpl"/"pb"/"bWb")但 Forge 的 shaped 模板会把第 4 行当成无字符的位置(直接被默认跳过);实际配方效果取决于 RecipeSorter.Category.SHAPED 的长度定义。可以理解为把 blb/lpl/pb/bWb 看作"前 3 行实际在工作台 + 第 4 行注释",或者看作 4 行 but only first 3 in grid。

removeVanillaChest

仅在 EnderStorage.disableVanillaEnderChest = true 时调用:

  1. GameDataManipulator.replaceItem(Block.getIdFromBlock(Blocks.ender_chest), new ItemEnderChestDummy()) —— 把原版 ender chest 的物品替成空实现的 dummy(保留可合成性但不放置方块)。
  2. 遍历 CraftingManager.getInstance().getRecipeList(),删除所有输出为 Blocks.ender_chest 的配方。
  3. 如果 EnderStorage.removeVanillaRecipe = false,重新注入原版配方("OOO" / "OeO" / "OOO")。
  4. 如果 EnderStorage.removeVanillaRecipe = true,原版配方就永远被删除。

该方法使用 codechicken.core.featurehack.GameDataManipulator 直接改写游戏注册表(runtime hack),不持久化到世界数据。

getDyeType(ItemStack item)

按顺序匹配:

  1. Items.dye → itemDamage
  2. 16 个 OreDictionary 名字(dyeBlack/dyeRed/…/dyeWhite)→ OreDictionary.itemMatches(target, item, false)
  3. EnderStorageDyeTool → 调 getDye(item)
  4. 都不匹配返回 -1

getDyeColour(String) 反向查表:根据 oreDictionaryNames[i].substring(3)(剥掉 dye 前缀)与字符串对比(不区分大小写),返回 0–15;找不到返回 -1(被 /enderstorage 命令用来校验三色字符串)。

第三方 mod 集成

  • CodeChickenCore:GameDataManipulator(来自 codechicken.core.featurehack)做注册表替换。
  • OreDictionary:所有 16 色染料 + EnderStorageDyeTool 在 getDyeType 路径中都可被识别,所以其他 mod 注册为标准染料的物品同样可用。
  • DreamCraft:当 Loader.isModLoaded("dreamcraft") 时 addNormalRecipies() 整体跳过,依赖 DreamCraft 自带的 GTNH 配方。

相关条目