ARC Recipe Framework Part 1

Added the serializers, deserializers, builders, etc, for the Alchemical Reaction Chamber recipe, ARCRecipe. The block does not currently have the functionality to use it yet.

And only when I am currently writing this do I realize I forgot to add FluidStack functionality to the recipes. Welp.
This commit is contained in:
WayofTime 2020-10-26 21:48:53 -04:00
parent 152525bbe3
commit f9327d8f5a
21 changed files with 556 additions and 39 deletions

View file

@ -0,0 +1,110 @@
package wayoftime.bloodmagic.api.impl.recipe;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public abstract class RecipeARC extends BloodMagicRecipe
{
public static final int MAX_RANDOM_OUTPUTS = 3;
@Nonnull
private final Ingredient input;
@Nonnull
private final Ingredient arc_tool;
@Nonnull
private final ItemStack output;
private final List<Pair<ItemStack, Double>> addedItems;
protected RecipeARC(ResourceLocation id, Ingredient input, Ingredient arc_tool, ItemStack output)
{
this(id, input, arc_tool, output, new ArrayList<Pair<ItemStack, Double>>());
}
protected RecipeARC(ResourceLocation id, Ingredient input, Ingredient arc_tool, ItemStack output, List<Pair<ItemStack, Double>> addedItems)
{
super(id);
this.input = input;
this.arc_tool = arc_tool;
this.output = output;
this.addedItems = addedItems;
}
public RecipeARC addRandomOutput(ItemStack stack, double chance)
{
if (addedItems.size() >= MAX_RANDOM_OUTPUTS)
{
return this;
}
addedItems.add(Pair.of(stack, chance));
return this;
}
@Nonnull
public final Ingredient getInput()
{
return input;
}
@Override
public final NonNullList<Ingredient> getIngredients()
{
NonNullList<Ingredient> list = NonNullList.create();
list.add(getInput());
return list;
}
public List<ItemStack> getAllListedOutputs()
{
List<ItemStack> list = new ArrayList<ItemStack>();
list.add(output.copy());
for (Pair<ItemStack, Double> pair : addedItems)
{
list.add(pair.getLeft().copy());
}
return list;
}
public List<ItemStack> getAllOutputs(Random rand)
{
List<ItemStack> list = new ArrayList<ItemStack>();
list.add(output.copy());
for (Pair<ItemStack, Double> pair : addedItems)
{
if (rand.nextDouble() < pair.getRight())
list.add(pair.getLeft().copy());
}
return list;
}
@Override
public void write(PacketBuffer buffer)
{
input.write(buffer);
arc_tool.write(buffer);
buffer.writeItemStack(output);
buffer.writeInt(addedItems.size());
for (Pair<ItemStack, Double> pair : addedItems)
{
buffer.writeItemStack(pair.getLeft());
buffer.writeDouble(pair.getValue());
}
}
}

View file

@ -0,0 +1,40 @@
package wayoftime.bloodmagic.common.data;
import java.nio.file.Path;
import net.minecraft.data.BlockTagsProvider;
import net.minecraft.data.DataGenerator;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
import wayoftime.bloodmagic.BloodMagic;
public class GeneratorBlockTags extends BlockTagsProvider
{
public GeneratorBlockTags(DataGenerator generatorIn, ExistingFileHelper exFileHelper)
{
super(generatorIn, BloodMagic.MODID, exFileHelper);
}
@Override
public void registerTags()
{
}
/**
* Resolves a Path for the location to save the given tag.
*/
@Override
protected Path makePath(ResourceLocation id)
{
return this.generator.getOutputFolder().resolve("data/" + id.getNamespace() + "/tags/blocks/" + id.getPath() + ".json");
}
/**
* Gets a name for this provider, to use in logging.
*/
@Override
public String getName()
{
return "Block Tags";
}
}

View file

