Arcane Infusion Handler(奥法注入)

基本信息

属性 值
类型 NEI Recipe / Usage Handler
源码类 com.gtnewhorizons.aspectrecipeindex.nei.InfusionRecipeHandler
基类 TemplateThaumHandler
Overlay ID thaumcraft.infusion
界面名 aspectrecipeindex.infusion.title = “Arcane Infusion”
底层配方类型 Thaumcraft InfusionRecipe + TC4RecipeLib 的 EnhancedInfusionRecipe
IMC 关联物品 Thaumcraft:blockStoneDevice:2(符文矩阵,handler 高度 152)
特殊内容 Runic 护甲强化配方(同一 handler 内)

功能:展示奥法注入配方的中心物品、外围材料、essentia 需求与不稳定性数值。

索引数据结构

结构 类型 说明
runicArmor static TreeMap<Integer, ArrayList<ItemStack>> 按 IRunicArmor.getRunicCharge(stack) 分组的护甲物品
aspects(继承自基类) ArrayList<AspectList> 与 arecipes 按下标平行,供 getRecipeHeight 读取

runicArmor 由 NEIConfig.loadConfig() 末尾调用的 static init() 一次性构建:clear() 后遍历整个 Item.itemRegistry,取所有 instanceof IRunicArmor 的 Item;无子类型的直接加一个 new ItemStack(item),有子类型的调 getSubItems(item, item.getCreativeTab(), subItems)(整个调用被 catch (Exception ignored) 包住),为空则退回一个无 meta 的栈。

配方高度

getRecipeHeight(recipe) = 152 + (ceil(元素数 / 7) - 1) * 20。aspectsPerRow 固定为 7。元素多时页面变高,这是"按配方数计算高度"而非固定高度的少数 handler 之一。

加载路径

方法 行为
loadCraftingRecipes(ItemStack) 产物用 areStacksSameTypeCraftingWithNBT 匹配;随后 loadRunicUpgradeRecipe(result)
loadCraftingRecipes(String, Object...) overlay 分支遍历全部 InfusionRecipe(要求 getRecipeInput() != null 且 validOutput),再 loadAllRunicCraftingRecipes()
loadUsageRecipes(ItemStack) 见下

loadUsageRecipes 的三段:

  1. getInfusionRecipesByInput(ingredient) 取匹配配方,逐个过 Util.shouldShowRecipe(recipe.getResearch()),并调用 setIngredientPermutation 高亮命中的材料。
  2. 若输入 instanceof IRunicArmor:charge = EventHandlerRunic.getFinalCharge(ingredient) + 1,在 0 < charge <= Byte.MAX_VALUE 时生成一条"再强化一级"的配方。
  3. 否则若 isRunicUpgradeIngredient(ingredient):一次性生成全部 Runic 强化配方。

getInfusionRecipesByInput 的匹配顺序:中心物品 matches → 外围 RecipeIngredient.matches(整个遍历 catch (Throwable ignored))→ essentia 交集。转换用 InfusionRecipeExt.get().convert(raw),被 try / catch (RuntimeException) { continue; } 包住(源码注释 “keep bad recipe from killing the scan”)。

isRunicUpgradeIngredient 判据:钻石、Thaumcraft ConfigItems.itemResource 的 metadata 14,或 essentia 中含 ENERGY / ARMOR / MAGIC 三者之一。

输出合法性校验

validOutput(InfusionRecipe):

  • ItemStack 且物品非空 → 合法。
  • Object[](无泛型参数)长度 ≥ 2 且首元素是 String → 合法(对应"给原物品打 tagInfo"的配方,源码举例为铋 stronghold 头盔的面板)。
  • 否则返回 false,并打三行警告日志:研究键、中心物品、输出对象。日志前缀固定为 “Invalid output for infusion recipe, please report to Aspect Recipe Index:”。

界面布局

元素 坐标 / 规则
中心物品 (OUTPUT_X, 63) = (75, 63),来自 r.getCentral().getRepresentativeStacks()
外围材料 沿圆周排布:圆心 (27 + 56, -31 + itemOffset() + 102) = (83, 71),半径 40,起始角 -90°,角步长 360 / 材料数
外围贴图 drawIngredientBackground 画符文矩阵 (27, 21, 207, 78, 42, 42),并做 (-0.5, -1, 0) 像素对齐平移
产物 (75, 5)(setResult)或 Runic 的 (75, 5)
元素网格 每行 7 个,baseX = 35,baseY = 130 + itemOffset(),水平间距 20
元素行分配 逆序行 reversedRow = -row + rows - 1,该行列数 (元素总数 + reversedRow) / rows,再按 (100 - 列数 * 20) / 2 居中
元素物品 metadata 1

itemOffset() 目前固定返回 0(保留的扩展点)。

不稳定性显示

drawInstability 在 shouldShowRecipe 为假时不画。

showInstabilityNumber = true(默认):

  • 文本 = tc.inst + 数值(直接拼接,无空格)。
  • 颜色档位 = Math.min(5, instability / 2)(整除),映射到 instability0 ~ instability5。
  • 绘制位置:X 为 83 - 文本宽度 / 2(在 83 处居中),Y = 120。

showInstabilityNumber = false:文本 = tc.inst.<档位>,颜色统一 instabilityOff(白)。详见 颜色常量。

metadata 技巧

Thaumcraft 用 Short.MAX_VALUE(32767)作为物品 metadata 的"跟随输入"标记:

  • getResult() 发现 result.item.getItemDamage() == Short.MAX_VALUE 时调 Items.feather.setDamage(result.item, 0) 改回 0——因为 Items.feather 是 maxStackSize = 1 的物品,可以直接改它的栈内 metadata 当作通用写入器。
  • setIngredientPermutation 覆写:结果 damage 为 Short.MAX_VALUE 且输入物品与结果相同时,用输入的 damage 覆盖结果,实现"结果复制输入子类型"。

Runic 护甲强化配方

RunicShieldCachedRecipe(内部类,继承 InfusionCachedRecipe):

属性 值
研究键 常量 RESEARCH = "RUNICAUGMENTATION"
不稳定性 5 + charge / 2
中心物品 目标护甲(items 列表)
外围材料 1 个钻石 + charge 个 ConfigItems.itemResource(metadata 14)
产物 护甲副本,RS.HARDEN 设为 EventHandlerRunic.getHardening(item) + 1(NBTTagByte)
结果槽备注 源码注明产物槽不显示排列变体,所以只取 items.getFirst()

essentia 成本(setAspects(int charge),源码注释给出公式):

  • charge >= 26 → 不加任何 essentia。
  • 否则 cost = 8 << charge(即 8 × 2^charge):
    • ENERGY(秩序 Potentia)= cost * 2
    • ARMOR(防护 Tutamen)= cost
    • MAGIC(秘法 Praecantatio)= cost

去重策略(见 元素配方索引机制 同类思路):loadAllRunicCraftingRecipes() 按 charge 分组,每个 charge 只生成一条配方并把所有适用护甲塞进中心物品槽。但当玩家搜索某个护甲的用途时,loadUsageRecipes 会单独为它生成一条精确到"再升一级"的配方,所以不会丢失升级信息。

loadRunicUpgradeRecipe(ItemStack) 处理"搜索已强化过的护甲的产物":要求 instanceof IRunicArmor、有 NBT 且 getHardening > 0,复制一份并把 RS.HARDEN 设为 charge - 1(即回退一级显示)。

相关条目