In this tutorial we will cover the creation of basic recipes such as shaped, shapeless, smelting and blasting. We will setup a handful of recipes for some of our items and blocks; we will add further recipes in a future tutorial which I'd deem as "advanced" as we will also cover custom receipe types. For this tutorial we will only use existing recipe types, such as smelting or shaped.
Recipe provider
Let's jump right into it by adding a new package named recipe within the datagen/common package and within there create a class called BaseRecipeProvider with the following content:
public abstract class BaseRecipeProvider extends RecipeProvider implements IConditionBuilder {
protected BaseRecipeProvider(PackOutput packOutput) {
super(packOutput);
}
protected static void addStorageBlock(@NotNull Consumer<FinishedRecipe> pWriter, ItemLike item, Block block) {
addStorageBlock(pWriter, RecipeCategory.MISC, item, RecipeCategory.BUILDING_BLOCKS, block);
}
protected static void addStorageBlock(@NotNull Consumer<FinishedRecipe> pWriter, RecipeCategory itemCategory, ItemLike item, RecipeCategory blockCategory, Block block) {
nineBlockStorageRecipes(pWriter, itemCategory, item, blockCategory, block);
}
protected static void addRawMaterialToIngot(@NotNull Consumer<FinishedRecipe> pWriter, ItemLike dustItem, ItemLike ingotItem, float experience, String group) {
addRawMaterialToIngot(pWriter, List.of(dustItem), ingotItem, experience, group);
}
protected static void addRawMaterialToIngot(@NotNull Consumer<FinishedRecipe> pWriter, ItemLike dustItem, RecipeCategory category, ItemLike ingotItem, float experience, String group) {
addRawMaterialToIngot(pWriter, List.of(dustItem), category, ingotItem, experience, group);
}
protected static void addRawMaterialToIngot(@NotNull Consumer<FinishedRecipe> pWriter, List<ItemLike> dustItems, ItemLike ingotItem, float experience, String group) {
addRawMaterialToIngot(pWriter, dustItems, RecipeCategory.MISC, ingotItem, experience, group);
}
protected static void addRawMaterialToIngot(@NotNull Consumer<FinishedRecipe> pWriter, List<ItemLike> dustItems, RecipeCategory category, ItemLike ingotItem, float experience, String group) {
oreSmelting(pWriter, dustItems, category, ingotItem, experience, 200, group);
oreBlasting(pWriter, dustItems, category, ingotItem, experience, 100, group);
}
}For all our recipe providers that we'll be creating we can use this as it's base class to provide useful helper methods, in this case we're adding a helper method for adding a storgage block recipe and some helper methods for smelting and blasting raw materials into ingots.
The reason for the helpers is to reduce the amount of code we have to write each and every time we want to add a raw material to ingot smelting/blasting recipe or a storage block recipe.
Here a storage block recipe actually adds two recipes, one for 9 ingots to 1 block and the reverse of that (1 block to 9 ingots), just as we'd see with the iron block in the base game.
Each time we add a raw material to ingot recipe we are adding two recipes, one for smelting with a cooking time of 200 and one for blasting with a faster cooking time of 100 (half the time of smelting).
Next, create a new class called ModRecipeProvider along side the class we just created with the following content:
public class ModRecipeProvider extends BaseRecipeProvider {
public ModRecipeProvider(PackOutput packOutput) {
super(packOutput);
}
@Override
protected void buildRecipes(@NotNull Consumer<FinishedRecipe> pWriter) {
addStorageBlocks(pWriter);
addDustsToIngots(pWriter);
addFrameBlocks(pWriter);
}
private void addStorageBlocks(@NotNull Consumer<FinishedRecipe> pWriter) {
}
private void addDustsToIngots(@NotNull Consumer<FinishedRecipe> pWriter) {
}
private void addFrameBlocks(@NotNull Consumer<FinishedRecipe> pWriter) {
}
}This is going to be our main recipe provider and will need to be added to our main DataGenerators class within the server section. Again we use smaller methods to help organise the class a little more and make it clear what type of recipes are being added etc.
Make sure to add the new provider into the DataGenerators main class so that it gets included next time we run data generation:
if (event.includeServer()) {
...
generator.addProvider(true, new ModRecipeProvider(packOutput));
}

