Difference between revisions of "Custom Recipes"

From Forge Community Wiki
(Update to 1.17 and fix all the wrong information, probably should come back later to finish at some point)
Line 5: Line 5:
 
== Classes/Interfaces for the inventories and serialization ==
 
== Classes/Interfaces for the inventories and serialization ==
  
==== IRecipeSerializer ====  
+
==== RecipeSerializer ====  
 
The thing that actually serializes recipe files. It implements the vanilla recipe serializer interface and provides means of reading from JSON and performing read/write operations on network buffer objects. One should look into using [[Codecs]] for this class, as using them simplifies the logic significantly.
 
The thing that actually serializes recipe files. It implements the vanilla recipe serializer interface and provides means of reading from JSON and performing read/write operations on network buffer objects. One should look into using [[Codecs]] for this class, as using them simplifies the logic significantly.
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
public class MyRecipeSerializer  
 
public class MyRecipeSerializer  
   extends ForgeRegistryEntry<IRecipeSerializer<?>>  
+
   extends ForgeRegistryEntry<RecipeSerializer<?>>  
   implements IRecipeSerializer<MyRecipeType> {
+
   implements RecipeSerializer<MyRecipe> {
 
    
 
    
 
   // your serializer code here
 
   // your serializer code here
Line 18: Line 18:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==== IRecipeType ====
+
==== RecipeType ====
Links the recipe type to its implementation class. This is a very lightweight class that vanilla uses to make a recipe file's <code>type</code> line to which serializer should be used to deserialize a recipe into an instance.
+
Links the recipe type to its implementation class(es). This is a very lightweight class that vanilla uses to determine what recipes are associated with what implementors (e.g. <code>CRAFTING</code> is for <code>SHAPED_RECIPE</code>, <code>SHAPELESS_RECIPE</code>, etc.).
  
==== IInventory ====
+
==== Container ====
Wraps vanilla's <code>IInventory</code> system. [https://gist.github.com/robotgryphon/344e5815e27f28fef7a837c4f98ade40 Here's a reference.] '''''Note this should not be used directly; you should make a fake inventory class and handle the actual match implementation with your own methods and logic.'''''
+
Vanilla's inventory system used in recipes to grab references to implementors to see if the associated recipe matches the current container data.
  
==== IRecipe ====
+
==== Recipe ====
Your actual recipe class or an abstraction to cheat vanilla's system and use your own recipe matching system. Takes the <code>IInventory</code> from above and matches it. Your recipe class should return the <code>IRecipeType</code> from registration in the getType override.
+
Your actual recipe class or an abstraction to use your own recipe matching system. Takes the <code>Container</code> from above and matches it. Your recipe class should return the <code>RecipeType</code> from registration in <code>#getType</code> and the serializer in <code>#getSerializer</code>.
  
 
== Setup ==
 
== Setup ==
Line 31: Line 31:
  
 
# Register your recipe serializer to the <code>RECIPE_SERIALIZERS</code> Forge registry.
 
# Register your recipe serializer to the <code>RECIPE_SERIALIZERS</code> Forge registry.
# Register the recipe type during the registration (constructor) phase. See below.
+
# Register the recipe type during the common setup event or statically. See below.
# Place a JSON file in <code>data/recipes/my_recipe.json</code> and ensure it has <code>"type": "mymod:my_recipe_type"</code> in the JSON structure.  
+
# Place a JSON file in <code>data/recipes/my_recipe.json</code> and ensure it has <code>"type": "mymod:my_recipe_serializer_registry_name"</code> in the JSON structure.  
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Registry.register(Registry.RECIPE_TYPE, new ResLoc('mymod:my_recipe_type'), MyRecipeType.class);
+
RecipeType.register("mymod:my_recipe_type");
 
</syntaxhighlight>
 
</syntaxhighlight>
  
This will load the recipe using the recipe serialization system, and wire it back to the serializer via matching the registry name in <code>type</code> to the value you specified while registering the serializer in step 1.
+
This will load the recipe using the recipe serialization system, and wire it back to the serializer via matching the registry name of the serializer to the value you specified while registering the serializer in step 1.

Revision as of 22:41, 2 August 2021

Custom Recipe Serializers

Want to make a custom recipe type for a machine, or some mechanic your mod has? Great! It means users can participate in the datapack system for recipes, so you get automatic syncing, updating, and ease of maintenance on servers. Here's what you need to get started:

Classes/Interfaces for the inventories and serialization

RecipeSerializer

The thing that actually serializes recipe files. It implements the vanilla recipe serializer interface and provides means of reading from JSON and performing read/write operations on network buffer objects. One should look into using Codecs for this class, as using them simplifies the logic significantly.

public class MyRecipeSerializer 
  extends ForgeRegistryEntry<RecipeSerializer<?>> 
  implements RecipeSerializer<MyRecipe> {
  
  // your serializer code here

}

RecipeType

Links the recipe type to its implementation class(es). This is a very lightweight class that vanilla uses to determine what recipes are associated with what implementors (e.g. CRAFTING is for SHAPED_RECIPE, SHAPELESS_RECIPE, etc.).

Container

Vanilla's inventory system used in recipes to grab references to implementors to see if the associated recipe matches the current container data.

Recipe

Your actual recipe class or an abstraction to use your own recipe matching system. Takes the Container from above and matches it. Your recipe class should return the RecipeType from registration in #getType and the serializer in #getSerializer.

Setup

Once you have the above implementations, here's how to wire everything up:

  1. Register your recipe serializer to the RECIPE_SERIALIZERS Forge registry.
  2. Register the recipe type during the common setup event or statically. See below.
  3. Place a JSON file in data/recipes/my_recipe.json and ensure it has "type": "mymod:my_recipe_serializer_registry_name" in the JSON structure.
RecipeType.register("mymod:my_recipe_type");

This will load the recipe using the recipe serialization system, and wire it back to the serializer via matching the registry name of the serializer to the value you specified while registering the serializer in step 1.