package com.Acrobot.Breeze.Utils; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; /** * @author Acrobot */ public class InventoryUtil { private static Boolean legacyContents = null; private static ItemStack[] getStorageContents(Inventory inventory) { if (legacyContents == null) { try { inventory.getStorageContents(); legacyContents = false; } catch (NoSuchMethodError e) { legacyContents = true; } } return legacyContents ? inventory.getContents() : inventory.getStorageContents(); } /** * Returns the amount of the item inside the inventory * * @param item Item to check * @param inventory inventory * @return amount of the item */ public static int getAmount(ItemStack item, Inventory inventory) { if (!inventory.contains(item.getType())) { return 0; } if (inventory.getType() == null) { return Integer.MAX_VALUE; } HashMap items = inventory.all(item.getType()); int itemAmount = 0; for (ItemStack iStack : items.values()) { if (!MaterialUtil.equals(iStack, item)) { continue; } itemAmount += iStack.getAmount(); } return itemAmount; } /** * Tells if the inventory is empty * * @param inventory inventory * @return Is the inventory empty? */ public static boolean isEmpty(Inventory inventory) { for (ItemStack stack : getStorageContents(inventory)) { if (!MaterialUtil.isEmpty(stack)) { return false; } } return true; } /** * Checks if the inventory has stock of this type * * @param items items * @param inventory inventory * @return Does the inventory contain stock of this type? */ public static boolean hasItems(ItemStack[] items, Inventory inventory) { for (ItemStack item : items) { if (getAmount(item, inventory) < item.getAmount()) { return false; } } return true; } /** * Checks if the item fits the inventory * * @param item Item to check * @param inventory inventory * @return Does item fit inside inventory? */ public static boolean fits(ItemStack item, Inventory inventory) { int left = item.getAmount(); if (inventory.getMaxStackSize() == Integer.MAX_VALUE) { return true; } for (ItemStack iStack : getStorageContents(inventory)) { if (left <= 0) { return true; } if (MaterialUtil.isEmpty(iStack)) { left -= item.getMaxStackSize(); continue; } if (!MaterialUtil.equals(iStack, item)) { continue; } left -= (iStack.getMaxStackSize() - iStack.getAmount()); } return left <= 0; } /** * Adds an item to the inventory with given maximum stack size * * @param item Item to add * @param inventory Inventory * @param maxStackSize Maximum item's stack size * @return Number of leftover items */ public static int add(ItemStack item, Inventory inventory, int maxStackSize) { if (item.getAmount() < 1) { return 0; } if (maxStackSize == item.getMaxStackSize()) { return add(item, inventory); } return addManually(item, inventory, maxStackSize); } private static int addManually(ItemStack item, Inventory inventory, int maxStackSize) { int amountLeft = item.getAmount(); for (int currentSlot = 0; currentSlot < effectiveSize(inventory) && amountLeft > 0; currentSlot++) { ItemStack currentItem = inventory.getItem(currentSlot); if (MaterialUtil.isEmpty(currentItem)) { currentItem.setAmount(Math.min(amountLeft, maxStackSize)); amountLeft -= currentItem.getAmount(); } else if (currentItem.getAmount() < maxStackSize && MaterialUtil.equals(currentItem, item)) { int neededToAdd = Math.min(maxStackSize - currentItem.getAmount(), amountLeft); currentItem.setAmount(currentItem.getAmount() + neededToAdd); amountLeft -= neededToAdd; } } return amountLeft; } // Don't use the armor slots or extra slots private static int effectiveSize(Inventory inventory) { return getStorageContents(inventory).length; } /** * Adds an item to the inventor * * @param item Item to add * @param inventory Inventory * @return Number of leftover items */ public static int add(ItemStack item, Inventory inventory) { Map leftovers = inventory.addItem(item.clone()); // item needs to be cloned as cb changes the amount of the stack size if (!leftovers.isEmpty()) { for (Iterator iterator = leftovers.values().iterator(); iterator.hasNext(); ) { ItemStack left = iterator.next(); int amountLeft = addManually(left, inventory, left.getMaxStackSize()); if (amountLeft == 0) { iterator.remove(); } else { left.setAmount(amountLeft); } } } return countItems(leftovers); } /** * Removes an item from the inventory * * @param item Item to remove * @param inventory Inventory * @return Number of items that couldn't be removed */ public static int remove(ItemStack item, Inventory inventory) { Map leftovers = inventory.removeItem(item); if (!leftovers.isEmpty()) { for (Iterator iterator = leftovers.values().iterator(); iterator.hasNext(); ) { ItemStack left = iterator.next(); if (removeManually(left, inventory) == 0) { iterator.remove(); } } } return countItems(leftovers); } private static int removeManually(ItemStack item, Inventory inventory) { int amountLeft = item.getAmount(); for (int currentSlot = 0; currentSlot < effectiveSize(inventory) && amountLeft > 0; currentSlot++) { ItemStack currentItem = inventory.getItem(currentSlot); if (currentItem != null && MaterialUtil.equals(currentItem, item)) { int neededToRemove = Math.min(currentItem.getAmount(), amountLeft); currentItem.setAmount(currentItem.getAmount() - neededToRemove); amountLeft -= neededToRemove; } } return amountLeft; } /** * If items in arguments are similar, this function merges them into stacks of the same type * * @param items Items to merge * @return Merged stack array */ public static ItemStack[] mergeSimilarStacks(ItemStack... items) { if (items.length <= 1) { return items; } List itemList = new LinkedList(); Iterating: for (ItemStack item : items) { for (ItemStack iStack : itemList) { if (MaterialUtil.equals(item, iStack)) { iStack.setAmount(iStack.getAmount() + item.getAmount()); continue Iterating; } } itemList.add(item); } return itemList.toArray(new ItemStack[itemList.size()]); } /** * Counts the amount of items in ItemStacks * * @param items ItemStacks of items to count * @return How many items are there? */ public static int countItems(ItemStack... items) { int count = 0; for (ItemStack item : items) { count += item.getAmount(); } return count; } /** * Counts leftovers from a map * * @param items Leftovers * @return Number of leftovers */ public static int countItems(Map items) { int totalLeft = 0; for (ItemStack left : items.values()) { totalLeft += left.getAmount(); } return totalLeft; } }