@ -0,0 +1,48 @@
package wayoftime.bloodmagic.common.data;
import java.nio.file.Path;
import net.minecraft.data.BlockTagsProvider;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.ItemTagsProvider;
import net.minecraft.item.Items;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.common.tags.BloodMagicTags;
public class GeneratorItemTags extends ItemTagsProvider
{
public GeneratorItemTags(DataGenerator dataGenerator, BlockTagsProvider blockTagProvider, ExistingFileHelper existingFileHelper)
{
super(dataGenerator, blockTagProvider, BloodMagic.MODID, existingFileHelper);
}
@Override
public void registerTags()
{
this.getOrCreateBuilder(BloodMagicTags.ARC_TOOL).add(Items.DIAMOND);
// this.getOrCreateBuilder(GOORESISTANT).addTag(BlockTags.DOORS);
// this.getOrCreateBuilder(GOORESISTANT).addTag(BlockTags.BEDS);
// this.getOrCreateBuilder(GOORESISTANT).add(Blocks.PISTON, Blocks.PISTON_HEAD, Blocks.STICKY_PISTON, Blocks.MOVING_PISTON);
}
/**
* Resolves a Path for the location to save the given tag.
*/
@Override
protected Path makePath(ResourceLocation id)
{
return this.generator.getOutputFolder().resolve("data/" + id.getNamespace() + "/tags/items/" + id.getPath() + ".json");
}
/**
* Gets a name for this provider, to use in logging.
*/
@Override
public String getName()
{
return "Item Tags";
}
}

View file

@ -5,6 +5,7 @@ import java.util.List;
import net.minecraft.data.DataGenerator;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.common.recipe.ARCRecipeProvider;
import wayoftime.bloodmagic.common.recipe.AlchemyArrayRecipeProvider;
import wayoftime.bloodmagic.common.recipe.BloodAltarRecipeProvider;
import wayoftime.bloodmagic.common.recipe.ISubRecipeProvider;
@ -20,6 +21,6 @@ public class BloodMagicRecipeProvider extends BaseRecipeProvider
@Override
protected List<ISubRecipeProvider> getSubRecipeProviders()
{
return Arrays.asList(new BloodAltarRecipeProvider(), new AlchemyArrayRecipeProvider(), new TartaricForgeRecipeProvider());
return Arrays.asList(new BloodAltarRecipeProvider(), new AlchemyArrayRecipeProvider(), new TartaricForgeRecipeProvider(), new ARCRecipeProvider());
}
}

View file

@ -0,0 +1,89 @@
package wayoftime.bloodmagic.common.data.recipe.builder;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.ResourceLocation;
import wayoftime.bloodmagic.api.SerializerHelper;
import wayoftime.bloodmagic.api.impl.recipe.RecipeARC;
import wayoftime.bloodmagic.common.data.recipe.BloodMagicRecipeBuilder;
import wayoftime.bloodmagic.util.Constants;
public class ARCRecipeBuilder extends BloodMagicRecipeBuilder<ARCRecipeBuilder>
{
private final Ingredient input;
private final Ingredient arcTool;
private final ItemStack output;
private final List<Pair<ItemStack, Double>> addedItems = new ArrayList<Pair<ItemStack, Double>>();
protected ARCRecipeBuilder(Ingredient input, Ingredient arcTool, ItemStack output)
{
super(bmSerializer("arc"));
this.input = input;
this.arcTool = arcTool;
this.output = output;
}
public static ARCRecipeBuilder arc(Ingredient input, Ingredient arcTool, ItemStack output)
{
return new ARCRecipeBuilder(input, arcTool, output);
}
public ARCRecipeBuilder addRandomOutput(ItemStack stack, double chance)
{
if (addedItems.size() >= RecipeARC.MAX_RANDOM_OUTPUTS)
{
return this;
}
addedItems.add(Pair.of(stack, chance));
return this;
}
@Override
protected ARCRecipeResult getResult(ResourceLocation id)
{
return new ARCRecipeResult(id);
}
public class ARCRecipeResult extends RecipeResult
{
protected ARCRecipeResult(ResourceLocation id)
{
super(id);
}
@Override
public void serialize(@Nonnull JsonObject json)
{
json.add(Constants.JSON.INPUT, input.serialize());
json.add(Constants.JSON.TOOL, arcTool.serialize());
if (addedItems.size() > 0)
{
JsonArray mainArray = new JsonArray();
for (Pair<ItemStack, Double> pair : addedItems)
{
JsonObject jsonObj = new JsonObject();
jsonObj.addProperty(Constants.JSON.CHANCE, pair.getValue().floatValue());
jsonObj.add(Constants.JSON.TYPE, SerializerHelper.serializeItemStack(pair.getKey()));
mainArray.add(jsonObj);
}
json.add(Constants.JSON.ADDEDOUTPUT, mainArray);
}
json.add(Constants.JSON.OUTPUT, SerializerHelper.serializeItemStack(output));
}
}
}

