跳到正文
烈焰甘蔗Wiki

Crucible Recipes

Crucible crafting is performed at the Crucible and transforms items by cooking them in aspect-tagged liquid. It is the primary way to create alchemical ingredients and some Thaumcraft components.

Registration

ThaumcraftApi.addCrucibleRecipe(String key,       // Research key
    ItemStack result,     // Output item
    Object catalyst,      // ItemStack, String (Ore Dict), or ArrayList<ItemStack>
    AspectList tags)      // Aspect requirements

Parameters

Parameter Type Description
key String Research key required to discover/use this recipe
result ItemStack The output item
catalyst Object Input item(s) being cooked; ItemStack, String (Ore Dict), or ArrayList<ItemStack>
tags AspectList Aspects that must be present in the crucible for the recipe to fire

Example: Single Item Catalyst

ThaumcraftApi.addCrucibleRecipe("RESEARCH_KEY",
    new ItemStack(TCItems.itemResource, 1, 2),   // Salis Mundus
    new ItemStack(Items.diamond),
    new AspectList()
        .add(Aspect.EARTH, 10)
        .add(Aspect.ORDER, 5));

Example: Ore Dictionary Catalyst

// Uses any item registered to the "gemDiamond" Ore Dictionary entry
ThaumcraftApi.addCrucibleRecipe("RESEARCH_KEY",
    new ItemStack(TCItems.itemResource, 1, 2),
    "gemDiamond",                                   // String → OreDictionary
    new AspectList()
        .add(Aspect.EARTH, 10)
        .add(Aspect.ORDER, 5));

Example: Multiple Possible Catalysts

ThaumcraftApi.addCrucibleRecipe("RESEARCH_KEY",
    new ItemStack(TCItems.itemResource, 1, 3),
    new ArrayList<ItemStack>(Arrays.asList(
        new ItemStack(Blocks.dirt),
        new ItemStack(Blocks.cobblestone)
    )),
    new AspectList().add(Aspect.EARTH, 8));

CrucibleRecipe Class

public class CrucibleRecipe {
    private ItemStack recipeOutput;
    public Object catalyst;
    public AspectList aspects;
    public String key;
    public int hash;
}

Constructor

public CrucibleRecipe(String researchKey, ItemStack result, Object cat, AspectList tags)

The constructor accepts the same parameters as addCrucibleRecipe. When catalyst is a String, it resolves immediately to an ArrayList<ItemStack> via OreDictionary.getOres().

A hash is computed from researchKey + result.toString() plus, for each entry, tag + amount, plus the catalyst.

⚠️ 订正:原文写成 ... + all aspect tags/amounts + catalyst.toString()——催化剂部分的描述不准确。 真实逻辑(crafting/CrucibleRecipe.java 构造器内 hc 累加):

  • hc = researchKey + result.toString()
  • 遍历 tags:对每个 Aspect 追加 a.getTag() + amount
  • 若 catalyst instanceof ItemStack:追加该 ItemStack 的 toString()
  • 否则(ArrayList):逐个追加每个 ItemStack 的 toString()

即追加的是各个 ItemStack 的 toString(),不是 ArrayList.toString()。 反查入口是 getCrucibleRecipeFromHash(int hash)(ThaumcraftApi.java:274)。

Methods

Method Returns Description
matches(AspectList itags, ItemStack cat) boolean Checks if the given aspects and catalyst satisfy this recipe
catalystMatches(ItemStack cat) boolean Checks if the catalyst matches (without checking aspects)
removeMatching(AspectList itags) AspectList Returns a new AspectList with this recipe’s aspects removed
getRecipeOutput() ItemStack The output ItemStack

matches()

public boolean matches(AspectList itags, ItemStack cat)

Returns true only if:

  1. The catalyst matches the input item (ThaumcraftApiHelper.itemMatches or Ore Dictionary match)
  2. The crucible’s aspect pool contains at least the required amount of each aspect
// Aspect sufficiency check
for (Aspect tag : aspects.getAspects()) {
    if (itags.getAmount(tag) < aspects.getAmount(tag)) return false;
}

removeMatching()

public AspectList removeMatching(AspectList itags)

Returns a new AspectList with this recipe’s aspect costs subtracted. The original AspectList is not modified.

AspectList remaining = recipe.removeMatching(currentAspectsInCrucible);

catalystMatches()

public boolean catalystMatches(ItemStack cat)

A fast check for catalyst compatibility without validating aspect requirements.

Finding Recipes

// By output ItemStack
CrucibleRecipe recipe = ThaumcraftApi.getCrucibleRecipe(ItemStack stack);

// By computed hash
CrucibleRecipe recipe = ThaumcraftApi.getCrucibleRecipeFromHash(int hash);

// Iterate all crucible recipes
for (Object r : ThaumcraftApi.getCraftingRecipes()) {
    if (r instanceof CrucibleRecipe) {
        CrucibleRecipe cr = (CrucibleRecipe) r;
        // ...
    }
}

Research Key Caching

⚠️ 已订正(两处)

① 键类型错:原文写「maps output ItemStacks to their research key and page index」且 private static HashMap<Object, Object[]> keyCache——类型错。真实声明是 private static HashMap<int[], Object[]> keyCache(证据:ThaumcraftApi.java:289), 键是 int[]{itemId, itemDamage} 二元组,不是 ItemStack 本身。 写入处可见键的构造:key = new int[]{stack.getItem().getId(), stack.getItemDamage()} (ThaumcraftApi.java:307,写入见 309、316)。

② 更新者错:原文写「The getCrucibleRecipe method also updates this cache」——这是错的。 getCrucibleRecipe(ThaumcraftApi.java:260-268)只读不写 keyCache; 实际读写该缓存的是 getCraftingRecipeKey(EntityPlayer, ItemStack) (ThaumcraftApi.java:290-330:读 293-296,写 309、316、325)。 全仓 grep keyCache 只命中 ThaumcraftApi.java 的 289/293/294/295/296/309/316/325 八行,均在 getCraftingRecipeKey 作用域内。

缓存值是 new Object[]{ri.key, a}(ThaumcraftApi.java:309/316),即 {研究键, 页码索引}。 getCraftingRecipeKey 会先用 ThaumcraftApiHelper.isResearchComplete(playerName, (String)keyCache.get(key)[0]) 判断该研究是否已完成(ThaumcraftApi.java:295),未完成则返回 null。 缓存用途按 javadoc 是 thaumonomicon 的 drilldown(钻取)功能,不是「解锁配方提示」。

浏览全部模组