Starting to add RecipeFactories and Recipe Handlers. Atomic Reconstructor implemented as ItemStack/Ingredient and BlockState version

This commit is contained in:
canitzp 2020-09-16 11:48:12 +02:00
parent 2ae9ed307e
commit 829cc788c7
9 changed files with 381 additions and 14 deletions

View File

@ -4,11 +4,13 @@ import de.ellpeck.actuallyadditions.api.internal.IAtomicReconstructor;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.registries.ForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistryEntry;
/**
* This is the base class for a Reconstructor Lens Type (NOT THE ITEM!)
*/
public abstract class Lens {
public abstract class Lens extends ForgeRegistryEntry<Lens> {
/**
* Invokes the lens type's behavior on a block

View File

@ -1,6 +1,7 @@
package de.ellpeck.actuallyadditions.common;
import de.ellpeck.actuallyadditions.api.ActuallyAdditionsAPI;
import de.ellpeck.actuallyadditions.api.lens.Lens;
import de.ellpeck.actuallyadditions.booklet.InitBooklet;
import de.ellpeck.actuallyadditions.common.blocks.InitBlocks;
import de.ellpeck.actuallyadditions.common.config.ConfigurationHandler;
@ -45,6 +46,10 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -61,6 +66,8 @@ public class ActuallyAdditions {
public static final Logger LOGGER = LogManager.getLogger(MODID);
public static ActuallyAdditions INSTANCE;
public static final IForgeRegistry<Lens> LENS_REGISTRY = new RegistryBuilder<Lens>().disableSync().disableSaving().disableOverrides().create();
public static boolean commonCapsLoaded = false;
// Creative Tab
@ -78,6 +85,8 @@ public class ActuallyAdditions {
// Register registers
InitBlocks.BLOCKS.register(bus);
// items
Lenses.LENSES.register(bus);
bus.addListener(this::setup);
bus.addListener(this::clientSetup);
@ -126,7 +135,6 @@ public class ActuallyAdditions {
ActuallyAdditionsAPI.methodHandler = new MethodHandler();
ActuallyAdditionsAPI.connectionHandler = new LaserRelayConnectionHandler();
Lenses.init();
InitBooklet.preInit();
CompatUtil.registerCraftingTweaks();

View File

@ -1,18 +1,23 @@
package de.ellpeck.actuallyadditions.common.items.lens;
import de.ellpeck.actuallyadditions.api.ActuallyAdditionsAPI;
import de.ellpeck.actuallyadditions.api.lens.Lens;
import de.ellpeck.actuallyadditions.api.lens.LensConversion;
import de.ellpeck.actuallyadditions.common.ActuallyAdditions;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
public final class Lenses {
public static void init() {
ActuallyAdditionsAPI.lensDefaultConversion = new LensConversion();
ActuallyAdditionsAPI.lensDetonation = new LensDetonation();
ActuallyAdditionsAPI.lensDeath = new LensDeath();
ActuallyAdditionsAPI.lensEvenMoarDeath = new LensKiller();
ActuallyAdditionsAPI.lensColor = new LensColor();
ActuallyAdditionsAPI.lensDisruption = new LensDisruption();
ActuallyAdditionsAPI.lensDisenchanting = new LensDisenchanting();
ActuallyAdditionsAPI.lensMining = new LensMining();
}
public static final DeferredRegister<Lens> LENSES = DeferredRegister.create(ActuallyAdditions.LENS_REGISTRY, ActuallyAdditions.MODID);
public static final RegistryObject<LensConversion> LENS_CONVERSION = LENSES.register("conversion", LensConversion::new);
public static final RegistryObject<LensDetonation> LENS_DETONATION = LENSES.register("detonation", LensDetonation::new);
public static final RegistryObject<LensDeath> LENS_DEATH = LENSES.register("death", LensDeath::new);
public static final RegistryObject<LensKiller> LENS_KILLER = LENSES.register("killer", LensKiller::new);
public static final RegistryObject<LensColor> LENS_COLOR = LENSES.register("color", LensColor::new);
public static final RegistryObject<LensDisruption> LENS_DISRUPTION = LENSES.register("disruption", LensDisruption::new);
public static final RegistryObject<LensDisenchanting> LENS_DISENCHANTING = LENSES.register("disenchanting", LensDisenchanting::new);
public static final RegistryObject<LensMining> LENS_MINING = LENSES.register("mining", LensMining::new);
}

View File

@ -0,0 +1,61 @@
package de.ellpeck.actuallyadditions.recipes;
import de.ellpeck.actuallyadditions.api.lens.Lens;
import net.minecraft.block.BlockState;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.util.ResourceLocation;
/**
* Recipe class for the AtomicReconstructor when hitting a items stack
*/
public class AtomicReconstructorBlockRecipe implements IDummyRecipe {
public static final IRecipeType<AtomicReconstructorBlockRecipe> ATOMIC_RECONSTRUCTOR_BLOCK_RECIPE_TYPE = IRecipeType.register("actuallyadditions:atomic_reconstructor_block");
private final ResourceLocation recipeId;
private final Lens lens;
private final BlockState input;
private final BlockState output;
private final int energyConsumption;
public AtomicReconstructorBlockRecipe(ResourceLocation recipeId, Lens lens, BlockState input, BlockState output, int energyConsumption){
this.recipeId = recipeId;
this.lens = lens;
this.input = input;
this.output = output;
this.energyConsumption = energyConsumption;
}
public Lens getLens(){
return lens;
}
public BlockState getInput(){
return input;
}
public BlockState getOutput(){
return output;
}
public int getEnergyConsumption(){
return energyConsumption;
}
@Override
public ResourceLocation getId(){
return this.recipeId;
}
@Override
public IRecipeSerializer<?> getSerializer(){
return AtomicReconstructorBlockRecipeFactory.INSTANCE;
}
@Override
public IRecipeType<?> getType(){
return ATOMIC_RECONSTRUCTOR_BLOCK_RECIPE_TYPE;
}
}

View File

@ -0,0 +1,97 @@
package de.ellpeck.actuallyadditions.recipes;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.JsonOps;
import de.ellpeck.actuallyadditions.api.lens.Lens;
import de.ellpeck.actuallyadditions.common.ActuallyAdditions;
import de.ellpeck.actuallyadditions.common.items.lens.Lenses;
import net.minecraft.block.BlockState;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.NBTDynamicOps;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistryEntry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AtomicReconstructorBlockRecipeFactory extends ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<AtomicReconstructorBlockRecipe> {
public static final AtomicReconstructorBlockRecipeFactory INSTANCE = IRecipeSerializer.register("actuallyadditions:atomic_reconstructor_block", new AtomicReconstructorBlockRecipeFactory());
@Nonnull
@Override
public AtomicReconstructorBlockRecipe read(@Nonnull ResourceLocation recipeId, @Nonnull JsonObject json){
Lens lens = Lenses.LENS_CONVERSION.get();
BlockState input;
BlockState output;
int energyConsumption = 1000; // default atomic reconstructor energy usage is 1000
if(json.has("lens") && json.get("lens").isJsonObject()){
ResourceLocation lensId = new ResourceLocation(json.get("lens").getAsString());
if(ActuallyAdditions.LENS_REGISTRY.containsKey(lensId)){
lens = ActuallyAdditions.LENS_REGISTRY.getValue(lensId);
} else {
throw new JsonSyntaxException(String.format("Lens type is given, but no lens could be found with id '%s'!", lensId));
}
}
if(json.has("input")){
input = BlockState.deserialize(new Dynamic<>(JsonOps.INSTANCE, json.get("input")));
} else {
throw new JsonSyntaxException("Input is not given for the recipe!");
}
if(json.has("output")){
output = BlockState.deserialize(new Dynamic<>(JsonOps.INSTANCE, json.get("input")));
} else {
throw new JsonSyntaxException("Output is not given for the recipe!");
}
if(json.has("energy") && json.get("energy").isJsonPrimitive()){
energyConsumption = json.get("energy").getAsInt();
}
return new AtomicReconstructorBlockRecipe(recipeId, lens, input, output, energyConsumption);
}
@Nullable
@Override
public AtomicReconstructorBlockRecipe read(@Nonnull ResourceLocation recipeId, @Nonnull PacketBuffer buffer){
ResourceLocation lensId = buffer.readResourceLocation();
CompoundNBT inputNBT = buffer.readCompoundTag();
CompoundNBT outputNBT = buffer.readCompoundTag();
int energyConsumption = buffer.readVarInt();
Lens lens;
if(ActuallyAdditions.LENS_REGISTRY.containsKey(lensId)){
lens = ActuallyAdditions.LENS_REGISTRY.getValue(lensId);
} else {
System.out.println(String.format("Lens is not possible to get while reading packet! '%s'", lensId));
return null;
}
BlockState input = BlockState.deserialize(new Dynamic<>(NBTDynamicOps.INSTANCE, inputNBT));
BlockState output = BlockState.deserialize(new Dynamic<>(NBTDynamicOps.INSTANCE, outputNBT));
return new AtomicReconstructorBlockRecipe(recipeId, lens, input, output, energyConsumption);
}
@Override
public void write(@Nonnull PacketBuffer buffer, @Nonnull AtomicReconstructorBlockRecipe recipe){
buffer.writeResourceLocation(recipe.getId());
INBT inputNBT = BlockState.serialize(NBTDynamicOps.INSTANCE, recipe.getInput()).getValue();
buffer.writeCompoundTag((CompoundNBT) inputNBT); // if it isn't a compound than something real big is wrong and a crash should be the best way to handle it
INBT outputNBT = BlockState.serialize(NBTDynamicOps.INSTANCE, recipe.getOutput()).getValue();
buffer.writeCompoundTag((CompoundNBT) outputNBT);
buffer.writeVarInt(recipe.getEnergyConsumption());
}
}

View File

@ -0,0 +1,62 @@
package de.ellpeck.actuallyadditions.recipes;
import de.ellpeck.actuallyadditions.api.lens.Lens;
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;
/**
* Recipe class for the AtomicReconstructor when hitting a items stack
*/
public class AtomicReconstructorItemRecipe implements IDummyRecipe {
public static final IRecipeType<AtomicReconstructorItemRecipe> ATOMIC_RECONSTRUCTOR_ITEM_RECIPE_TYPE = IRecipeType.register("actuallyadditions:atomic_reconstructor_item");
private final ResourceLocation recipeId;
private final Lens lens;
private final Ingredient input;
private final ItemStack output;
private final int energyConsumption;
public AtomicReconstructorItemRecipe(ResourceLocation recipeId, Lens lens, Ingredient input, ItemStack output, int energyConsumption){
this.recipeId = recipeId;
this.lens = lens;
this.input = input;
this.output = output;
this.energyConsumption = energyConsumption;
}
public Lens getLens(){
return lens;
}
public Ingredient getInput(){
return input;
}
public ItemStack getOutput(){
return output;
}
public int getEnergyConsumption(){
return energyConsumption;
}
@Override
public ResourceLocation getId(){
return this.recipeId;
}
@Override
public IRecipeSerializer<?> getSerializer(){
return AtomicReconstructorItemRecipeFactory.INSTANCE;
}
@Override
public IRecipeType<?> getType(){
return ATOMIC_RECONSTRUCTOR_ITEM_RECIPE_TYPE;
}
}

View File

@ -0,0 +1,85 @@
package de.ellpeck.actuallyadditions.recipes;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import de.ellpeck.actuallyadditions.api.lens.Lens;
import de.ellpeck.actuallyadditions.common.ActuallyAdditions;
import de.ellpeck.actuallyadditions.common.items.lens.Lenses;
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.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistryEntry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class AtomicReconstructorItemRecipeFactory extends ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<AtomicReconstructorItemRecipe> {
public static final AtomicReconstructorItemRecipeFactory INSTANCE = IRecipeSerializer.register("actuallyadditions:atomic_reconstructor_item", new AtomicReconstructorItemRecipeFactory());
@Nonnull
@Override
public AtomicReconstructorItemRecipe read(@Nonnull ResourceLocation recipeId, @Nonnull JsonObject json){
Lens lens = Lenses.LENS_CONVERSION.get();
Ingredient input;
ItemStack output;
int energyConsumption = 1000; // default atomic reconstructor energy usage is 1000
if(json.has("lens") && json.get("lens").isJsonObject()){
ResourceLocation lensId = new ResourceLocation(json.get("lens").getAsString());
if(ActuallyAdditions.LENS_REGISTRY.containsKey(lensId)){
lens = ActuallyAdditions.LENS_REGISTRY.getValue(lensId);
} else {
throw new JsonSyntaxException(String.format("Lens type is given, but no lens could be found with id '%s'!", lensId));
}
}
if(json.has("input")){
input = Ingredient.deserialize(json.get("input"));
} else {
throw new JsonSyntaxException("Input is not given for the recipe!");
}
if(json.has("output") && json.get("output").isJsonObject()){
output = ShapedRecipe.deserializeItem(json.get("output").getAsJsonObject());
} else {
throw new JsonSyntaxException("Output is not given for the recipe!");
}
if(json.has("energy") && json.get("energy").isJsonPrimitive()){
energyConsumption = json.get("energy").getAsInt();
}
return new AtomicReconstructorItemRecipe(recipeId, lens, input, output, energyConsumption);
}
@Nullable
@Override
public AtomicReconstructorItemRecipe read(@Nonnull ResourceLocation recipeId, @Nonnull PacketBuffer buffer){
ResourceLocation lensId = buffer.readResourceLocation();
Ingredient input = Ingredient.read(buffer);
ItemStack output = buffer.readItemStack();
int energyConsumption = buffer.readVarInt();
Lens lens;
if(ActuallyAdditions.LENS_REGISTRY.containsKey(lensId)){
lens = ActuallyAdditions.LENS_REGISTRY.getValue(lensId);
} else {
System.out.println(String.format("Lens is not possible to get while reading packet! '%s'", lensId));
return null;
}
return new AtomicReconstructorItemRecipe(recipeId, lens, input, output, energyConsumption);
}
@Override
public void write(@Nonnull PacketBuffer buffer, @Nonnull AtomicReconstructorItemRecipe recipe){
buffer.writeResourceLocation(recipe.getId());
recipe.getInput().write(buffer);
buffer.writeItemStack(recipe.getOutput());
buffer.writeVarInt(recipe.getEnergyConsumption());
}
}

View File

@ -0,0 +1,42 @@
package de.ellpeck.actuallyadditions.recipes;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
/**
* A dummy Recipe implementation, because the minecraft recipe system forces us to use IRecipe with all of it's methods,
* but we don't need any of them.
* Additionally the "isDynamic()" methods now returns true, because this indicates that the recipe book doesn't list
* this recipe at all.
*/
public interface IDummyRecipe extends IRecipe<IInventory> {
@Override
default boolean matches(IInventory inv, World worldIn){
return false;
}
@Override
default ItemStack getCraftingResult(IInventory inv){
return ItemStack.EMPTY;
}
@Override
default boolean canFit(int width, int height){
return false;
}
@Override
default ItemStack getRecipeOutput(){
return ItemStack.EMPTY;
}
// used for ignoring the recipe book, since this prevents it from showing up.
@Override
default boolean isDynamic(){
return true;
}
}

View File

@ -0,0 +1,5 @@
{
"recipes": {
"atomic_reconstructor": "de.ellpeck.actuallyadditions.recipes.AtomicReconstructorRecipeFactory"
}
}