View file

@ -0,0 +1,23 @@
package wayoftime.bloodmagic.common.recipe;
import java.util.function.Consumer;
import net.minecraft.data.IFinishedRecipe;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.Ingredient;
import net.minecraftforge.common.Tags;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.common.block.BloodMagicBlocks;
import wayoftime.bloodmagic.common.data.recipe.builder.ARCRecipeBuilder;
public class ARCRecipeProvider implements ISubRecipeProvider
{
@Override
public void addRecipes(Consumer<IFinishedRecipe> consumer)
{
String basePath = "arc/";
ARCRecipeBuilder.arc(Ingredient.fromTag(Tags.Items.GEMS_DIAMOND), Ingredient.fromTag(Tags.Items.BONES), new ItemStack(BloodMagicBlocks.BLOOD_ALTAR.get())).addRandomOutput(new ItemStack(Items.DIAMOND), 0.5).build(consumer, BloodMagic.rl(basePath + "test1"));
ARCRecipeBuilder.arc(Ingredient.fromTag(Tags.Items.GEMS_DIAMOND), Ingredient.fromItems(Items.ACACIA_BOAT), new ItemStack(BloodMagicBlocks.BLOOD_ALTAR.get())).build(consumer, BloodMagic.rl(basePath + "test2"));
}
}

View file

@ -1,6 +1,7 @@
package wayoftime.bloodmagic.common.recipe;
import net.minecraft.item.crafting.IRecipeType;
import wayoftime.bloodmagic.api.impl.recipe.RecipeARC;
import wayoftime.bloodmagic.api.impl.recipe.RecipeAlchemyArray;
import wayoftime.bloodmagic.api.impl.recipe.RecipeBloodAltar;
import wayoftime.bloodmagic.api.impl.recipe.RecipeTartaricForge;
@ -10,4 +11,5 @@ public class BloodMagicRecipeType
public static final IRecipeType<RecipeBloodAltar> ALTAR = IRecipeType.register("altar");
public static final IRecipeType<RecipeAlchemyArray> ARRAY = IRecipeType.register("array");
public static final IRecipeType<RecipeTartaricForge> TARTARICFORGE = IRecipeType.register("soulforge");
public static final IRecipeType<RecipeARC> ARC = IRecipeType.register("arc");
}

View file

