原料转换

GTTweaker 提供两条静态转换方法,把 CraftTweaker 的 IIngredient 转成 GregTech 5 需要的 ItemStack / FluidStack。全 mod 的 55 台机器类与 RA2 Builder、Recipe Remover 都间接依赖这两条路径。

基本信息

属性 值
类 gttweaker.GTTweaker
方法 1 public static ItemStack getItemStackOrNull(IIngredient ingredient)
方法 2 public static FluidStack getFluidStackOrNull(IIngredient ingredient)
行数 20(GTTweaker.java:146-159)
使用者 56 个类通过方法引用(GTTweaker::getItemStackOrNull)间接调用

getItemStackOrNull(:146-153)

Object internal = ingredient.getInternal();
if (internal instanceof ItemStack) return (ItemStack) internal;
else if (internal instanceof String)
    return OreDictionary.getOres((String) internal).size() > 0
        ? OreDictionary.getOres((String) internal).get(0) : null;
return null;
internal 类型 返回 风险
ItemStack 原对象(同一引用,未 copy) 调用方若修改会污染原 ingredient
String(矿辞典名) OreDictionary.getOres(name).get(0) —— 静默取第一个 见下
其他(如 FluidStack、List<IItemStack>) null 静默

getFluidStackOrNull(:155-159)

Object internal = ingredient.getInternal();
if (internal instanceof FluidStack) return (FluidStack) internal;
return null;

不处理矿辞典:流体在 CraftTweaker 中本就没有 ore dict 形式。IIngredient 若内部是 ILiquidStack 会被 AddMultipleRecipeAction 提前转成 FluidStack 再存入,本方法只处理这一路径。

三种失败模式

模式 触发条件 后果
静默取第一个 矿辞典含多个变体 配方只用了某一个具体物品,其余变体(可能是更便宜的替代)被无视,无日志
返回 null 被 filter 掉 矿辞典为空 / 类型不匹配 参数数量减少 → 见 Recipe Remover 的过度匹配风险;机器类中则可能 itemInputs(null) NPE
同一引用 internal instanceof ItemStack 调用方 recipeBuilder.itemInputs(stack) 若持有引用,后续修改会影响原 ingredient

数值

数值 值
静态转换方法数 2
支持的 internal 类型 ItemStack / String(物品);FluidStack(流体)
矿辞典取法 getOres(name).get(0) —— 第一个,无排序保证
空矿辞典 返回 null
返回值是否 copy 否(ItemStack 分支直接返回原引用)
失败时是否有日志 否(全部静默)
流体的矿辞典支持 无

源码缺陷

  • 矿辞典静默取第一个变体(:150-151):OreDictionary.getOres(name).get(0)。矿辞典的注册顺序由各 mod 的加载顺序决定,因此同一脚本在不同 mod 组合下可能生成不同的配方。这在打包整合包中是难以排查的问题。源码无注释、无日志。
  • 调用两次 OreDictionary.getOres(:150 与 :151):getOres 每次返回一个新的 ArrayList(1.7.10 行为),因此有一次多余的列表分配 + 完整拷贝。size() > 0 与 get(0) 应合并为一次调用。
  • 返回 null 后由调用方 filter(nonNull) 静默丢弃:RA2Builder 的 4 个数组方法与 RecipeRemover.remove 都用 .filter(Objects::nonNull)。后果分两种:
    • RA2Builder.itemInputs([<不存在的ore>]) → 传入空数组给 builder(不是 null),可能写出无输入的配方。
    • RecipeRemover.remove(map, [<不存在的ore>], []) → 查询条件被削弱,可能删掉一条与预期完全不同的配方。
  • ItemStack 分支不 copy:return (ItemStack) internal;。GTRecipeBuilder.itemInputs 在 GT5 中会保存引用。CraftTweaker 的 IItemStack 内部 ItemStack 通常是脚本创建的新对象,但若来自 IIngredient 的缓存可能被复用。
  • 无 @Nullable / 无异常:两条路径都靠返回 null 表达失败,与 AddMultipleRecipeAction 里三个抛异常的校验风格相反(同仓库两种失败表达方式并存)。
  • 方法名 OrNull 表明作者知晓会返回 null,但没有任何调用方检查 null(除了 filter)。
  • getFluidStackOrNull 不处理 List<FluidStack>:CraftTweaker 的 ILiquidStack 内部可能是列表(当 <ore:...> 类写法产生多流体时),本方法直接返回 null,与物品侧的矿辞典支持不对称。
  • 两条方法放在 @Mod 主类而非工具类:它们是通用转换逻辑,却绑在模组入口类 GTTweaker 上,测试与复用不便。对比 util/ArrayHelper 有独立工具类但反而是死代码。

相关条目