-
Notifications
You must be signed in to change notification settings - Fork 0
Recipes
This page describes the custom recipe JSON formats implemented by Tinker Foundry for NeoForge 1.21.1 and NeoForge 26.1.2.
The examples are based on the current MeltingRecipe, AlloyingRecipe, CastingRecipe, MoldingRecipe, FuelRecipe, OreMeltingRecipe, DamageableMeltingRecipe, and EntityMeltingRecipe codecs. Do not treat a recipe that works on one target as automatically valid on the other target.
Put a recipe in:
src/main/resources/data/tinker_foundry/recipe/<recipe_path>.json
For example:
src/main/resources/data/tinker_foundry/recipe/melting/copper_ingot.json
The recipe ID is the path below recipe, so this file becomes tinker_foundry:melting/copper_ingot. The filename and folders identify the recipe; the JSON type selects the codec and must still be written explicitly.
Use registry IDs for every item and fluid, for example minecraft:copper_ingot or tinker_foundry:copper. The id inside an item result is an item ID; the id inside a fluid result is a fluid ID. Neither one is the recipe ID.
Fluid amounts use the project's fluid units. The current constants are:
| Meaning | Amount |
|---|---|
| Nugget | 10 |
| Ingot | 90 |
| Block | 810 |
| Vanilla bucket | 1000 |
A fluid result normally looks like this on both targets:
{
"id": "tinker_foundry:copper",
"amount": 90
}An item result normally looks like this on both targets:
{
"id": "minecraft:copper_ingot",
"count": 1
}amount is the fluid quantity. count is the item stack count. Do not replace a fluid result with an item result or vice versa.
The important migration difference is the ingredient notation used by the current codecs.
| Input | NeoForge 1.21.1 | NeoForge 26.1.2 |
|---|---|---|
| Exact item | { "item": "minecraft:copper_ingot" } |
"minecraft:copper_ingot" |
| Item tag | { "tag": "c:ingots/copper" } |
"#c:ingots/copper" |
| Exact fluid | { "fluid": "tinker_foundry:copper" } |
"tinker_foundry:copper" |
| Fluid tag | { "tag": "c:molten/copper" } |
"#c:molten/copper" |
| Exact mold | { "item": "tinker_foundry:ingot_cast" } |
"tinker_foundry:ingot_cast" |
| Mold tag | { "tag": "c:ingots" } |
"#c:ingots" |
For 1.21.1, a fluid ingredient is usually nested inside a sized ingredient object:
"fluid": {
"ingredient": { "fluid": "tinker_foundry:copper" },
"amount": 90
}For 26.1.2, the same field uses the string form used by the current resources:
"fluid": {
"ingredient": "tinker_foundry:copper",
"amount": 90
}This difference follows the version-specific Ingredient and FluidIngredient codecs. When porting a JSON file, convert every affected item, fluid, and mold input instead of changing only the top-level type.
Internally, 1.21.1 recipes use FluidStack/ItemStack codecs, while 26.1.2 uses FluidStackTemplate/ItemStackTemplate for data-driven recipe records. The normal JSON result shape remains id plus amount for fluids and id plus count for items, but the codec implementation is different.
JSON type
|
Input → output | Main use |
|---|---|---|
tinker_foundry:melting |
Item → fluid | Normal item melting |
tinker_foundry:ore_melting |
Item → fluid | Ore-style metal/gem scaling and byproducts |
tinker_foundry:damageable_melting |
Damageable item → fluid | Output based on remaining durability |
tinker_foundry:entity_melting |
Entity match → fluid | Entity or entity-tag fluid sources |
tinker_foundry:alloying |
Two or more fluids → fluid | Alloyer and smeltery alloy processing |
tinker_foundry:casting |
Fluid + optional mold → item | Casting-table/basin style recipes |
tinker_foundry:molding |
Mold + fluid → item | Reusable or consumable mold recipes |
tinker_foundry:fuel |
Item or fluid → heat | Heater and fuel-tank fuel definitions |
These are Tinker Foundry recipe types. Do not use minecraft:smelting for a molten-fluid recipe.
NeoForge 1.21.1:
{
"type": "tinker_foundry:melting",
"ingredient": { "item": "minecraft:copper_ingot" },
"result": { "id": "tinker_foundry:copper", "amount": 90 },
"temperature": 500,
"time": 50
}NeoForge 26.1.2:
{
"type": "tinker_foundry:melting",
"ingredient": "minecraft:copper_ingot",
"result": { "id": "tinker_foundry:copper", "amount": 90 },
"temperature": 500,
"time": 50
}Fields:
| Field | Required | Meaning |
|---|---|---|
ingredient |
Yes | One item, item tag, or item ingredient list |
result |
Yes | Fluid ID and base amount |
temperature |
Yes | Minimum heat temperature |
time |
No | Processing time in ticks; 100 by default |
rate |
No |
none by default; may be metal or gem
|
byproducts |
No | Additional fluid results |
Use an item tag when the recipe should accept a whole material group:
// 1.21.1 ingredient
{ "tag": "c:ingots/copper" }// 26.1.2 ingredient
"#c:ingots/copper"The rate value is interpreted by the mod's metal/gem conversion logic. none keeps the result amount unchanged. Use metal and gem only when the recipe is intended to participate in those conversion rules.
Use ore_melting for an ore-style recipe whose output participates in the project's metal or gem scaling rules:
{
"type": "tinker_foundry:ore_melting",
"ingredient": "#c:ores/copper",
"result": { "id": "tinker_foundry:copper", "amount": 90 },
"temperature": 500,
"time": 100,
"rate": "metal"
}The exact ingredient notation above is the 26.1.2 form. On 1.21.1, use an object instead:
"ingredient": { "tag": "c:ores/copper" }ore_melting defaults rate to metal; write it explicitly when the intended behavior matters.
Add a byproducts array to melting or ore_melting:
"byproducts": [
{
"result": { "id": "tinker_foundry:slag", "amount": 10 },
"rate": "default"
}
]default inherits the main recipe rate. You can set rate to metal, gem, or none for a specific byproduct. Byproducts are additional fluid outputs; they are not item outputs.
Use damageable_melting for tools or other damageable items. It has the normal melting fields plus unit_size:
{
"type": "tinker_foundry:damageable_melting",
"ingredient": "minecraft:iron_pickaxe",
"result": { "id": "tinker_foundry:iron", "amount": 90 },
"temperature": 800,
"time": 100,
"unit_size": 1
}unit_size controls the durability granularity used when calculating fluid output. Keep it positive. Add byproducts with the same shape as a normal melting recipe when needed.
An alloy recipe must contain at least two entries in ingredients. Each entry has:
-
ingredient: an exact fluid or fluid tag; -
amount: the minimum amount required from one stored fluid layer/input; -
catalyst: optional, defaults tofalse.
The matcher assigns each ingredient to a different fluid layer/input. Extra fluid is allowed. A catalyst is required for matching but is not drained when the alloy completes. The result amount is not calculated automatically; write the intended amount explicitly.
NeoForge 1.21.1:
{
"type": "tinker_foundry:alloying",
"ingredients": [
{
"ingredient": { "fluid": "tinker_foundry:iron" },
"amount": 180
},
{
"ingredient": { "fluid": "tinker_foundry:nickel" },
"amount": 90
}
],
"result": { "id": "tinker_foundry:invar", "amount": 270 },
"temperature": 1000
}NeoForge 26.1.2:
{
"type": "tinker_foundry:alloying",
"ingredients": [
{
"ingredient": "tinker_foundry:iron",
"amount": 180
},
{
"ingredient": "tinker_foundry:nickel",
"amount": 90
}
],
"result": { "id": "tinker_foundry:invar", "amount": 270 },
"temperature": 1000
}Catalyst example:
{
"ingredient": "tinker_foundry:cobalt",
"amount": 90,
"catalyst": true
}There is no time field in AlloyingRecipe. Alloying follows the machine's processing cadence and the temperature gate. Do not add an unused time field expecting a custom duration.
Casting uses a sized fluid input and produces an item. mold is optional for a casting recipe.
NeoForge 1.21.1:
{
"type": "tinker_foundry:casting",
"fluid": {
"ingredient": { "fluid": "tinker_foundry:iron" },
"amount": 90
},
"mold": { "item": "tinker_foundry:ingot_cast" },
"result": { "id": "minecraft:iron_ingot", "count": 1 },
"time": 60
}NeoForge 26.1.2:
{
"type": "tinker_foundry:casting",
"fluid": {
"ingredient": "tinker_foundry:iron",
"amount": 90
},
"mold": "tinker_foundry:ingot_cast",
"result": { "id": "minecraft:iron_ingot", "count": 1 },
"time": 60
}Optional fields:
| Field | Default | Meaning |
|---|---|---|
time |
60 |
Casting time in ticks |
cast_consumed |
false |
Consume the mold/cast when the recipe completes |
switch_slots |
false |
Use the recipe's slot-switch behavior |
copy_potion_contents |
false |
Copy potion contents when the result supports it |
Molding is the inverse-style operation: a mold item and fluid produce an item.
{
"type": "tinker_foundry:molding",
"mold": "tinker_foundry:ingot_sand_cast",
"fluid": {
"ingredient": "tinker_foundry:copper",
"amount": 90
},
"result": { "id": "minecraft:copper_ingot", "count": 1 },
"time": 60
}The mold and fluid.ingredient strings above are the 26.1.2 notation. For 1.21.1, use { "item": ... } or { "tag": ... } for mold, and { "fluid": ... } or { "tag": ... } inside fluid.ingredient.
Optional fields:
| Field | Default | Meaning |
|---|---|---|
time |
60 |
Molding time in ticks |
remainder |
Empty | Item returned after processing, if any |
pattern_consumed |
true |
Consume the mold/pattern when the recipe completes |
Fuel recipes define item fuel, fluid fuel, or both. The item and fluid inputs are independent optional fields; provide the field(s) that the corresponding heater or tank should accept.
Item fuel in 1.21.1:
{
"type": "tinker_foundry:fuel",
"item": { "tag": "minecraft:coals" },
"duration": 1600,
"temperature": 800,
"consumption": 1,
"rate": 8
}Item fuel in 26.1.2:
{
"type": "tinker_foundry:fuel",
"item": "#minecraft:coals",
"duration": 1600,
"temperature": 800,
"consumption": 1,
"rate": 8
}Fluid fuel in 1.21.1 uses { "fluid": "..." }; 26.1.2 uses the fluid ID string:
// 1.21.1
"fluid": { "fluid": "tinker_foundry:blazing_blood" }// 26.1.2
"fluid": "tinker_foundry:blazing_blood"Fields:
| Field | Required | Meaning |
|---|---|---|
item or fluid
|
At least one intended input | Item or fluid fuel matcher |
duration |
Yes | Fuel duration |
temperature |
Yes | Heat temperature supplied |
consumption |
No | Amount consumed per operation; 1 by default |
rate |
No | Fuel transfer/processing rate; 10 by default and must be positive |
Entity melting matches explicit entity IDs, an entity tag, or both:
{
"type": "tinker_foundry:entity_melting",
"entity_tag": "tinker_foundry:melting/blazes",
"result": { "id": "tinker_foundry:blazing_blood", "amount": 20 },
"damage": 2
}Use entities for explicit IDs:
"entities": ["minecraft:blaze", "minecraft:magma_cube"]damage defaults to 2 and is restricted to the codec's valid positive range. The result fluid uses the same id/amount shape on both targets.
Before committing a recipe:
- Confirm that every item, fluid, and tag exists in the target version.
- Confirm the top-level
typematches one of the Tinker Foundry recipe serializers. - Convert item, fluid, and mold inputs to the target version's notation.
- Check that fluid amounts are large enough for the intended item output.
- For alloying, use at least two distinct input layers and mark catalysts explicitly.
- Use
/reloadin a development world and inspect the log for recipe loading errors. - Open the relevant Tinker Foundry or JEI recipe view and verify the recipe is present.
The most common migration error is a valid-looking JSON file that still contains 1.21.1 object ingredients in a 26.1.2 resource, or 26.1.2 #tag strings in a 1.21.1 resource. The JSON parser can only accept the codec for the target branch.