Ingredients and Recipes
About this page
This page aims to give the intermediate scripter a more detailed look into some of the common concepts passed around when dealing with recipes.
Let’s talk semantics: The Good, the Bad and the Block
It is fairly possible that in your scripting adventures, you’ve seen the following types being mentioned: IItemStack, IIngredient, ItemDefinition, MCTags, and Blocks.
However, their meaning within the context of the game might be a bit vague, so let’s break them down individually shall we?
- An ItemDefinition is an abstract representation of an in game item. At runtime, there is only one definition for each registered item during the whole execution of the game.
- An IItemStack is a bundle of data, containing an ItemDefinition, a stack size, and extra NBT Data. Anything in your inventory is an IItemStack. Tons and tons of them are instantiated during the normal execution of the game.
- An IIngredient is a predicate that matches some IItemStacks. Like in a cooking recipe, it is essentially a guideline for what fits in a recipe. Said guideline can be really strict: “1x pumpkin_seed”, or vague: “1x any seed”.
- A BlockState is a Block with properties, found within a Level. A Block, like an ItemDefinition only has one instance.
- A MCTag (not to be confused with NBT Tags) is a collection of registry objects, such as ItemDefinitions, Blocks, Fluids, or Biomes, along many others. MCTags are the ones that have contents, and not the other way around: An item (definition) is in many MCTags, or a single MCTag contains many ItemDefinitions.
So what do we interpret from this?
- Blocks are rarely used in the context of recipes
- MCTags do not contain IItemStacks, only ItemDefinitions. This means that any extra data (such as the stacksize, or NBT IData) won’t be checked at the moment of looking at whether a MCTag contains an item.
- IIngredients are an abstract template that determine what can go in a recipe.
About Ingredients and Predicates
Predicates are type of function. They take in one argument and return whether said argument passes all conditions.
Obviously, you don’t need to do this at all! It is all handled behind the scenes by all recipes that take IIngredients as parameters. However, it is good to have a mental idea of how matching works with these types.
MCTags can also be implicitly as well as explicitly be converted to IIngredients. Their check more or less looks like this:
Fine tuning your ingredients
Sometimes, you’ll want more precision, or to group ingredients. For this, you can use some of the methods found in the IIngredient class:
anyDamage
onlyDamaged
onlyDamagedAtLeast
andonlyDamagedAtMost
onlyIf
, the more flexible of them all, allows you to define a custom predicate.reuse
transformCustom
transformReplace
transformDamage
And the magic IIngredientTransformed, which modify the item after being used. However, these require special support, and in Vanilla they will only work in a Crafting Table.
Using fancy ingredients in json recipes
CraftTweaker registers custom ingredient types so that you can use them in json recipes. The following are available to use:
crafttweaker:any
crafttweaker:list
crafttweaker:conditioned
(except for onlyIf)crafttweaker:transformed
-> (except for transformCustom)crafttweaker:partial_tag
Those are the ingredient types. Just about half of what you want. The following script should provide you with a json object, which you can copy and paste as an ingredient in a Json Recipe.
To sum up
So, what do we learn from this post?
- IIngredients are abstract. They’re conditions an IItemStack must match in order to be considered valid.
- MCTags are sets of ItemDefinitions, not IItemStacks.
- Most ingredients and conditions can be serialized into json and used by other mods. However, the most complex of transformations re quire explicit support.