Reimplement fix for #68 from #110, using IManaStoringItem and multiple mana flask sizes

This commit is contained in:
Electroblob77
2019-09-04 11:47:23 +01:00
parent 1ba723ade1
commit 3a788c867c
2 changed files with 187 additions and 76 deletions
@@ -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<inv.getSizeInventory(); i++){
ItemStack ingredient = inv.getStackInSlot(i);
if(ingredient.getItem() == chargeable) return ingredient;
}
return ItemStack.EMPTY;
}
// /** lookup for the needed ingredients && return the rechargeable itemstack */
// private ItemStack lookupForIngredients(InventoryCrafting inv, boolean copy){
// ItemStack flask = ItemStack.EMPTY;
// ItemStack rechargeable = ItemStack.EMPTY;
// for(int i = 0; (flask.isEmpty() || rechargeable.isEmpty()) && i < inv.getSizeInventory(); i++){
// ItemStack itemstack = inv.getStackInSlot(i);
// if(!itemstack.isEmpty()){
// if(flask.isEmpty() && itemstack.getItem() == WizardryItems.mana_flask){
// flask = itemstack;
// }else if(rechargeable.isEmpty() && (itemstack.getItem() instanceof ItemWand || itemstack.getItem() instanceof ItemWizardArmour) && itemstack.getItemDamage() > 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);
}
}
}
}
}
@@ -3,9 +3,7 @@ package electroblob.wizardry.registry;
import electroblob.wizardry.Wizardry; import electroblob.wizardry.Wizardry;
import electroblob.wizardry.item.IManaStoringItem; import electroblob.wizardry.item.IManaStoringItem;
import electroblob.wizardry.item.ItemManaFlask; import electroblob.wizardry.item.ItemManaFlask;
import net.minecraft.inventory.ContainerPlayer; import electroblob.wizardry.misc.RecipeRechargeWithFlask;
import net.minecraft.inventory.ContainerWorkbench;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.item.crafting.FurnaceRecipes;
@@ -14,9 +12,6 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 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 net.minecraftforge.registries.IForgeRegistry;
import java.util.LinkedList; import java.util.LinkedList;
@@ -54,84 +49,77 @@ public final class WizardryRecipes {
// Mana flask recipes // Mana flask recipes
ItemStack smallFlaskStack = new ItemStack(WizardryItems.small_mana_flask); Item chargeable;
ItemStack mediumFlaskStack = new ItemStack(WizardryItems.medium_mana_flask);
ItemStack largeFlaskStack = new ItemStack(WizardryItems.large_mana_flask);
ItemStack chargeable;
while(!chargingRecipeQueue.isEmpty()){ while(!chargingRecipeQueue.isEmpty()){
// Use remove() and not poll() because the queue shouldn't be empty in here // 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){ registry.register(new RecipeRechargeWithFlask(chargeable, (ItemManaFlask)WizardryItems.small_mana_flask)
@Override public boolean isDynamic(){ return true; } // Stops it appearing in the recipe book .setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/small_flask_" + chargeable.getRegistryName().getPath())));
}.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/small_flask_" + chargeable.getItem().getRegistryName().getPath())));
registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, mediumFlaskStack){ registry.register(new RecipeRechargeWithFlask(chargeable, (ItemManaFlask)WizardryItems.medium_mana_flask)
@Override public boolean isDynamic(){ return true; } .setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/medium_flask_" + chargeable.getRegistryName().getPath())));
}.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/medium_flask_" + chargeable.getItem().getRegistryName().getPath())));
registry.register(new ShapelessOreRecipe(null, chargeable, chargeable, largeFlaskStack){ registry.register(new RecipeRechargeWithFlask(chargeable, (ItemManaFlask)WizardryItems.large_mana_flask)
@Override public boolean isDynamic(){ return true; } .setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/large_flask_" + chargeable.getRegistryName().getPath())));
}.setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/large_flask_" + chargeable.getItem().getRegistryName().getPath())));
} }
} }
@SubscribeEvent // @SubscribeEvent
public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){ // public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){
//
if(event.phase == TickEvent.Phase.START){ // if(event.phase == TickEvent.Phase.START){
//
if(event.player.openContainer instanceof ContainerWorkbench){ // if(event.player.openContainer instanceof ContainerWorkbench){
//
IInventory craftMatrix = ((ContainerWorkbench)event.player.openContainer).craftMatrix; // IInventory craftMatrix = ((ContainerWorkbench)event.player.openContainer).craftMatrix;
ItemStack output = ((ContainerWorkbench)event.player.openContainer).craftResult.getStackInSlot(0); // ItemStack output = ((ContainerWorkbench)event.player.openContainer).craftResult.getStackInSlot(0);
processManaFlaskCrafting(craftMatrix, output); // processManaFlaskCrafting(craftMatrix, output);
//
}else if(event.player.openContainer instanceof ContainerPlayer){ // }else if(event.player.openContainer instanceof ContainerPlayer){
//
IInventory craftMatrix = ((ContainerPlayer)event.player.openContainer).craftMatrix; // IInventory craftMatrix = ((ContainerPlayer)event.player.openContainer).craftMatrix;
ItemStack output = ((ContainerPlayer)event.player.openContainer).craftResult.getStackInSlot(0); // 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 // // 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 // // inventory, since the only thing tracking whether the player is looking at their inventory is the GUI
// itself, which is client-side only. // // itself, which is client-side only.
processManaFlaskCrafting(craftMatrix, output); // processManaFlaskCrafting(craftMatrix, output);
} // }
} // }
} // }
//
private static void processManaFlaskCrafting(IInventory craftMatrix, ItemStack output){ // private static void processManaFlaskCrafting(IInventory craftMatrix, ItemStack output){
//
// Charges wand using mana flask // // Charges wand using mana flask
//
ItemManaFlask flask = null; // ItemManaFlask flask = null;
ItemStack input = ItemStack.EMPTY; // ItemStack input = ItemStack.EMPTY;
//
for(int i = 0; i < craftMatrix.getSizeInventory(); i++){ // for(int i = 0; i < craftMatrix.getSizeInventory(); i++){
//
ItemStack stack = craftMatrix.getStackInSlot(i); // ItemStack stack = craftMatrix.getStackInSlot(i);
//
if(stack.getItem() instanceof ItemManaFlask){ // if(stack.getItem() instanceof ItemManaFlask){
flask = (ItemManaFlask)stack.getItem(); // flask = (ItemManaFlask)stack.getItem();
} // }
//
if(stack.getItem() instanceof IManaStoringItem){ // if(stack.getItem() instanceof IManaStoringItem){
input = stack; // input = stack;
} // }
} // }
//
if(flask == null) return; // if(flask == null) return;
//
if(output.getItem() instanceof IManaStoringItem && !input.isEmpty()){ // if(output.getItem() instanceof IManaStoringItem && !input.isEmpty()){
//
output.setTagCompound((input.getTagCompound())); // output.setTagCompound((input.getTagCompound()));
//
int currentMana = ((IManaStoringItem)input.getItem()).getMana(input); // int currentMana = ((IManaStoringItem)input.getItem()).getMana(input);
//
((IManaStoringItem)output.getItem()).setMana(output, Math.min(currentMana + flask.size.capacity, // ((IManaStoringItem)output.getItem()).setMana(output, Math.min(currentMana + flask.size.capacity,
((IManaStoringItem)input.getItem()).getManaCapacity(input))); // ((IManaStoringItem)input.getItem()).getManaCapacity(input)));
} // }
} // }
} }