Skip to content

Commit

Permalink
Add transformable shaped and shapeless recipe serializers
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Jul 25, 2022
1 parent 78621c4 commit 7ca97de
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.cyclops.cyclopscore.recipe.type;

import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;

/**
* @author rubensworks
*/
public class RecipeCraftingShapedCustomOutput extends ShapedRecipe {

private final RecipeSerializerCraftingShapedCustomOutput serializer;

public RecipeCraftingShapedCustomOutput(RecipeSerializerCraftingShapedCustomOutput serializer, ResourceLocation idIn, String groupIn, int recipeWidthIn, int recipeHeightIn, NonNullList<Ingredient> recipeItemsIn, ItemStack recipeOutputIn) {
super(idIn, groupIn, recipeWidthIn, recipeHeightIn, recipeItemsIn, recipeOutputIn);
this.serializer = serializer;
}

@Override
public IRecipeSerializer<?> getSerializer() {
return this.serializer;
}

@Override
public ItemStack getCraftingResult(CraftingInventory inv) {
RecipeSerializerCraftingShapedCustomOutput.IOutputTransformer outputTransformer = serializer.getOutputTransformer();
if (outputTransformer != null) {
return outputTransformer.transform(inv, super.getRecipeOutput());
}
return super.getRecipeOutput().copy();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.cyclops.cyclopscore.recipe.type;

import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapelessRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;

/**
* @author rubensworks
*/
public class RecipeCraftingShapelessCustomOutput extends ShapelessRecipe {

private final RecipeSerializerCraftingShapelessCustomOutput serializer;

public RecipeCraftingShapelessCustomOutput(RecipeSerializerCraftingShapelessCustomOutput serializer, ResourceLocation idIn, String groupIn, ItemStack recipeOutputIn, NonNullList<Ingredient> recipeItemsIn) {
super(idIn, groupIn, recipeOutputIn, recipeItemsIn);
this.serializer = serializer;
}

@Override
public IRecipeSerializer<?> getSerializer() {
return this.serializer;
}

@Override
public ItemStack getCraftingResult(CraftingInventory inv) {
RecipeSerializerCraftingShapelessCustomOutput.IOutputTransformer outputTransformer = serializer.getOutputTransformer();
if (outputTransformer != null) {
return outputTransformer.transform(inv, super.getRecipeOutput());
}
return super.getRecipeOutput().copy();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package org.cyclops.cyclopscore.recipe.type;

import com.google.gson.JsonObject;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistryEntry;

import javax.annotation.Nullable;
import java.util.Map;
import java.util.function.Supplier;

/**
* Recipe serializer for predefined output items.
* @author rubensworks
*/
public class RecipeSerializerCraftingShapedCustomOutput extends ForgeRegistryEntry<IRecipeSerializer<?>>
implements IRecipeSerializer<RecipeCraftingShapedCustomOutput> {

private final Supplier<ItemStack> outputProvider;
@Nullable
private final IOutputTransformer outputTransformer;

public RecipeSerializerCraftingShapedCustomOutput(Supplier<ItemStack> outputProvider, @Nullable IOutputTransformer outputTransformer) {
this.outputProvider = outputProvider;
this.outputTransformer = outputTransformer;
}

public RecipeSerializerCraftingShapedCustomOutput(Supplier<ItemStack> outputProvider) {
this(outputProvider, null);
}

@Nullable
public IOutputTransformer getOutputTransformer() {
return outputTransformer;
}

// Partially copied from ShapedRecipe.Serializer

@Override
public RecipeCraftingShapedCustomOutput read(ResourceLocation recipeId, JsonObject json) {
String s = JSONUtils.getString(json, "group", "");
Map<String, Ingredient> map = ShapedRecipe.deserializeKey(JSONUtils.getJsonObject(json, "key"));
String[] astring = ShapedRecipe.shrink(ShapedRecipe.patternFromJson(JSONUtils.getJsonArray(json, "pattern")));
int i = astring[0].length();
int j = astring.length;
NonNullList<Ingredient> nonnulllist = ShapedRecipe.deserializeIngredients(astring, map, i, j);
ItemStack itemstack = this.outputProvider.get(); // This line is different
return new RecipeCraftingShapedCustomOutput(this, recipeId, s, i, j, nonnulllist, itemstack);
}

@Override
public RecipeCraftingShapedCustomOutput read(ResourceLocation recipeId, PacketBuffer buffer) {
int i = buffer.readVarInt();
int j = buffer.readVarInt();
String s = buffer.readString(32767);
NonNullList<Ingredient> nonnulllist = NonNullList.withSize(i * j, Ingredient.EMPTY);

for(int k = 0; k < nonnulllist.size(); ++k) {
nonnulllist.set(k, Ingredient.read(buffer));
}

ItemStack itemstack = buffer.readItemStack();
return new RecipeCraftingShapedCustomOutput(this, recipeId, s, i, j, nonnulllist, itemstack);
}

@Override
public void write(PacketBuffer buffer, RecipeCraftingShapedCustomOutput recipe) {
buffer.writeVarInt(recipe.getRecipeWidth());
buffer.writeVarInt(recipe.getRecipeHeight());
buffer.writeString(recipe.getGroup());

for(Ingredient ingredient : recipe.getIngredients()) {
ingredient.write(buffer);
}

buffer.writeItemStack(recipe.getRecipeOutput());
}

public static interface IOutputTransformer {
public ItemStack transform(CraftingInventory inventory, ItemStack staticOutput);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.cyclops.cyclopscore.recipe.type;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.item.crafting.ShapelessRecipe;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistryEntry;

import javax.annotation.Nullable;
import java.util.Map;
import java.util.function.Supplier;

/**
* Recipe serializer for predefined output items.
* @author rubensworks
*/
public class RecipeSerializerCraftingShapelessCustomOutput extends ForgeRegistryEntry<IRecipeSerializer<?>>
implements IRecipeSerializer<RecipeCraftingShapelessCustomOutput> {

private final Supplier<ItemStack> outputProvider;
@Nullable
private final IOutputTransformer outputTransformer;

public RecipeSerializerCraftingShapelessCustomOutput(Supplier<ItemStack> outputProvider, @Nullable IOutputTransformer outputTransformer) {
this.outputProvider = outputProvider;
this.outputTransformer = outputTransformer;
}

public RecipeSerializerCraftingShapelessCustomOutput(Supplier<ItemStack> outputProvider) {
this(outputProvider, null);
}

@Nullable
public IOutputTransformer getOutputTransformer() {
return outputTransformer;
}

// Partially copied from ShapelessRecipe.Serializer

@Override
public RecipeCraftingShapelessCustomOutput read(ResourceLocation recipeId, JsonObject json) {
String s = JSONUtils.getString(json, "group", "");
NonNullList<Ingredient> nonnulllist = readIngredients(JSONUtils.getJsonArray(json, "ingredients"));
if (nonnulllist.isEmpty()) {
throw new JsonParseException("No ingredients for shapeless recipe");
} else if (nonnulllist.size() > 3 * 3) {
throw new JsonParseException("Too many ingredients for shapeless recipe the max is " + (3 * 3));
} else {
ItemStack itemstack = this.outputProvider.get(); // This line is different
return new RecipeCraftingShapelessCustomOutput(this, recipeId, s, itemstack, nonnulllist);
}
}

private static NonNullList<Ingredient> readIngredients(JsonArray ingredientArray) {
NonNullList<Ingredient> nonnulllist = NonNullList.create();

for(int i = 0; i < ingredientArray.size(); ++i) {
Ingredient ingredient = Ingredient.deserialize(ingredientArray.get(i));
if (!ingredient.hasNoMatchingItems()) {
nonnulllist.add(ingredient);
}
}

return nonnulllist;
}

@Override
public RecipeCraftingShapelessCustomOutput read(ResourceLocation recipeId, PacketBuffer buffer) {
String s = buffer.readString(32767);
int i = buffer.readVarInt();
NonNullList<Ingredient> nonnulllist = NonNullList.withSize(i, Ingredient.EMPTY);

for(int j = 0; j < nonnulllist.size(); ++j) {
nonnulllist.set(j, Ingredient.read(buffer));
}

ItemStack itemstack = buffer.readItemStack();
return new RecipeCraftingShapelessCustomOutput(this, recipeId, s, itemstack, nonnulllist);
}

@Override
public void write(PacketBuffer buffer, RecipeCraftingShapelessCustomOutput recipe) {
buffer.writeString(recipe.getGroup());
buffer.writeVarInt(recipe.getIngredients().size());

for(Ingredient ingredient : recipe.getIngredients()) {
ingredient.write(buffer);
}

buffer.writeItemStack(recipe.getRecipeOutput());
}

public static interface IOutputTransformer {
public ItemStack transform(CraftingInventory inventory, ItemStack staticOutput);
}
}
6 changes: 6 additions & 0 deletions src/main/resources/META-INF/accesstransformer.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ public net.minecraft.block.FireBlock field_149848_b # flammabilities

# Worldgen
public net.minecraft.world.gen.trunkplacer.TrunkPlacerType <init>(Lcom/mojang/serialization/Codec;)V # TrunkPlacerType

# ShapedRecipe
public net.minecraft.item.crafting.ShapedRecipe func_192408_a(Lcom/google/gson/JsonObject;)Ljava/util/Map; # deserializeKey
public net.minecraft.item.crafting.ShapedRecipe func_194134_a([Ljava/lang/String;)[Ljava/lang/String; # shrink
public net.minecraft.item.crafting.ShapedRecipe func_192407_a(Lcom/google/gson/JsonArray;)[Ljava/lang/String; # patternFromJson
public net.minecraft.item.crafting.ShapedRecipe func_192402_a([Ljava/lang/String;Ljava/util/Map;II)Lnet/minecraft/util/NonNullList; # deserializeIngredients

0 comments on commit 7ca97de

Please sign in to comment.