diff --git a/src/main/java/de/ellpeck/actuallyadditions/api/lens/Lens.java b/src/main/java/de/ellpeck/actuallyadditions/api/lens/Lens.java index 95d2cd4fd..82b2c136f 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/api/lens/Lens.java +++ b/src/main/java/de/ellpeck/actuallyadditions/api/lens/Lens.java @@ -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 { /** * Invokes the lens type's behavior on a block diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java b/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java index b4f9efc9a..9456fe355 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/ActuallyAdditions.java @@ -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_REGISTRY = new RegistryBuilder().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(); diff --git a/src/main/java/de/ellpeck/actuallyadditions/common/items/lens/Lenses.java b/src/main/java/de/ellpeck/actuallyadditions/common/items/lens/Lenses.java index 43231be05..1ff660530 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/common/items/lens/Lenses.java +++ b/src/main/java/de/ellpeck/actuallyadditions/common/items/lens/Lenses.java @@ -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 LENSES = DeferredRegister.create(ActuallyAdditions.LENS_REGISTRY, ActuallyAdditions.MODID); + + public static final RegistryObject LENS_CONVERSION = LENSES.register("conversion", LensConversion::new); + public static final RegistryObject LENS_DETONATION = LENSES.register("detonation", LensDetonation::new); + public static final RegistryObject LENS_DEATH = LENSES.register("death", LensDeath::new); + public static final RegistryObject LENS_KILLER = LENSES.register("killer", LensKiller::new); + public static final RegistryObject LENS_COLOR = LENSES.register("color", LensColor::new); + public static final RegistryObject LENS_DISRUPTION = LENSES.register("disruption", LensDisruption::new); + public static final RegistryObject LENS_DISENCHANTING = LENSES.register("disenchanting", LensDisenchanting::new); + public static final RegistryObject LENS_MINING = LENSES.register("mining", LensMining::new); + + } diff --git a/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorBlockRecipe.java b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorBlockRecipe.java new file mode 100644 index 000000000..81b0bd51b --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorBlockRecipe.java @@ -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 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; + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorBlockRecipeFactory.java b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorBlockRecipeFactory.java new file mode 100644 index 000000000..0fcfb77d5 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorBlockRecipeFactory.java @@ -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> implements IRecipeSerializer { + + 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()); + } + +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorItemRecipe.java b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorItemRecipe.java new file mode 100644 index 000000000..440f35b2d --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorItemRecipe.java @@ -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 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; + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorItemRecipeFactory.java b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorItemRecipeFactory.java new file mode 100644 index 000000000..306f6e0e3 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/recipes/AtomicReconstructorItemRecipeFactory.java @@ -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> implements IRecipeSerializer { + + 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()); + } + +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/recipes/IDummyRecipe.java b/src/main/java/de/ellpeck/actuallyadditions/recipes/IDummyRecipe.java new file mode 100644 index 000000000..cee64c989 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/recipes/IDummyRecipe.java @@ -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 { + + @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; + } + +} diff --git a/src/main/resources/assets/actuallyadditions/recipes/_factories.json b/src/main/resources/assets/actuallyadditions/recipes/_factories.json new file mode 100644 index 000000000..de353d32d --- /dev/null +++ b/src/main/resources/assets/actuallyadditions/recipes/_factories.json @@ -0,0 +1,5 @@ +{ + "recipes": { + "atomic_reconstructor": "de.ellpeck.actuallyadditions.recipes.AtomicReconstructorRecipeFactory" + } +} \ No newline at end of file