From 3a788c867c718097977a8c115f8c34fb8d54c1de Mon Sep 17 00:00:00 2001 From: Electroblob77 <35599699+Electroblob77@users.noreply.github.com> Date: Wed, 4 Sep 2019 11:47:23 +0100 Subject: [PATCH] Reimplement fix for #68 from #110, using IManaStoringItem and multiple mana flask sizes --- .../misc/RecipeRechargeWithFlask.java | 123 +++++++++++++++ .../wizardry/registry/WizardryRecipes.java | 140 ++++++++---------- 2 files changed, 187 insertions(+), 76 deletions(-) create mode 100644 src/main/java/electroblob/wizardry/misc/RecipeRechargeWithFlask.java diff --git a/src/main/java/electroblob/wizardry/misc/RecipeRechargeWithFlask.java b/src/main/java/electroblob/wizardry/misc/RecipeRechargeWithFlask.java new file mode 100644 index 00000000..88ca841f --- /dev/null +++ b/src/main/java/electroblob/wizardry/misc/RecipeRechargeWithFlask.java @@ -0,0 +1,123 @@ +package electroblob.wizardry.misc; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.ItemManaFlask; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.oredict.OreDictionary; +import net.minecraftforge.oredict.ShapelessOreRecipe; + +import javax.annotation.Nonnull; + +/** + * Implements a dynamic crafting recipe for recharging items with mana flasks. + * + * @author Corail31, Electroblob + * @since Wizardry 4.2.2 + */ +@Mod.EventBusSubscriber +public class RecipeRechargeWithFlask extends ShapelessOreRecipe { + + private final IManaStoringItem chargeable; + private final ItemManaFlask flask; + + /** + * Creates a new charging recipe for the given chargeable item using the given flask item. + * @param chargeable The type of item to be charged + * @param flask The mana flask used to charge the item + */ + public RecipeRechargeWithFlask(Item chargeable, ItemManaFlask flask){ + super(null, new ItemStack(chargeable, 1, OreDictionary.WILDCARD_VALUE), + new ItemStack(chargeable, 1, OreDictionary.WILDCARD_VALUE), flask); + if(!(chargeable instanceof IManaStoringItem)) throw new IllegalArgumentException("Item to be charged must be an instance of IManaStoringItem"); + this.chargeable = (IManaStoringItem)chargeable; + this.flask = flask; + } + + @Nonnull + @Override + public ItemStack getRecipeOutput(){ + return ItemStack.EMPTY; // According to the javadoc, dynamic recipes are supposed to return an empty stack here + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inv){ + ItemStack result = super.getCraftingResult(inv);//lookupForIngredients(inv, true); + rechargeItem(result, inv); + return result; + } + + @Override + public boolean matches(InventoryCrafting inv, World world){ + ItemStack stack = findItemToCharge(inv); + if(!stack.isEmpty() && chargeable.isManaFull(stack)) return false; + return super.matches(inv, world); + //return !lookupForIngredients(inv, false).isEmpty(); + } + + private void rechargeItem(ItemStack toCharge, InventoryCrafting inv){ + if(toCharge.getItem() == chargeable){ + ItemStack stack = findItemToCharge(inv); + if(!stack.isEmpty()) chargeable.setMana(toCharge, chargeable.getMana(stack)); + chargeable.rechargeMana(toCharge, flask.size.capacity); + }else{ + Wizardry.logger.warn("Tried to recharge item {} with mana flask, but it did not match the recipe result {}!", toCharge.getItem(), chargeable); + } + } + + private ItemStack findItemToCharge(InventoryCrafting inv){ + for(int i=0; i 0){ +// rechargeable = copy ? itemstack.copy() : itemstack; +// }else{ +// return ItemStack.EMPTY; +// } +// } +// } +// return flask.isEmpty() || rechargeable.isEmpty() ? ItemStack.EMPTY : rechargeable; +// } + + @Override + public boolean isDynamic(){ + return true; // Stops it appearing in the recipe book + } + + @SubscribeEvent + public static void onItemCraftedEvent(PlayerEvent.ItemCraftedEvent event){ + // getCraftingResult seems to only work for the result that's displayed, not once it is actually taken + // This means that although I no longer have to replace the result every tick, I still need to do it here + // ... I thought the whole point of the new recipe system was so that I DIDN'T have to do this?! + if(event.craftMatrix instanceof InventoryCrafting){ + for(IRecipe recipe : CraftingManager.REGISTRY){ + if(recipe instanceof RecipeRechargeWithFlask + && recipe.matches((InventoryCrafting)event.craftMatrix, event.player.world)){ + // Have to modify the itemstack in the actual event, it cannot be replaced + ((RecipeRechargeWithFlask)recipe).rechargeItem(event.crafting, (InventoryCrafting)event.craftMatrix); + } + } + } + } +} diff --git a/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java b/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java index f2691884..ac71efdf 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryRecipes.java @@ -3,9 +3,7 @@ package electroblob.wizardry.registry; import electroblob.wizardry.Wizardry; import electroblob.wizardry.item.IManaStoringItem; import electroblob.wizardry.item.ItemManaFlask; -import net.minecraft.inventory.ContainerPlayer; -import net.minecraft.inventory.ContainerWorkbench; -import net.minecraft.inventory.IInventory; +import electroblob.wizardry.misc.RecipeRechargeWithFlask; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.FurnaceRecipes; @@ -14,9 +12,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import net.minecraftforge.oredict.OreDictionary; -import net.minecraftforge.oredict.ShapelessOreRecipe; import net.minecraftforge.registries.IForgeRegistry; import java.util.LinkedList; @@ -54,84 +49,77 @@ public final class WizardryRecipes { // Mana flask recipes - ItemStack smallFlaskStack = new ItemStack(WizardryItems.small_mana_flask); - ItemStack mediumFlaskStack = new ItemStack(WizardryItems.medium_mana_flask); - ItemStack largeFlaskStack = new ItemStack(WizardryItems.large_mana_flask); - - ItemStack chargeable; + Item chargeable; while(!chargingRecipeQueue.isEmpty()){ // Use remove() and not poll() because the queue shouldn't be empty in here - chargeable = new ItemStack(chargingRecipeQueue.remove(), 1, OreDictionary.WILDCARD_VALUE); + chargeable = chargingRecipeQueue.remove(); - registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, smallFlaskStack){ - @Override public boolean isDynamic(){ return true; } // Stops it appearing in the recipe book - }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/small_flask_" + chargeable.getItem().getRegistryName().getPath()))); + registry.register(new RecipeRechargeWithFlask(chargeable, (ItemManaFlask)WizardryItems.small_mana_flask) + .setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/small_flask_" + chargeable.getRegistryName().getPath()))); - registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, mediumFlaskStack){ - @Override public boolean isDynamic(){ return true; } - }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/medium_flask_" + chargeable.getItem().getRegistryName().getPath()))); + registry.register(new RecipeRechargeWithFlask(chargeable, (ItemManaFlask)WizardryItems.medium_mana_flask) + .setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/medium_flask_" + chargeable.getRegistryName().getPath()))); - registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, largeFlaskStack){ - @Override public boolean isDynamic(){ return true; } - }.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/large_flask_" + chargeable.getItem().getRegistryName().getPath()))); + registry.register(new RecipeRechargeWithFlask(chargeable, (ItemManaFlask)WizardryItems.large_mana_flask) + .setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/large_flask_" + chargeable.getRegistryName().getPath()))); } } - @SubscribeEvent - public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ - - if(event.phase == TickEvent.Phase.START){ - - if(event.player.openContainer instanceof ContainerWorkbench){ - - IInventory craftMatrix = ((ContainerWorkbench)event.player.openContainer).craftMatrix; - ItemStack output = ((ContainerWorkbench)event.player.openContainer).craftResult.getStackInSlot(0); - processManaFlaskCrafting(craftMatrix, output); - - }else if(event.player.openContainer instanceof ContainerPlayer){ - - IInventory craftMatrix = ((ContainerPlayer)event.player.openContainer).craftMatrix; - ItemStack output = ((ContainerPlayer)event.player.openContainer).craftResult.getStackInSlot(0); - // Unfortunately I have no choice but to call this method every tick when the player isn't using another - // inventory, since the only thing tracking whether the player is looking at their inventory is the GUI - // itself, which is client-side only. - processManaFlaskCrafting(craftMatrix, output); - } - } - } - - private static void processManaFlaskCrafting(IInventory craftMatrix, ItemStack output){ - - // Charges wand using mana flask - - ItemManaFlask flask = null; - ItemStack input = ItemStack.EMPTY; - - for(int i = 0; i < craftMatrix.getSizeInventory(); i++){ - - ItemStack stack = craftMatrix.getStackInSlot(i); - - if(stack.getItem() instanceof ItemManaFlask){ - flask = (ItemManaFlask)stack.getItem(); - } - - if(stack.getItem() instanceof IManaStoringItem){ - input = stack; - } - } - - if(flask == null) return; - - if(output.getItem() instanceof IManaStoringItem && !input.isEmpty()){ - - output.setTagCompound((input.getTagCompound())); - - int currentMana = ((IManaStoringItem)input.getItem()).getMana(input); - - ((IManaStoringItem)output.getItem()).setMana(output, Math.min(currentMana + flask.size.capacity, - ((IManaStoringItem)input.getItem()).getManaCapacity(input))); - } - } +// @SubscribeEvent +// public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ +// +// if(event.phase == TickEvent.Phase.START){ +// +// if(event.player.openContainer instanceof ContainerWorkbench){ +// +// IInventory craftMatrix = ((ContainerWorkbench)event.player.openContainer).craftMatrix; +// ItemStack output = ((ContainerWorkbench)event.player.openContainer).craftResult.getStackInSlot(0); +// processManaFlaskCrafting(craftMatrix, output); +// +// }else if(event.player.openContainer instanceof ContainerPlayer){ +// +// IInventory craftMatrix = ((ContainerPlayer)event.player.openContainer).craftMatrix; +// ItemStack output = ((ContainerPlayer)event.player.openContainer).craftResult.getStackInSlot(0); +// // Unfortunately I have no choice but to call this method every tick when the player isn't using another +// // inventory, since the only thing tracking whether the player is looking at their inventory is the GUI +// // itself, which is client-side only. +// processManaFlaskCrafting(craftMatrix, output); +// } +// } +// } +// +// private static void processManaFlaskCrafting(IInventory craftMatrix, ItemStack output){ +// +// // Charges wand using mana flask +// +// ItemManaFlask flask = null; +// ItemStack input = ItemStack.EMPTY; +// +// for(int i = 0; i < craftMatrix.getSizeInventory(); i++){ +// +// ItemStack stack = craftMatrix.getStackInSlot(i); +// +// if(stack.getItem() instanceof ItemManaFlask){ +// flask = (ItemManaFlask)stack.getItem(); +// } +// +// if(stack.getItem() instanceof IManaStoringItem){ +// input = stack; +// } +// } +// +// if(flask == null) return; +// +// if(output.getItem() instanceof IManaStoringItem && !input.isEmpty()){ +// +// output.setTagCompound((input.getTagCompound())); +// +// int currentMana = ((IManaStoringItem)input.getItem()).getMana(input); +// +// ((IManaStoringItem)output.getItem()).setMana(output, Math.min(currentMana + flask.size.capacity, +// ((IManaStoringItem)input.getItem()).getManaCapacity(input))); +// } +// } }