@ -0,0 +1,127 @@
package wayoftime.bloodmagic.common.recipe.serializer;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistryEntry;
import wayoftime.bloodmagic.api.SerializerHelper;
import wayoftime.bloodmagic.api.impl.recipe.RecipeARC;
import wayoftime.bloodmagic.util.Constants;
public class ARCRecipeSerializer<RECIPE extends RecipeARC> extends ForgeRegistryEntry<IRecipeSerializer<?>>
implements IRecipeSerializer<RECIPE>
{
private final IFactory<RECIPE> factory;
public ARCRecipeSerializer(IFactory<RECIPE> factory)
{
this.factory = factory;
}
@Nonnull
@Override
public RECIPE read(@Nonnull ResourceLocation recipeId, @Nonnull JsonObject json)
{
JsonElement input = JSONUtils.isJsonArray(json, Constants.JSON.INPUT)
? JSONUtils.getJsonArray(json, Constants.JSON.INPUT)
: JSONUtils.getJsonObject(json, Constants.JSON.INPUT);
JsonElement tool = JSONUtils.isJsonArray(json, Constants.JSON.TOOL)
? JSONUtils.getJsonArray(json, Constants.JSON.TOOL)
: JSONUtils.getJsonObject(json, Constants.JSON.TOOL);
Ingredient inputIng = Ingredient.deserialize(input);
Ingredient toolIng = Ingredient.deserialize(tool);
ItemStack output = SerializerHelper.getItemStack(json, Constants.JSON.OUTPUT);
List<Pair<ItemStack, Double>> addedItems = new ArrayList<Pair<ItemStack, Double>>();
if (json.has(Constants.JSON.ADDEDOUTPUT) && JSONUtils.isJsonArray(json, Constants.JSON.ADDEDOUTPUT))
{
JsonArray mainArray = JSONUtils.getJsonArray(json, Constants.JSON.ADDEDOUTPUT);
arrayLoop: for (JsonElement element : mainArray)
{
if (addedItems.size() >= RecipeARC.MAX_RANDOM_OUTPUTS)
{
break arrayLoop;
}
if (element.isJsonObject())
{
JsonObject obj = element.getAsJsonObject();
double chance = JSONUtils.getFloat(obj, Constants.JSON.CHANCE);
ItemStack extraDrop = SerializerHelper.getItemStack(obj, Constants.JSON.TYPE);
addedItems.add(Pair.of(extraDrop, chance));
}
}
}
return this.factory.create(recipeId, inputIng, toolIng, output, addedItems);
}
@Override
public RECIPE read(@Nonnull ResourceLocation recipeId, @Nonnull PacketBuffer buffer)
{
try
{
List<Pair<ItemStack, Double>> addedItems = new ArrayList<Pair<ItemStack, Double>>();
Ingredient inputIng = Ingredient.read(buffer);
Ingredient toolIng = Ingredient.read(buffer);
ItemStack output = buffer.readItemStack();
int addedItemSize = buffer.readInt();
for (int i = 0; i < addedItemSize; i++)
{
ItemStack stack = buffer.readItemStack();
double chance = buffer.readDouble();
addedItems.add(Pair.of(stack, chance));
}
buffer.writeInt(addedItems.size());
for (Pair<ItemStack, Double> pair : addedItems)
{
buffer.writeItemStack(pair.getLeft());
buffer.writeDouble(pair.getValue());
}
return this.factory.create(recipeId, inputIng, toolIng, output, addedItems);
} catch (Exception e)
{
// Mekanism.logger.error("Error reading electrolysis recipe from packet.", e);
throw e;
}
}
@Override
public void write(@Nonnull PacketBuffer buffer, @Nonnull RECIPE recipe)
{
try
{
recipe.write(buffer);
} catch (Exception e)
{
// Mekanism.logger.error("Error writing electrolysis recipe to packet.", e);
throw e;
}
}
@FunctionalInterface
public interface IFactory<RECIPE extends RecipeARC>
{
RECIPE create(ResourceLocation id, Ingredient input, Ingredient arcTool, ItemStack output, List<Pair<ItemStack, Double>> addedItems);
}
}

View file

@ -1,14 +1,17 @@
package wayoftime.bloodmagic.common.registries;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.api.impl.recipe.RecipeARC;
import wayoftime.bloodmagic.api.impl.recipe.RecipeAlchemyArray;
import wayoftime.bloodmagic.api.impl.recipe.RecipeBloodAltar;
import wayoftime.bloodmagic.api.impl.recipe.RecipeTartaricForge;
import wayoftime.bloodmagic.common.recipe.serializer.ARCRecipeSerializer;
import wayoftime.bloodmagic.common.recipe.serializer.AlchemyArrayRecipeSerializer;
import wayoftime.bloodmagic.common.recipe.serializer.BloodAltarRecipeSerializer;
import wayoftime.bloodmagic.common.recipe.serializer.TartaricForgeRecipeSerializer;
import wayoftime.bloodmagic.common.registration.impl.IRecipeSerializerDeferredRegister;
import wayoftime.bloodmagic.common.registration.impl.IRecipeSerializerRegistryObject;
import wayoftime.bloodmagic.recipe.IRecipeARC;
import wayoftime.bloodmagic.recipe.IRecipeAlchemyArray;
import wayoftime.bloodmagic.recipe.IRecipeBloodAltar;
import wayoftime.bloodmagic.recipe.IRecipeTartaricForge;
@ -25,6 +28,7 @@ public class BloodMagicRecipeSerializers
public static final IRecipeSerializerRegistryObject<RecipeBloodAltar> ALTAR = RECIPE_SERIALIZERS.register("altar", () -> new BloodAltarRecipeSerializer<>(IRecipeBloodAltar::new));
public static final IRecipeSerializerRegistryObject<RecipeAlchemyArray> ARRAY = RECIPE_SERIALIZERS.register("array", () -> new AlchemyArrayRecipeSerializer<>(IRecipeAlchemyArray::new));
public static final IRecipeSerializerRegistryObject<RecipeTartaricForge> TARTARIC = RECIPE_SERIALIZERS.register("soulforge", () -> new TartaricForgeRecipeSerializer<>(IRecipeTartaricForge::new));
public static final IRecipeSerializerRegistryObject<RecipeARC> ARC = RECIPE_SERIALIZERS.register("arc", () -> new ARCRecipeSerializer<>(IRecipeARC::new));
// public static final DeferredRegister<IRecipeSerializer<?>> RECIPE_SERIALIZERS = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, BloodMagic.MODID);

