Notice: This website is still under development. Please report any issues at https://github.com/QuiltMC/developer-wiki

Recipe API

A Quilt Standard Libraries module that aims to help to manipulate recipes.

It has three parts, QuiltRecipeSerializer (Which was briefly covered in the Recipe Type Tutorial), recipe manager manipulation, and utilities.

QuiltRecipeSerializer

An interface that extends RecipeSerializer to add to-JSON serialization.

Its primary use is the recipe dump, which allows for dumping of JSON representations of recipes as files into the game directory (./debug/quilt/recipe/...) - It supports any recipes whose serializer implements QuiltRecipeSerializer, vanilla recipes are supported by default.

Dumping can be enabled with the quilt.recipe.dump system property.

Manipulation

The recipe manager manipulation is a grouping of systems that can alter the state of the recipe manager and its recipes, they can be accessed using the RecipeManagerHelper class.

The events contained in this system have a set order, which is addition, modification, and removal respectively.

Static Recipes

Static recipes are a kind of recipe that is always kept present during the whole game lifecycle. They're only applied after data pack reloads, that is, when starting a world/server or after using the /reload command.

From Recipes.java:

// ...
RecipeManagerHelper.registerStaticRecipe(
		VanillaRecipeBuilders.shapedRecipe("IAI") // Shaped recipe with the IAI pattern
				.output(new ItemStack(Items.CHAINMAIL_CHESTPLATE)) // That outputs a chestplate
				.ingredient('I', Items.IRON_INGOT) // 'I' being an ingot
				.ingredient('A', Items.APPLE) // and 'A' an apple
				.build(new Identifier(modId, "apple_iron_ingot_fun"), "")
);
// ...

Addition

Mods might want to add recipes that have runtime components - Something that cannot be known at build time - for example, recipes that depend on other mods. Dynamic recipe providers allow for that.

From Recipes.java:

// ...
RecipeManagerHelper.addRecipes(handler -> handler.register(new Identifier(modId, "random"), id ->
		VanillaRecipeBuilders.shapelessRecipe(new ItemStack(
				// We can't know which item it's going to output in advance, therefore
				// it's impossible to create a JSON for this recipe.
				Registry.ITEM.getRandom(RandomGenerator.createLegacy()).orElseThrow().value()))
			.ingredient(Items.ACACIA_BUTTON)
			.build(id, "")));
// ...

Modification

Mods might want to modify values or replace recipes entirely while they're being built, this event allows for that.

From Recipes.java:

// ...
RecipeManagerHelper.modifyRecipes(handler -> {
	// Modifies the name of the output of the stone smelting recipe
	handler.getRecipe(new Identifier("minecraft", "stone"), RecipeType.SMELTING)
			.getOutput().setCustomName(Text.literal("Modified!").formatted(Formatting.RED));
	// Replaces the enchanting table recipe with different ingredients
	handler.replace(VanillaRecipeBuilders.shapedRecipe(" B ", "D#D", "###")
			.ingredient('B', Items.WRITABLE_BOOK)
			.ingredient('D', Items.GOLD_INGOT)
			.ingredient('#', Items.POLISHED_BASALT)
			.output(new ItemStack(Items.ENCHANTING_TABLE))
			.build(new Identifier("minecraft", "enchanting_table"), "")
	);
});
// ...

Removal

Mods might want to remove a recipe completely from the game, this event allows for that. Be aware that removing recipes might not be entirely compatible with what other mods expect.

From Recipes.java:

// ...
RecipeManagerHelper.removeRecipes(handler -> {
	handler.remove(new Identifier("minecraft", "acacia_door"));
	handler.removeIf(RecipeType.BLASTING, rec -> rec.getOutput().isOf(Items.GOLD_INGOT));
});
// ...