package gr8pefish.ironbackpacks.events; import gr8pefish.ironbackpacks.api.items.backpacks.interfaces.IBackpack; import gr8pefish.ironbackpacks.capabilities.player.PlayerWearingBackpackCapabilities; import gr8pefish.ironbackpacks.config.ConfigHandler; import gr8pefish.ironbackpacks.container.backpack.ContainerBackpack; import gr8pefish.ironbackpacks.container.backpack.InventoryBackpack; import gr8pefish.ironbackpacks.items.backpacks.ItemBackpack; import gr8pefish.ironbackpacks.items.upgrades.UpgradeMethods; import gr8pefish.ironbackpacks.util.Logger; import gr8pefish.ironbackpacks.util.helpers.IronBackpacksHelper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Items; import net.minecraft.inventory.ContainerWorkbench; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemArrow; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.network.play.server.SPacketCustomSound; import net.minecraft.util.EnumHand; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.oredict.OreDictionary; import org.apache.commons.lang3.tuple.ImmutablePair; import java.util.ArrayList; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; public class IronBackpacksEventHelper { //============================================================================Helper Methods=============================================================================== /** * Gets all the backpacks that have filter, condenser, or restocker upgrades in them for the EntityItemPickupEvent event. * @param player - the player to check * @return - a nested array list of the array lists of each type of backpack that has each filter type */ protected static ArrayList<ArrayList<ItemStack>> getFilterCrafterAndRestockerBackpacks(EntityPlayer player){ ArrayList<ItemStack> filterBackpacks = new ArrayList<ItemStack>(); ArrayList<ItemStack> crafterTinyBackpacks = new ArrayList<ItemStack>(); ArrayList<ItemStack> crafterSmallBackpacks = new ArrayList<ItemStack>(); ArrayList<ItemStack> crafterBackpacks = new ArrayList<ItemStack>(); ArrayList<ItemStack> restockerBackpacks = new ArrayList<ItemStack>(); ArrayList<ArrayList<ItemStack>> returnArray = new ArrayList<ArrayList<ItemStack>>(); //get the equipped pack getEventBackpacks(PlayerWearingBackpackCapabilities.getEquippedBackpack(player), filterBackpacks, crafterTinyBackpacks, crafterSmallBackpacks, crafterBackpacks, restockerBackpacks, player); //get the packs in the inventory for (int i = 0; i < player.inventory.getSizeInventory(); i++) { ItemStack stack = player.inventory.getStackInSlot(i); getEventBackpacks(stack, filterBackpacks, crafterTinyBackpacks, crafterSmallBackpacks, crafterBackpacks, restockerBackpacks, player); } returnArray.add(filterBackpacks); returnArray.add(crafterTinyBackpacks); returnArray.add(crafterSmallBackpacks); returnArray.add(crafterBackpacks); returnArray.add(restockerBackpacks); return returnArray; } protected static void getEventBackpacks(ItemStack backpack, ArrayList<ItemStack> filterBackpacks, ArrayList<ItemStack> crafterTinyBackpacks, ArrayList<ItemStack> crafterSmallBackpacks, ArrayList<ItemStack> crafterBackpacks, ArrayList<ItemStack> restockerBackpacks, EntityPlayer player){ if (backpack != null && backpack.getItem() != null && backpack.getItem() instanceof IBackpack) { ArrayList<ItemStack> upgrades = IronBackpacksHelper.getUpgradesAppliedFromNBT(backpack); addToLists(backpack, filterBackpacks, crafterTinyBackpacks, crafterSmallBackpacks, crafterBackpacks, restockerBackpacks, upgrades); if (UpgradeMethods.hasDepthUpgrade(upgrades)) { ItemBackpack itemBackpack = (ItemBackpack)backpack.getItem(); ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(player, backpack)); for (int j = 0; j < container.getInventoryBackpack().getSizeInventory(); j++) { ItemStack nestedBackpack = container.getInventoryBackpack().getStackInSlot(j); if (nestedBackpack != null && nestedBackpack.getItem() != null && nestedBackpack.getItem() instanceof IBackpack) { addToLists(nestedBackpack, filterBackpacks, crafterTinyBackpacks, crafterSmallBackpacks, crafterBackpacks, restockerBackpacks, IronBackpacksHelper.getUpgradesAppliedFromNBT(nestedBackpack)); } } } } } protected static void addToLists(ItemStack stack, ArrayList<ItemStack> filterBackpacks, ArrayList<ItemStack> crafterTinyBackpacks, ArrayList<ItemStack> crafterSmallBackpacks, ArrayList<ItemStack> crafterBackpacks, ArrayList<ItemStack> restockerBackpacks, ArrayList<ItemStack> upgrades){ if (UpgradeMethods.hasFilterBasicUpgrade(upgrades) || UpgradeMethods.hasFilterModSpecificUpgrade(upgrades) || UpgradeMethods.hasFilterFuzzyUpgrade(upgrades) || UpgradeMethods.hasFilterOreDictUpgrade(upgrades) || UpgradeMethods.hasFilterVoidUpgrade(upgrades) || UpgradeMethods.hasFilterAdvancedUpgrade(upgrades) || UpgradeMethods.hasFilterMiningUpgrade(upgrades)) { filterBackpacks.add(stack); } if (UpgradeMethods.hasCraftingTinyUpgrade(upgrades)) { crafterTinyBackpacks.add(stack); } if (UpgradeMethods.hasCraftingSmallUpgrade(upgrades)) { crafterSmallBackpacks.add(stack); } if (UpgradeMethods.hasCraftingUpgrade(upgrades)) { crafterBackpacks.add(stack); } if (UpgradeMethods.hasRestockingUpgrade(upgrades)) { restockerBackpacks.add(stack); } } //TODO: cleanup the following two methods /** * Checks the hopper/restocking upgrade to try and refill items. * @param event - EntityItemPickupEvent * @param backpackStacks - the backpacks with this upgrade * @return - boolean successful */ protected static boolean checkRestockingUpgradeItemPickup(EntityItemPickupEvent event, ArrayList<ItemStack> backpackStacks){ boolean doFilter = true; boolean shouldSave; if (!backpackStacks.isEmpty()){ for (ItemStack backpack : backpackStacks) { shouldSave = false; ItemBackpack itemBackpack = ((ItemBackpack)backpack.getItem()); //TODO: hardcoded ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(event.getEntityPlayer(), backpack)); //TODO: remove additional itemstack parameter if (!(event.getEntityPlayer().openContainer instanceof ContainerBackpack)) { //can't have the backpack open ArrayList<ItemStack> restockerItems = UpgradeMethods.getRestockingItems(backpack); for (ItemStack restockerItem : restockerItems) { if (restockerItem != null) { boolean foundSlot = false; ItemStack stackToResupply = null; Slot slotToResupply = null; for (int i = itemBackpack.getSize(backpack); i < itemBackpack.getSize(backpack) + 36; i++){ //check player's inv for items Slot tempSlot = container.getSlot(i); if (tempSlot!= null && tempSlot.getHasStack()){ ItemStack tempItem = tempSlot.getStack(); if (IronBackpacksHelper.areItemsEqualAndStackable(tempItem, restockerItem)){ //found and less than max stack size foundSlot = true; slotToResupply = tempSlot; stackToResupply = tempItem; break; } } } if (foundSlot){ //try to resupply with the itemEntity first boolean done = false; if (IronBackpacksHelper.areItemsEqualForStacking(event.getItem().getEntityItem(), stackToResupply)){ int amountToResupply = stackToResupply.getMaxStackSize() - stackToResupply.stackSize; if (event.getItem().getEntityItem().stackSize >= amountToResupply) { //if larger size of stack on the ground than needed to resupply //TODO: not updating event entity correctly, make this work // System.out.println("setting to "+(event.getItem()s.getEntityItem().stackSize - amountToResupply)); // // event.getItem()s.setEntityItemStack(new ItemStack(event.getItem()s.getEntityItem().getItem(), event.getItem()s.getEntityItem().stackSize - amountToResupply, event.getItem()s.getEntityItem().getItemDamage())); // // event.getEntityPlayer().inventory.setInventorySlotContents(slotToResupply.getSlotIndex(), new ItemStack(stackToResupply.getItem(), stackToResupply.getMaxStackSize(), stackToResupply.getItemDamage())); done = true; shouldSave = true; } else { //just resupply what you can, it will automatically go into the player's slot needed doFilter = false; done = false; } } if (!done) { //then resupply from the backpack (if necessary) for (int i = 0; i < itemBackpack.getSize(backpack); i++) { Slot tempSlot = container.getSlot(i); if (tempSlot != null && tempSlot.getHasStack()) { ItemStack tempItem = tempSlot.getStack(); if (IronBackpacksHelper.areItemsEqualForStacking(tempItem, stackToResupply)) { int amountToResupply; if (IronBackpacksHelper.areItemsEqualForStacking(event.getItem().getEntityItem(), stackToResupply)) { //if resupplied already from the items picked up ItemStack stackUpdated = event.getEntityPlayer().inventory.getStackInSlot(slotToResupply.getSlotIndex()); amountToResupply = stackToResupply.getMaxStackSize() - stackUpdated.stackSize - event.getItem().getEntityItem().stackSize; if (tempItem.stackSize >= amountToResupply) { tempSlot.decrStackSize(amountToResupply); event.getEntityPlayer().inventory.setInventorySlotContents(slotToResupply.getSlotIndex(), new ItemStack(stackToResupply.getItem(), stackToResupply.getMaxStackSize() - event.getItem().getEntityItem().stackSize, stackToResupply.getItemDamage())); container.onContainerClosed(event.getEntityPlayer()); break; } else { tempSlot.decrStackSize(tempItem.stackSize); event.getEntityPlayer().inventory.setInventorySlotContents(slotToResupply.getSlotIndex(), new ItemStack(stackToResupply.getItem(), stackUpdated.stackSize + tempItem.stackSize, stackToResupply.getItemDamage())); } } else { //normal resupply, no items picked up contribution ItemStack stackUpdated = event.getEntityPlayer().inventory.getStackInSlot(slotToResupply.getSlotIndex()); amountToResupply = stackToResupply.getMaxStackSize() - stackUpdated.stackSize; if (tempItem.stackSize >= amountToResupply) { tempSlot.decrStackSize(amountToResupply); slotToResupply.putStack(new ItemStack(stackToResupply.getItem(), stackToResupply.getMaxStackSize(), stackToResupply.getItemDamage())); container.onContainerClosed(event.getEntityPlayer()); break; } else { tempSlot.decrStackSize(tempItem.stackSize); event.getEntityPlayer().inventory.setInventorySlotContents(slotToResupply.getSlotIndex(), new ItemStack(stackToResupply.getItem(), stackUpdated.stackSize + tempItem.stackSize, stackToResupply.getItemDamage())); } } shouldSave = true; } } } } } } } } if (shouldSave) { container.onContainerClosed(event.getEntityPlayer()); } } } return doFilter; } /** * Checks the hopper/restocking upgrade to try and refill items. Decrements from the backpack's stacks and updates the appropriate slot/stack in the player's inventory. * for each backpack * if backpack has itemUsed in filter * if backpack has itemUsed in inv * resupply itemUsed * get rid of backpackStack * return new size of itemUsed stack * @param event - PlayerUseItemEvent.Finish * @param backpackStacks - the backpacks with this upgrade */ protected static ItemStack checkRestockerUpgradeItemUse(PlayerInteractEvent.RightClickItem event, ArrayList<ItemStack> backpackStacks){ if (!backpackStacks.isEmpty()){ for (ItemStack backpack : backpackStacks) { // BackpackTypes type = BackpackTypes.values()[((ItemBackpackSubItems) backpack.getItem()).getGuiId()]; ItemBackpack itemBackpack = (ItemBackpack)backpack.getItem(); //TODO: hardcoded ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(event.getEntityPlayer(), backpack)); if (!(event.getEntityPlayer().openContainer instanceof ContainerBackpack)) { //can't have the backpack open container.sort(); //TODO: test with this removed ArrayList<ItemStack> restockerItems = UpgradeMethods.getRestockingItems(backpack); for (ItemStack restockerItem : restockerItems) { if (restockerItem != null) { boolean foundSlot = false; ItemStack stackToResupply = null; Slot slotToResupply = null; for (int i = itemBackpack.getSize(backpack); i < itemBackpack.getSize(backpack) + 36; i++){ //check player's inv for items (backpack size + 36 for player inv) Slot tempSlot = (Slot) container.getSlot(i); if (tempSlot!= null && tempSlot.getHasStack()){ ItemStack tempItem = tempSlot.getStack(); if (IronBackpacksHelper.areItemsEqualForStacking(event.getItemStack(), restockerItem) //has to be same items as what was used in the event && IronBackpacksHelper.areItemsEqualAndStackable(tempItem, restockerItem)){ //found and less than max stack size foundSlot = true; slotToResupply = tempSlot; stackToResupply = tempItem; break; } } } if (foundSlot){ // resupply from the backpack for (int i = 0; i < itemBackpack.getSize(backpack); i++) { Slot backpackSlot = (Slot) container.getSlot(i); if (backpackSlot != null && backpackSlot.getHasStack()) { ItemStack backpackItemStack = backpackSlot.getStack(); if (IronBackpacksHelper.areItemsEqualForStacking(stackToResupply, backpackItemStack)) { int amountToResupply = stackToResupply.getMaxStackSize() - stackToResupply.stackSize; if (backpackItemStack.stackSize >= amountToResupply) { backpackSlot.decrStackSize(amountToResupply); container.sort(); container.onContainerClosed(event.getEntityPlayer()); return (new ItemStack(stackToResupply.getItem(), stackToResupply.getMaxStackSize(), stackToResupply.getItemDamage())); } else { backpackSlot.decrStackSize(backpackItemStack.stackSize); container.sort(); container.onContainerClosed(event.getEntityPlayer()); return (new ItemStack(stackToResupply.getItem(), stackToResupply.stackSize + backpackItemStack.stackSize, stackToResupply.getItemDamage())); //don't have to iterate //b/c once sorted you have as big of a stack as you will ever have so it can only refill that much } } } } } } } } //no save b/c returns and saves if it does anything } } return null; } /** * Checks the hopper/restocking upgrade to try and refill items. Decrements from the backpack's stacks and updates the appropriate slot/stack in the player's inventory. * for each backpack * if backpack has itemUsed in filter * if backpack has itemUsed in inv * resupply itemUsed * get rid of backpackStack * return new size of itemUsed stack * @param backpackStacks - the backpacks with this upgrade */ protected static ItemStack checkRestockerUpgradeItemPlace(EntityPlayer player, EnumHand hand, ItemStack toResupply, ArrayList<ItemStack> backpackStacks){ if (!backpackStacks.isEmpty()){ for (ItemStack backpack : backpackStacks) { // BackpackTypes type = BackpackTypes.values()[((ItemBackpackSubItems) backpack.getItem()).getGuiId()]; ItemBackpack itemBackpack = (ItemBackpack)backpack.getItem(); //TODO: hardcoded ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(player, backpack)); if (!(player.openContainer instanceof ContainerBackpack)) { //can't have the backpack open container.sort(); //TODO: test with this removed ArrayList<ItemStack> restockerItems = UpgradeMethods.getRestockingItems(backpack); for (ItemStack restockerItem : restockerItems) { if (restockerItem != null) { boolean foundSlot = false; ItemStack stackToResupply = null; Slot slotToResupply = null; if (hand == EnumHand.OFF_HAND) { if (IronBackpacksHelper.areItemsEqualForStacking(toResupply, restockerItem) && IronBackpacksHelper.areItemsEqualAndStackable(toResupply, restockerItem) ) { stackToResupply = toResupply; foundSlot = true; } } else { for (int i = itemBackpack.getSize(backpack); i < itemBackpack.getSize(backpack) + 36; i++) { //check player's inv for items (backpack size + 36 for player inv) Slot tempSlot = (Slot) container.getSlot(i); if (tempSlot != null && tempSlot.getHasStack()) { ItemStack tempItem = tempSlot.getStack(); if (IronBackpacksHelper.areItemsEqualForStacking(toResupply, restockerItem) //has to be same items as what was used in the event && IronBackpacksHelper.areItemsEqualAndStackable(tempItem, restockerItem)) { //found and less than max stack size foundSlot = true; slotToResupply = tempSlot; stackToResupply = tempItem; break; } } } } if (foundSlot){ // resupply from the backpack for (int i = 0; i < itemBackpack.getSize(backpack); i++) { Slot backpackSlot = (Slot) container.getSlot(i); if (backpackSlot != null && backpackSlot.getHasStack()) { ItemStack backpackItemStack = backpackSlot.getStack(); if (IronBackpacksHelper.areItemsEqualForStacking(stackToResupply, backpackItemStack)) { int amountToResupply = stackToResupply.getMaxStackSize() - (stackToResupply.stackSize - 1); if (backpackItemStack.stackSize >= amountToResupply) { backpackSlot.decrStackSize(amountToResupply); container.sort(); container.onContainerClosed(player); return (new ItemStack(stackToResupply.getItem(), stackToResupply.getMaxStackSize(), stackToResupply.getItemDamage())); } else { backpackSlot.decrStackSize(backpackItemStack.stackSize); container.sort(); container.onContainerClosed(player); return (new ItemStack(stackToResupply.getItem(), stackToResupply.stackSize + backpackItemStack.stackSize, stackToResupply.getItemDamage())); //don't have to iterate //b/c once sorted you have as big of a stack as you will ever have so it can only refill that much } } } } } } } } //no save b/c returns and saves if it does anything } } return null; } /** * Checks the hopper/restocking upgrade to try and refill items. Decrements from the backpack's stacks and updates the appropriate slot/stack in the player's inventory. * for each backpack * if backpack has itemUsed in filter * if backpack has itemUsed in inv * resupply itemUsed * get rid of backpackStack * return new size of itemUsed stack * @param backpackStacks - the backpacks with this upgrade */ //ToDo: Need to fix it for derivative arrows, works for normal arrows only. protected static ImmutablePair<ItemStack, Slot> checkRestockerUpgradeArrowLoose(EntityPlayer player, ArrayList<ItemStack> backpackStacks){ if (!backpackStacks.isEmpty()){ for (ItemStack backpack : backpackStacks) { // BackpackTypes type = BackpackTypes.values()[((ItemBackpackSubItems) backpack.getItem()).getGuiId()]; ItemBackpack itemBackpack = (ItemBackpack)backpack.getItem(); //TODO: hardcoded ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(player, backpack)); if (!(player.openContainer instanceof ContainerBackpack)) { //can't have the backpack open container.sort(); //TODO: test with this removed ArrayList<ItemStack> restockerItems = UpgradeMethods.getRestockingItems(backpack); for (ItemStack restockerItem : restockerItems) { if ((restockerItem != null) && (restockerItem.getItem() instanceof ItemArrow || restockerItem.getItem().getClass().isAssignableFrom(ItemArrow.class))) { //only restock arrows boolean foundSlot = false; ItemStack stackToResupply = null; Slot slotToResupply = null; for (int i = itemBackpack.getSize(backpack); i < itemBackpack.getSize(backpack) + 36; i++){ //check player's inv for items (backpack size + 36 for player inv) Slot tempSlot = (Slot) container.getSlot(i); if (tempSlot!= null && tempSlot.getHasStack()){ ItemStack tempItem = tempSlot.getStack(); if (tempItem.getItem() instanceof ItemArrow) { if (IronBackpacksHelper.areItemsEqualForStacking(tempItem, restockerItem) //has to be same items as what was used in the event && IronBackpacksHelper.areItemsEqualAndStackable(tempItem, restockerItem)) { //found and less than max stack size foundSlot = true; slotToResupply = tempSlot; stackToResupply = tempItem; break; } } } } if (foundSlot){ // resupply from the backpack for (int i = 0; i < itemBackpack.getSize(backpack); i++) { Slot backpackSlot = (Slot) container.getSlot(i); if (backpackSlot != null && backpackSlot.getHasStack()) { ItemStack backpackItemStack = backpackSlot.getStack(); if (IronBackpacksHelper.areItemsEqualForStacking(stackToResupply, backpackItemStack)) { int amountToResupply = stackToResupply.getMaxStackSize() - (stackToResupply.stackSize - 1); if (backpackItemStack.stackSize >= amountToResupply) { backpackSlot.decrStackSize(amountToResupply); container.sort(); container.onContainerClosed(player); ItemStack stackToReturn = stackToResupply.copy(); stackToReturn.stackSize = stackToResupply.getMaxStackSize(); return new ImmutablePair<>(stackToReturn, slotToResupply); } else { backpackSlot.decrStackSize(backpackItemStack.stackSize); container.sort(); container.onContainerClosed(player); ItemStack stackToReturn = stackToResupply.copy(); stackToReturn.stackSize = stackToResupply.stackSize + backpackItemStack.stackSize; return new ImmutablePair<>(stackToReturn, slotToResupply); //don't have to iterate //b/c once sorted you have as big of a stack as you will ever have so it can only refill that much } } } } } } } } //no save b/c returns and saves if it does anything } } return null; } /** * Checks the backpacks with the crafter/recipes upgrade to craft the specified items * @param event - EntityItemPickupEvent * @param backpackStacks - the backpacks with the crafter upgrade * @param craftingGridDiameterToFill - The size of the recipes grid to try filling with (1x1 or 2x2 or 3x3) */ protected static void checkCrafterUpgrade(EntityItemPickupEvent event, ArrayList<ItemStack> backpackStacks, int craftingGridDiameterToFill){ boolean shouldSave = false; if (!backpackStacks.isEmpty()){ CraftingManager craftingManager = CraftingManager.getInstance(); for (ItemStack backpack : backpackStacks) { shouldSave = false; if (!(event.getEntityPlayer().openContainer instanceof ContainerBackpack)) { //can't have the backpack open // BackpackTypes type = BackpackTypes.values()[((ItemBackpackSubItems) backpack.getItem()).getGuiId()]; ItemBackpack itemBackpack = (ItemBackpack)backpack.getItem(); ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(event.getEntityPlayer(), backpack)); container.sort(); //sort to make sure all items are in their smallest slot numbers possible if (container.getInventoryBackpack().getStackInSlot( //if the last slot has an items container.getInventoryBackpack().getSizeInventory()) != null){ //assume the backpack is full and stop trying to craft break; //TODO: test } ContainerWorkbench containerWorkbench = new ContainerWorkbench(event.getEntityPlayer().inventory, event.getItem().worldObj, new BlockPos(0, 0, 0)); InventoryCrafting inventoryCrafting = new InventoryCrafting(containerWorkbench, 3, 3); //fake workbench/inventory for checking matching recipe ArrayList<ItemStack> crafterItems; switch (craftingGridDiameterToFill){ case 1: crafterItems = UpgradeMethods.getCrafterTinyItems(backpack); break; case 2: crafterItems = UpgradeMethods.getCrafterSmallItems(backpack); break; case 3: crafterItems = UpgradeMethods.getCrafterItems(backpack); break; default: //should be unreachable crafterItems = UpgradeMethods.getCrafterItems(backpack); Logger.error("IronBackpacks CraftingUpgrade Error, will probably give the wrong output"); } for (ItemStack crafterItem : crafterItems) { if (crafterItem != null) { for (int index = 0; index < itemBackpack.getSize(backpack); index++) { Slot theSlot = (Slot) container.getSlot(index); if (theSlot!=null && theSlot.getHasStack()) { ItemStack theStack = theSlot.getStack(); if (theStack != null && theStack.stackSize >= (craftingGridDiameterToFill*craftingGridDiameterToFill) && IronBackpacksHelper.areItemsEqualForStacking(theStack, crafterItem)) { ItemStack myStack = new ItemStack(theStack.getItem(), 1, theStack.getItemDamage()); //stackSize of 1 if (craftingGridDiameterToFill == 2){//special handling needed to make it a square inventoryCrafting.setInventorySlotContents(0, myStack); inventoryCrafting.setInventorySlotContents(1, myStack); inventoryCrafting.setInventorySlotContents(3, myStack); inventoryCrafting.setInventorySlotContents(4, myStack); }else { for (int i = 0; i < (craftingGridDiameterToFill*craftingGridDiameterToFill); i++) { inventoryCrafting.setInventorySlotContents(i, myStack); //recipes grid with a 1x1 (single items) or 3x3 square of the items } } ItemStack recipeOutput = craftingManager.findMatchingRecipe(inventoryCrafting, event.getItem().worldObj); if (recipeOutput != null) { //TODO: test math is correct here shouldSave = true; int numberOfIterations = (int) Math.floor(theStack.stackSize / (craftingGridDiameterToFill * craftingGridDiameterToFill)); int numberOfItems = recipeOutput.stackSize * numberOfIterations; if (numberOfItems > 64){ //multiple stacks, need to make sure there is room //More efficient code [that doesn't work] // int tempNumberOfItems = numberOfItems; // int totalStacks = ((int)Math.ceil(numberOfItems / 64d)); // for (int numOfStacks = 0; numOfStacks < totalStacks; numOfStacks++) { // Logger.info("temp number of items: "+tempNumberOfItems); // ItemStack myRecipeOutput = new ItemStack(recipeOutput.getItem(), tempNumberOfItems, recipeOutput.getItemDamage()); // if (container.transferStackInSlot(myRecipeOutput) != null) { //check if there is room to put them // int decrementAmount = tempNumberOfItems >= 64 ? 64 : tempNumberOfItems; // theSlot.decrStackSize(theStack.stackSize - ((int) Math.ceil(decrementAmount / recipeOutput.stackSize))); // } // tempNumberOfItems -= 64; // } //TODO: iterates an excessive amount, make it more efficient by using the basis of the code above for (int i = 0; i < numberOfIterations; i++){ //for every possible recipes operation ItemStack myRecipeOutput = new ItemStack(recipeOutput.getItem(), recipeOutput.stackSize, recipeOutput.getItemDamage()); //get the output ItemStack stack = container.transferStackInSlot(myRecipeOutput); //try to put that output into the backpack if (stack == null){ //can't put it anywhere break; }else if (stack.stackSize != 0){ //remainder present, stack couldn't be fully transferred, undo the last operation Slot slot = container.getSlot(itemBackpack.getSize(backpack)-1); //last slot in pack slot.putStack(new ItemStack(recipeOutput.getItem(), recipeOutput.getMaxStackSize()-(recipeOutput.stackSize - stack.stackSize), recipeOutput.getItemDamage())); break; } else { //normal condition, stack was fully transferred theSlot.decrStackSize(1); } } }else { ItemStack myRecipeOutput = new ItemStack(recipeOutput.getItem(), numberOfItems, recipeOutput.getItemDamage()); if (container.transferStackInSlot(myRecipeOutput) != null) { theSlot.decrStackSize(theStack.stackSize - (theStack.stackSize % (craftingGridDiameterToFill * craftingGridDiameterToFill))); } container.save(event.getEntityPlayer()); } } } } } } } if (shouldSave) { container.sort(); //sort items container.onContainerClosed(event.getEntityPlayer()); } } } } } //===================================================================Filter Upgrade====================================================================== /** * Checks the filters to see what items should be picked up and put in the backpack(s). * @param event - EntityItemPickupEvent * @param backpackStacks - the backpacks with a filter */ protected static void checkFilterUpgrade(EntityItemPickupEvent event, ArrayList<ItemStack> backpackStacks){ if (!backpackStacks.isEmpty()){ for (ItemStack backpack : backpackStacks) { // BackpackTypes type = BackpackTypes.values()[((ItemBackpackSubItems) backpack.getItem()).getGuiId()]; ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(event.getEntityPlayer(), backpack)); if (!(event.getEntityPlayer().openContainer instanceof ContainerBackpack)) { //can't have the backpack open ArrayList<ItemStack> upgrades = IronBackpacksHelper.getUpgradesAppliedFromNBT(backpack); if (UpgradeMethods.hasFilterBasicUpgrade(upgrades)) transferWithBasicFilter(UpgradeMethods.getBasicFilterItems(backpack), event, container); if (UpgradeMethods.hasFilterModSpecificUpgrade(upgrades)) transferWithModSpecificFilter(UpgradeMethods.getModSpecificFilterItems(backpack), event, container); if (UpgradeMethods.hasFilterFuzzyUpgrade(upgrades)) transferWithFuzzyFilter(UpgradeMethods.getFuzzyFilterItems(backpack), event, container); if (UpgradeMethods.hasFilterOreDictUpgrade(upgrades)) transferWithOreDictFilter(UpgradeMethods.getOreDictFilterItems(backpack), getOreDict(event.getItem().getEntityItem()), event, container); if (UpgradeMethods.hasFilterVoidUpgrade(upgrades)) deleteWithVoidFilter(UpgradeMethods.getVoidFilterItems(backpack), event); if (UpgradeMethods.hasFilterAdvancedUpgrade(upgrades)) { ItemStack[] advFilterItems = UpgradeMethods.getAdvFilterAllItems(backpack); byte[] advFilterButtonStates = UpgradeMethods.getAdvFilterButtonStates(backpack); transferWithBasicFilter(UpgradeMethods.getAdvFilterBasicItems(advFilterItems, advFilterButtonStates), event, container); transferWithModSpecificFilter(UpgradeMethods.getAdvFilterModSpecificItems(advFilterItems, advFilterButtonStates), event, container); transferWithFuzzyFilter(UpgradeMethods.getAdvFilterFuzzyItems(advFilterItems, advFilterButtonStates), event, container); transferWithOreDictFilter(UpgradeMethods.getAdvFilterOreDictItems(advFilterItems, advFilterButtonStates), getOreDict(event.getItem().getEntityItem()), event, container); deleteWithVoidFilter(UpgradeMethods.getAdvFilterVoidItems(advFilterItems, advFilterButtonStates), event); } if (UpgradeMethods.hasFilterMiningUpgrade(upgrades)) transferWithMiningFilter(UpgradeMethods.getMiningFilterItems(backpack), getOreDict(event.getItem().getEntityItem()), event, container); } } } } /** * Transfers items with respect to exact matching. * @param filterItems - the itemstacks to check * @param event - EntityItemPickupEvent * @param container - the backpack to transfer items into */ private static void transferWithBasicFilter(ArrayList<ItemStack> filterItems, EntityItemPickupEvent event, ContainerBackpack container){ boolean shouldSave = false; for (ItemStack filterItem : filterItems) { if (filterItem != null) { if (IronBackpacksHelper.areItemsEqualForStacking(event.getItem().getEntityItem(), filterItem)) { ItemStack returned = container.transferStackInSlot(event.getItem().getEntityItem()); //custom method to put itemEntity's itemStack into the backpack if (returned != null) shouldSave = true; } } } if (shouldSave) { playItemPickupSound(event); container.onContainerClosed(event.getEntityPlayer()); } } /** * Transfers items ignoring damage values. * @param filterItems - the items to check * @param event - EntityItemPickupEvent * @param container - the backpack to transfer items into */ private static void transferWithFuzzyFilter(ArrayList<ItemStack> filterItems, EntityItemPickupEvent event, ContainerBackpack container){ boolean shouldSave = false; for (ItemStack filterItem : filterItems) { if (filterItem != null) { if (event.getItem().getEntityItem().getItem() == filterItem.getItem()) { ItemStack returned = container.transferStackInSlot(event.getItem().getEntityItem()); //custom method to put itemEntity's itemStack into the backpack if (returned != null) shouldSave = true; } } } if (shouldSave) { playItemPickupSound(event); container.onContainerClosed(event.getEntityPlayer()); } } /** * Transfers items with respect to the ore dictionary * @param filterItems - the items to check * @param itemEntityOre - the ore dictionary entry of the items * @param event - EntityItemPickupEvent * @param container - the backpack to move items into */ private static void transferWithOreDictFilter(ArrayList<ItemStack> filterItems, ArrayList<String> itemEntityOre, EntityItemPickupEvent event, ContainerBackpack container){ boolean shouldSave = false; for (ItemStack filterItem : filterItems) { if (filterItem != null) { ArrayList<String> filterItemOre = getOreDict(filterItem); if (itemEntityOre != null && filterItemOre != null) { for (String oreName : itemEntityOre) { if (oreName != null && filterItemOre.contains(oreName)) { ItemStack returned = container.transferStackInSlot(event.getItem().getEntityItem()); //custom method to put itemEntity's itemStack into the backpack if (returned != null) shouldSave = true; } } } } } if (shouldSave) { playItemPickupSound(event); container.onContainerClosed(event.getEntityPlayer()); } } /** * Transfers items with respect to the category of the same mod * @param filterItems - the items to check * @param event - EntityItemPickupEvent * @param container - the backpack to move the items into */ private static void transferWithModSpecificFilter(ArrayList<ItemStack> filterItems, EntityItemPickupEvent event, ContainerBackpack container){ boolean shouldSave = false; for (ItemStack filterItem : filterItems) { if (filterItem != null) { //if modId1 == modId2 same mod so transfer if ((event.getItem().getEntityItem().getItem()).getRegistryName().getResourceDomain().equals(((filterItem.getItem()).getRegistryName().getResourceDomain()))){ ItemStack returned = container.transferStackInSlot(event.getItem().getEntityItem()); //custom method to put itemEntity's itemStack into the backpack if (returned != null) shouldSave = true; } } } if (shouldSave) { playItemPickupSound(event); container.onContainerClosed(event.getEntityPlayer()); } } /** * Transfers items with ore in the name * @param filterItems - the items to check * @param event - EntityItemPickupEvent * @param container - the backpack to move the items into */ private static void transferWithMiningFilter(ArrayList<ItemStack> filterItems, ArrayList<String> itemEntityOre, EntityItemPickupEvent event, ContainerBackpack container){ boolean shouldSave = false; filterItems.add(new ItemStack(Items.COAL, 1, 0)); //add coal to filter addWhitelistEntriesToFilterItems(filterItems); //adds whitelisted items to filter transferWithBasicFilter(filterItems, event, container); if (itemEntityOre != null) { for (String oreName : itemEntityOre) { if (oreName != null && (oreName.startsWith("ore") || oreName.startsWith("gem") || oreName.startsWith("dust"))) { ItemStack returned = container.transferStackInSlot(event.getItem().getEntityItem()); //custom method to put itemEntity's itemStack into the backpack if (returned != null) shouldSave = true; } } } if (shouldSave) { playItemPickupSound(event); container.onContainerClosed(event.getEntityPlayer()); } } /** * Deletes items in the void filter by destroying the entityItem picked up intead of moving it into the backpack or elsewhere * @param filterItems - the items to delete * @param event - EntityItemPickupEvent */ private static void deleteWithVoidFilter(ArrayList<ItemStack> filterItems, EntityItemPickupEvent event){ for (ItemStack stack : filterItems) { if (stack != null) { if (event.getItem().getEntityItem().getItem() == stack.getItem()){ //if same items (but different damage value) event.getItem().setDead(); //delete it event.getItem().onUpdate(); //update to make sure it's gone event.setCanceled(true); //make sure it can't be picked up by other mods/vanilla } } } } /** * Gets the ore dictionary entries from an items * @param itemStack - the items to check * @return - OreDict entries in string form, null if no entries */ private static ArrayList<String> getOreDict(ItemStack itemStack){ int[] ids = OreDictionary.getOreIDs(itemStack); ArrayList<String> retList = new ArrayList<String>(); if (ids.length > 0){ for (int i = 0; i < ids.length; i++) { if (i > 0 && !retList.contains(OreDictionary.getOreName(ids[i]))) { //no duplicates retList.add(OreDictionary.getOreName(ids[i])); }else{ retList.add(OreDictionary.getOreName(ids[i])); } } } return retList.isEmpty() ? null : retList; } //ToDo: Not at runtime private static ArrayList<ItemStack> addWhitelistEntriesToFilterItems(ArrayList<ItemStack> filterItems) { String[] whitelistEntries = ConfigHandler.filterMiningUpgradeWhitelist; for (String entry : whitelistEntries) { ItemStack stack = getItemStackFromString(entry); if (stack != null) filterItems.add(stack); } return filterItems; } private static Pattern pattern = Pattern.compile("((?<modid>.*?):)?(?<item>[^@]*)(@(?<damage>\\d+|[*])(x(?<size>\\d+))?)?"); /** * Construct an {@link ItemStack} from a string in the format modid:itemName@damagexstackSize. * Thanks to Ordinaste for the code. * * @param str the str * @return the item */ private static ItemStack getItemStackFromString(String str) { Matcher matcher = pattern.matcher(str); if (!matcher.find()) return null; String itemString = matcher.group("item"); if (itemString == null) return null; String modid = matcher.group("modid"); if (modid == null) modid = "minecraft"; int damage = 0; String strDamage = matcher.group("damage"); if (strDamage != null) damage = strDamage.equals("*") ? OreDictionary.WILDCARD_VALUE : Integer.parseInt(matcher.group("damage")); //work on wildcard returns multiple items? int size = matcher.group("size") == null ? 1 : Integer.parseInt(matcher.group("size")); if (size == 0) size = 1; Item item = Item.getByNameOrId(modid + ":" + itemString); if (item == null) return null; return new ItemStack(item, size, damage); } /** * Play the item pickup sound * @param event - the item pick up event */ private static void playItemPickupSound(EntityItemPickupEvent event){ Random random = new Random(); EntityPlayerMP playerMP = ((EntityPlayerMP)event.getEntityPlayer()); playerMP.connection.sendPacket(new SPacketCustomSound("minecraft:entity.item.pickup", SoundCategory.PLAYERS, playerMP.getPositionVector().xCoord, playerMP.getPositionVector().yCoord, playerMP.getPositionVector().zCoord, 0.3F, ((random.nextFloat() - random.nextFloat()) * 0.7F + 1.0F) * 2.0F)); } /** * Handles any indirect restocking by scanning the inventory of the player for the first matching item rather than restocking the hand directly. * @param player * @param backpackStacks * @param toResupply */ public static void handleIndirectRestock(EntityPlayer player, ArrayList<ItemStack> backpackStacks, ItemStack toResupply) { //if restockingItem matches toResupply //for each slot in player's inventory (starting with offhand) //if item in slot is equal to toResupply //save that slot //if have a slot //iterate through backpack's inventory //if found a slot with same item as toResupply //join slot items together, update backpack //if slot is now equal to maxStackSize stop iterating, otherwise continue boolean useOffhand; boolean foundSlot; int playerSlotIndexToRestockTo = 0; if (!backpackStacks.isEmpty()) { for (ItemStack backpack : backpackStacks) { ItemBackpack itemBackpack = (ItemBackpack) backpack.getItem(); //TODO: hardcoded ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(player, backpack)); if (!(player.openContainer instanceof ContainerBackpack)) { //can't have the backpack open ArrayList<ItemStack> restockerItems = UpgradeMethods.getRestockingItems(backpack); for (ItemStack restockerItem : restockerItems) { foundSlot = false; useOffhand = false; if (restockerItem != null && IronBackpacksHelper.areItemsEqualAndStackable(toResupply, restockerItem)) { //for each slot in player's inventory (starting with offhand) if (sameItemForRestocking(player.inventory.offHandInventory[0], restockerItem)) { foundSlot = true; useOffhand = true; } else { for (int i = 0; i < player.inventory.mainInventory.length; i++) { if (sameItemForRestocking(player.inventory.getStackInSlot(i), restockerItem)) { foundSlot = true; playerSlotIndexToRestockTo = i; break; } } } //if slot exists to resupply to if (foundSlot) { for (int i = 0; i < itemBackpack.getSize(backpack); i++) { //check backpack's inv for items Slot backpackSlot = (Slot) container.getSlot(i); if (backpackSlot != null && backpackSlot.getHasStack()) { ItemStack backpackItemStack = backpackSlot.getStack(); if (IronBackpacksHelper.areItemsEqualAndStackable(useOffhand ? player.inventory.offHandInventory[0] : player.inventory.mainInventory[playerSlotIndexToRestockTo], backpackItemStack)) { //found resupply slot (accounts for stack size at maximum) ItemStack stackToResupply = useOffhand ? player.inventory.offHandInventory[0] : player.inventory.mainInventory[playerSlotIndexToRestockTo]; int amountToResupply = stackToResupply.getMaxStackSize() - stackToResupply.stackSize; if (backpackItemStack.stackSize >= amountToResupply) { backpackSlot.decrStackSize(amountToResupply); container.onContainerClosed(player); if (useOffhand) player.inventory.offHandInventory[0].stackSize = stackToResupply.getMaxStackSize(); else player.inventory.mainInventory[playerSlotIndexToRestockTo].stackSize = stackToResupply.getMaxStackSize(); player.inventory.markDirty(); return; //full stack size, no point in continuing to iterate } else { backpackSlot.decrStackSize(backpackItemStack.stackSize); container.onContainerClosed(player); if (useOffhand) player.inventory.offHandInventory[0].stackSize += backpackItemStack.stackSize; else player.inventory.mainInventory[playerSlotIndexToRestockTo].stackSize += backpackItemStack.stackSize; player.inventory.markDirty(); } } } } } } } } } } } /** * Handle restocking an item directly (off or mainhand only) * @param player * @param backpackStacks * @param toResupply */ public static void handleDirectRestock(EntityPlayer player, ArrayList<ItemStack> backpackStacks, ItemStack toResupply, boolean preEvent) { boolean useOffhand; boolean foundSlot; boolean firstRestock; int extraCost = preEvent ? 1 : 0; //to deal with BlockPlaceEvent giving the itemStack.stackSize *before* it is placed if (!backpackStacks.isEmpty()) { for (ItemStack backpack : backpackStacks) { ItemBackpack itemBackpack = (ItemBackpack) backpack.getItem(); //TODO: hardcoded ContainerBackpack container = new ContainerBackpack(new InventoryBackpack(player, backpack)); if (!(player.openContainer instanceof ContainerBackpack)) { //can't have the backpack open ArrayList<ItemStack> restockerItems = UpgradeMethods.getRestockingItems(backpack); for (ItemStack restockerItem : restockerItems) { foundSlot = false; useOffhand = false; if (restockerItem != null && IronBackpacksHelper.areItemsEqualAndStackable(toResupply, restockerItem)) { //for each slot in player's inventory (starting with offhand) if (sameItemForRestocking(player.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND), restockerItem)) { foundSlot = true; useOffhand = true; } else if (sameItemForRestocking(player.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND), restockerItem)) { foundSlot = true; useOffhand = false; } else { Logger.warn("Error with restocking. Please create a bug report detailing your actions on Github."); } //if slot exists to resupply to if (foundSlot) { firstRestock = true; for (int i = 0; i < itemBackpack.getSize(backpack); i++) { //check backpack's inv for items Slot backpackSlot = (Slot) container.getSlot(i); if (backpackSlot != null && backpackSlot.getHasStack()) { ItemStack backpackItemStack = backpackSlot.getStack(); if (IronBackpacksHelper.areItemsEqualAndStackable(useOffhand ? player.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND) : player.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND), backpackItemStack)) { //found resupply slot (accounts for stack size at maximum) ItemStack stackToResupply = useOffhand ? player.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND) : player.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND); if (stackToResupply.stackSize + backpackItemStack.stackSize >= stackToResupply.getMaxStackSize()) { //if can refill stack completely backpackSlot.decrStackSize(stackToResupply.getMaxStackSize() - stackToResupply.stackSize + extraCost); container.onContainerClosed(player); ItemStack copy = stackToResupply.copy(); copy.stackSize = copy.getMaxStackSize(); //max stack size if (useOffhand) player.setItemStackToSlot(EntityEquipmentSlot.OFFHAND, copy); else player.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, copy); player.inventory.markDirty(); return; //full stack size, no point in continuing to iterate } else { //can't fully refill with this stack backpackSlot.decrStackSize(backpackItemStack.stackSize); container.onContainerClosed(player); ItemStack copy = stackToResupply.copy(); copy.stackSize += backpackItemStack.stackSize; if (firstRestock) copy.stackSize -= extraCost; //deal with placing block if (useOffhand) player.setItemStackToSlot(EntityEquipmentSlot.OFFHAND, copy); else player.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, copy); player.inventory.markDirty(); firstRestock = false; } } } } } } } } } } } private static boolean sameItemForRestocking(ItemStack toFill, ItemStack toSupply){ if (toFill != null && toSupply != null) { return IronBackpacksHelper.areItemsEqualAndStackable(toFill, toSupply); } return false; } }