View file

@ -0,0 +1,12 @@
package wayoftime.bloodmagic.common.tags;
import net.minecraft.item.Item;
import net.minecraft.tags.ITag;
import net.minecraft.tags.ItemTags;
public class BloodMagicTags
{
public static final ITag.INamedTag<Item> ARC_TOOL = ItemTags.makeWrapperTag("bloodmagic:arc_tool");
public static final ITag.INamedTag<Item> ARC_TOOL_FURNACE = ItemTags.makeWrapperTag("bloodmagic:arc_tool_furnace");
public static final ITag.INamedTag<Item> ARC_TOOL_SIEVE = ItemTags.makeWrapperTag("bloodmagic:arc_tool_sieve");
}

View file

@ -0,0 +1,40 @@
package wayoftime.bloodmagic.recipe;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.ResourceLocation;
import wayoftime.bloodmagic.api.impl.recipe.RecipeARC;
import wayoftime.bloodmagic.common.recipe.BloodMagicRecipeType;
import wayoftime.bloodmagic.common.registries.BloodMagicRecipeSerializers;
public class IRecipeARC extends RecipeARC
{
public IRecipeARC(ResourceLocation id, Ingredient input, Ingredient arc_tool, ItemStack output)
{
super(id, input, arc_tool, output, new ArrayList<Pair<ItemStack, Double>>());
}
public IRecipeARC(ResourceLocation id, Ingredient input, Ingredient arc_tool, ItemStack output, List<Pair<ItemStack, Double>> addedItems)
{
super(id, input, arc_tool, output, addedItems);
}
@Override
public IRecipeSerializer<RecipeARC> getSerializer()
{
return BloodMagicRecipeSerializers.ARC.getRecipeSerializer();
}
@Override
public IRecipeType<RecipeARC> getType()
{
return BloodMagicRecipeType.ARC;
}
}

View file

@ -14,7 +14,7 @@ import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import wayoftime.bloodmagic.common.block.BloodMagicBlocks;
import wayoftime.bloodmagic.common.item.IARCTool;
import wayoftime.bloodmagic.common.tags.BloodMagicTags;
import wayoftime.bloodmagic.tile.TileAlchemicalReactionChamber;
public class ContainerAlchemicalReactionChamber extends Container
@ -88,7 +88,7 @@ public class ContainerAlchemicalReactionChamber extends Container
slot.onSlotChange(itemstack1, itemstack);
} else if (index > 9) // Attempting to transfer from main inventory
{
if (itemstack1.getItem() instanceof IARCTool) // Try the tool slot first
if (itemstack1.getItem().isIn(BloodMagicTags.ARC_TOOL)) // Try the tool slot first
{
if (!this.mergeItemStack(itemstack1, 0, 1, false))
{
@ -150,7 +150,7 @@ public class ContainerAlchemicalReactionChamber extends Container
@Override
public boolean isItemValid(ItemStack itemStack)
{
return itemStack.getItem() instanceof IARCTool;
return itemStack.getItem().isIn(BloodMagicTags.ARC_TOOL);
}
}