/* * This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT). * * Copyright (c) JCThePants (www.jcwhatever.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jcwhatever.nucleus.utils.inventory; import com.jcwhatever.nucleus.utils.PreCon; import com.jcwhatever.nucleus.utils.items.ItemStackMatcher; import com.jcwhatever.nucleus.utils.items.ItemStackUtils; import com.jcwhatever.nucleus.utils.materials.MaterialProperty; import com.jcwhatever.nucleus.utils.materials.Materials; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Provides static methods to help with inventories of {@link org.bukkit.inventory.ItemStack}'s. */ public final class InventoryUtils { private InventoryUtils() {} /** * Add and merge item stacks into an {@link org.bukkit.inventory.ItemStack} array. * * <p>Merges matching item stacks if there is room.</p> * * @param array The array to add items stacks to. * @param itemStacks The item stacks to add. * * @return A list of {@link org.bukkit.inventory.ItemStack}'s that could not be added. */ public static List<ItemStack> add(ItemStack[] array, ItemStack... itemStacks) { List<ItemStack> toAdd = new ArrayList<>(itemStacks.length); Collections.addAll(toAdd, itemStacks); ItemStackMatcher matcher = ItemStackMatcher.getTypeMetaDurability(); for (int i=0; i < array.length; i++) { ItemStack item = array[i]; Iterator<ItemStack> iterator = toAdd.iterator(); while (iterator.hasNext()) { ItemStack newItem = iterator.next(); if (newItem == null || newItem.getType() == Material.AIR) { iterator.remove(); continue; } if (item == null || item.getType() == Material.AIR) { array[i] = newItem; iterator.remove(); continue; } int maxStackSize = item.getType().getMaxStackSize(); // make sure item is not already full if (item.getAmount() == maxStackSize) break; if (!matcher.isMatch(item, newItem)) continue; // merge int space = maxStackSize - item.getAmount(); int add = Math.min(newItem.getAmount(), space); item.setAmount(item.getAmount() + add); if (newItem.getAmount() >= add) { iterator.remove(); } else { newItem.setAmount(newItem.getAmount() - add); } // check no more room in item if (add == space) break; } // check no more items to add if (toAdd.size() == 0) break; } return toAdd; } /** * Add and merge item stacks into an {@link org.bukkit.inventory.ItemStack} collection. * * <p>Merges matching item stacks if there is room.</p> * * @param collection The array to add items stacks to. * @param itemStacks The item stacks to add. */ public static void add(Collection<ItemStack> collection, ItemStack... itemStacks) { List<ItemStack> list = collection instanceof ArrayList ? (ArrayList<ItemStack>)collection : new ArrayList<ItemStack>(collection); List<ItemStack> toAdd = new ArrayList<>(itemStacks.length); Collections.addAll(toAdd, itemStacks); ItemStackMatcher matcher = ItemStackMatcher.getTypeMetaDurability(); for (int i=0; i < list.size(); i++) { ItemStack item = list.get(i); Iterator<ItemStack> iterator = toAdd.iterator(); while (iterator.hasNext()) { ItemStack newItem = iterator.next(); if (newItem == null || newItem.getType() == Material.AIR) { iterator.remove(); continue; } if (item == null || item.getType() == Material.AIR) { list.set(i, newItem); iterator.remove(); continue; } int maxStackSize = item.getType().getMaxStackSize(); // make sure item is not already full if (item.getAmount() == maxStackSize) break; if (!matcher.isMatch(item, newItem)) continue; // merge int space = maxStackSize - item.getAmount(); int add = Math.min(newItem.getAmount(), space); item.setAmount(item.getAmount() + add); if (newItem.getAmount() >= add) { iterator.remove(); } else { newItem.setAmount(newItem.getAmount() - add); } // check no more room in item if (add == space) break; } // check no more items to add if (toAdd.size() == 0) break; } list.addAll(toAdd); if (!(collection instanceof ArrayList)) { collection.clear(); collection.addAll(list); } } /** * Gets the number of items of the specified stack that can be stored in * the specified inventory. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static int getMax(Inventory inventory, ItemStack itemStack) { return getMax(inventory.getContents(), itemStack, ItemStackMatcher.getTypeMetaDurability(), -1); } /** * Gets the number of items of the specified stack that can be stored in * the specified inventory. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static int getMax(Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher) { return getMax(inventory.getContents(), itemStack, matcher, -1); } /** * Gets the number of items of the specified stack that * can be stored in the specified {@link org.bukkit.inventory.ItemStack} array. * * @param contents The inventory contents. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static int getMax(ItemStack[] contents, ItemStack itemStack) { return getMax(contents, itemStack, ItemStackMatcher.getTypeMetaDurability(), -1); } /** * Gets the number of items of the specified stack that * can be stored in the specified {@link org.bukkit.inventory.ItemStack} array. * * @param contents The inventory contents. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static int getMax(ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher) { return getMax(contents, itemStack, matcher, -1); } /** * Determine if there is enough room in the specified inventory for the * specified stack. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static boolean hasRoom(Inventory inventory, ItemStack itemStack) { return hasRoom(inventory, itemStack, itemStack.getAmount()); } /** * Determine if there is enough room in the specified inventory for the * specified stack. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static boolean hasRoom(Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher) { return hasRoom(inventory, itemStack, matcher, itemStack.getAmount()); } /** * Determine if there is enough room in the specified inventory for * items of the same type as the specified stack in the amount of * the specified quantity. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param qty The amount of space needed. */ public static boolean hasRoom(Inventory inventory, ItemStack itemStack, int qty) { return getMax(inventory.getContents(), itemStack, ItemStackMatcher.getTypeMetaDurability(), qty) >= qty; } /** * Determine if there is enough room in the specified inventory for * items of the same type as the specified stack in the amount of the * specified quantity. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. * @param qty The quantity. */ public static boolean hasRoom(Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher, int qty) { return getMax(inventory.getContents(), itemStack, matcher, qty) >= qty; } /** * Determine if there is enough room in the specified {@link ItemStack} array * for items of the same type as the specified stack in the amount of the * specified quantity. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static boolean hasRoom(ItemStack[] contents, ItemStack itemStack) { return getMax(contents, itemStack, ItemStackMatcher.getTypeMetaDurability(), itemStack.getAmount()) >= itemStack.getAmount(); } /** * Determine if there is enough room in the specified {@link org.bukkit.inventory.ItemStack} array * for items of the same type as the specified stack in the amount of the * specified quantity. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param qty The quantity. */ public static boolean hasRoom(ItemStack[] contents, ItemStack itemStack, int qty) { return getMax(contents, itemStack, ItemStackMatcher.getTypeMetaDurability(), qty) >= qty; } /** * Determine if there is enough room in the specified {@link ItemStack} array * for items of the same type as the specified stack in the amount of the * specified quantity. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. * @param qty The quantity. */ public static boolean hasRoom(ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher, int qty) { return getMax(contents, itemStack, matcher, qty) >= qty; } /** * Count the number of items of the same type as the specified item stack * in the specified inventory. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static int count (Inventory inventory, ItemStack itemStack) { return count(inventory, itemStack, ItemStackMatcher.getTypeMetaDurability()); } /** * Count the number of items of the same type as the specified item stack * in the specified inventory. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static int count (Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher) { return count(inventory.getContents(), itemStack, matcher, -1); } /** * Count the number of items of the same type as the specified item stack * in the specified {@link org.bukkit.inventory.ItemStack} array. * * @param contents The inventory contents. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static int count (ItemStack[] contents, ItemStack itemStack) { return count(contents, itemStack, ItemStackMatcher.getTypeMetaDurability(), -1); } /** * Count the number of items of the same type as the specified item stack * in the specified {@link org.bukkit.inventory.ItemStack} array. * * @param contents The inventory contents. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static int count (ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher) { return count(contents, itemStack, matcher, -1); } /** * Determine if the specified inventory contains an item stack * that matches the specified item stack. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static boolean has(Inventory inventory, ItemStack itemStack) { return has (inventory, itemStack, ItemStackMatcher.getTypeMetaDurability()); } /** * Determine if the specified inventory contains an item stack * that matches the specified item stack. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static boolean has(Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher) { PreCon.notNull(inventory); PreCon.notNull(itemStack); PreCon.notNull(matcher); ItemStack[] contents = inventory.getContents(); for (ItemStack item : contents) { if (item == null || item.getType() == Material.AIR) continue; if (matcher.isMatch(itemStack, item)) return true; } if (inventory instanceof PlayerInventory) { PlayerInventory playerInventory = (PlayerInventory)inventory; Set<MaterialProperty> properties = Materials.getProperties(itemStack.getType()); if (properties.contains(MaterialProperty.ARMOR)) { if (properties.contains(MaterialProperty.HELMET) && matcher.isMatch(playerInventory.getHelmet(), itemStack)) { return true; } else if (properties.contains(MaterialProperty.CHESTPLATE) && matcher.isMatch(playerInventory.getChestplate(), itemStack)) { return true; } else if (properties.contains(MaterialProperty.LEGGINGS) && matcher.isMatch(playerInventory.getLeggings(), itemStack)) { return true; } else if (properties.contains(MaterialProperty.BOOTS) && matcher.isMatch(playerInventory.getBoots(), itemStack)) { return true; } } } return false; } /** * Determine if the specified inventory contains the specified quantity * of items that match the specified {@link org.bukkit.inventory.ItemStack}. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param qty The quantity. */ public static boolean has (Inventory inventory, ItemStack itemStack, int qty) { return has(inventory, itemStack, ItemStackMatcher.getTypeMetaDurability(), qty); } /** * Determine if the specified inventory contains the specified quantity * of items that match the specified {@link org.bukkit.inventory.ItemStack}. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. * @param qty The quantity. */ public static boolean has (Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher, int qty) { return count(inventory, itemStack, matcher, qty) >= qty; } /** * Determine if the specified {@link org.bukkit.inventory.ItemStack} array contains an item stack * that matches the specified {@link org.bukkit.inventory.ItemStack}. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static boolean has(ItemStack[] contents, ItemStack itemStack) { return has(contents, itemStack, ItemStackMatcher.getTypeMetaDurability()); } /** * Determine if the specified {@link org.bukkit.inventory.ItemStack} array contains an item stack * that matches the specified {@link org.bukkit.inventory.ItemStack}. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static boolean has(ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher) { PreCon.notNull(contents); PreCon.notNull(itemStack); PreCon.notNull(matcher); for (ItemStack item : contents) { if (item == null || item.getType() == Material.AIR) continue; if (matcher.isMatch(itemStack, item)) return true; } return false; } /** * Determine if the specified {@link org.bukkit.inventory.ItemStack} array contains the specified quantity * of items that match the specified {@link org.bukkit.inventory.ItemStack}. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param qty The quantity. */ public static boolean has (ItemStack[] contents, ItemStack itemStack, int qty) { return has(contents, itemStack, ItemStackMatcher.getTypeMetaDurability(), qty); } /** * Determine if the specified {@link org.bukkit.inventory.ItemStack} array contains the specified quantity * of items that match the specified {@link org.bukkit.inventory.ItemStack}. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. * @param qty The quantity. */ public static boolean has (ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher, int qty) { PreCon.notNull(contents); PreCon.notNull(itemStack); PreCon.notNull(matcher); PreCon.positiveNumber(qty); int count = count(contents, itemStack, matcher, qty); return count >= qty; } /** * Get all {@link org.bukkit.inventory.ItemStack}'s that match the specified * {@link org.bukkit.inventory.ItemStack} from the specified inventory. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static ItemStack[] getAll (Inventory inventory, ItemStack itemStack) { return getAll(inventory, itemStack, ItemStackMatcher.getTypeMetaDurability()); } /** * Get all {@link org.bukkit.inventory.ItemStack}'s that match the specified * {@link org.bukkit.inventory.ItemStack} from the specified inventory. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static ItemStack[] getAll (Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher) { return getAll(inventory.getContents(), itemStack, matcher); } /** * Get all {@link org.bukkit.inventory.ItemStack}'s that match the specified * {@link org.bukkit.inventory.ItemStack} from the specified {@link ItemStack} array. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. */ public static ItemStack[] getAll (ItemStack[] contents, ItemStack itemStack) { return getAll(contents, itemStack, ItemStackMatcher.getTypeMetaDurability()); } /** * Get all {@link org.bukkit.inventory.ItemStack}'s that match the specified * {@link org.bukkit.inventory.ItemStack} from the specified * {@link org.bukkit.inventory.ItemStack} array. * * @param contents The inventory contents to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. */ public static ItemStack[] getAll (ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher) { PreCon.notNull(contents); PreCon.notNull(itemStack); PreCon.notNull(matcher); List<ItemStack> items = new ArrayList<ItemStack>(contents.length); for (ItemStack item : contents) { if (item == null || item.getType() == Material.AIR) continue; if (matcher.isMatch(itemStack, item)) items.add(item); } return items.toArray(new ItemStack[items.size()]); } /** * Remove specified items from the the {@link org.bukkit.inventory.ItemStack} array. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param contents The array to remove items from. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(ItemStack[] contents, ItemStack... itemStacks) { ItemStackMatcher matcher = ItemStackMatcher.getTypeMetaDurability(); return remove(contents, matcher, itemStacks); } /** * Remove specified items from the the {@link org.bukkit.inventory.ItemStack} array. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param contents The array to remove items from. * @param matcher The matcher to use. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(ItemStack[] contents, ItemStackMatcher matcher, ItemStack... itemStacks) { PreCon.notNull(contents); PreCon.notNull(matcher); PreCon.notNull(itemStacks); List<ItemStack> result = new ArrayList<>(itemStacks.length); for (ItemStack item : itemStacks) { result.addAll(removeAmount(contents, item, matcher, item.getAmount())); } return result; } /** * Remove specified items from the the {@link org.bukkit.inventory.ItemStack} array. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param contents The array to remove items from. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(ItemStack[] contents, Collection<ItemStack> itemStacks) { ItemStackMatcher matcher = ItemStackMatcher.getTypeMetaDurability(); return remove(contents, matcher, itemStacks); } /** * Remove specified items from the the {@link org.bukkit.inventory.ItemStack} array. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param contents The array to remove items from. * @param matcher The matcher to use. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(ItemStack[] contents, ItemStackMatcher matcher, Collection<ItemStack> itemStacks) { PreCon.notNull(contents); PreCon.notNull(matcher); PreCon.notNull(itemStacks); List<ItemStack> result = new ArrayList<>(itemStacks.size()); for (ItemStack item : itemStacks) { result.addAll(removeAmount(contents, item, matcher, item.getAmount())); } return result; } /** * Remove specified items from the the inventory. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param inventory The inventory to remove items from. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(Inventory inventory, ItemStack... itemStacks) { ItemStackMatcher matcher = ItemStackMatcher.getTypeMetaDurability(); return remove(inventory, matcher, itemStacks); } /** * Remove specified items from the the inventory. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param inventory The inventory to remove items from. * @param matcher The matcher to use. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(Inventory inventory, ItemStackMatcher matcher, ItemStack... itemStacks) { PreCon.notNull(inventory); PreCon.notNull(matcher); PreCon.notNull(itemStacks); List<ItemStack> result = new ArrayList<>(itemStacks.length); for (ItemStack item : itemStacks) { result.addAll(removeAmount(inventory, item, matcher, item.getAmount())); } return result; } /** * Remove specified items from the the inventory. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param inventory The inventory to remove items from. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(Inventory inventory, Collection<ItemStack> itemStacks) { ItemStackMatcher matcher = ItemStackMatcher.getTypeMetaDurability(); return remove(inventory, matcher, itemStacks); } /** * Remove specified items from the the inventory. * * <p>Removes the quantity of the stack, not all matching items.</p> * * @param inventory The inventory to remove items from. * @param matcher The matcher to use. * @param itemStacks The {@link org.bukkit.inventory.ItemStack}'s to remove. * * @return The removed items. */ public static List<ItemStack> remove(Inventory inventory, ItemStackMatcher matcher, Collection<ItemStack> itemStacks) { PreCon.notNull(inventory); PreCon.notNull(matcher); PreCon.notNull(itemStacks); List<ItemStack> result = new ArrayList<>(itemStacks.size()); for (ItemStack item : itemStacks) { result.addAll(removeAmount(inventory, item, matcher, item.getAmount())); } return result; } /** * Remove a specified quantity of {@link org.bukkit.inventory.ItemStack}'s from the specified inventory * that match the specified {@link org.bukkit.inventory.ItemStack} array. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param qty The quantity. */ public static List<ItemStack> removeAmount(Inventory inventory, ItemStack itemStack, int qty) { return removeAmount(inventory, itemStack, ItemStackMatcher.getTypeMetaDurability(), qty); } /** * Remove a specified quantity of {@link org.bukkit.inventory.ItemStack}'s from the * specified inventory that match the specified {@link org.bukkit.inventory.ItemStack} array. * * @param inventory The inventory to check. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. * @param qty The quantity. */ public static List<ItemStack> removeAmount(Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher, int qty) { PreCon.notNull(inventory); PreCon.notNull(itemStack); PreCon.notNull(matcher); PreCon.positiveNumber(qty); int size = inventory.getSize(); List<ItemStack> results = new ArrayList<ItemStack>(size); int qtyLeft = qty; for (int i=0; i < size ; i++) { if (qtyLeft <= 0) return results; ItemStack item = inventory.getItem(i); if (item == null || item.getType() == Material.AIR) continue; if (matcher.isMatch(itemStack, item)) { ItemStack clone = item.clone(); if (item.getAmount() > qtyLeft) { int newAmount = item.getAmount() - qtyLeft; item.setAmount(newAmount); clone.setAmount(qtyLeft); results.add(clone); inventory.setItem(i, item); break; } else { qtyLeft -= item.getAmount(); clone.setAmount(item.getAmount()); results.add(clone); inventory.setItem(i, ItemStackUtils.AIR); } } } if (qtyLeft > 0 && inventory instanceof PlayerInventory) { PlayerInventory playerInventory = (PlayerInventory)inventory; Set<MaterialProperty> properties = Materials.getProperties(itemStack.getType()); if (properties.contains(MaterialProperty.ARMOR)) { if (properties.contains(MaterialProperty.HELMET) && matcher.isMatch(playerInventory.getHelmet(), itemStack)) { results.add(playerInventory.getHelmet()); playerInventory.setHelmet(null); } else if (properties.contains(MaterialProperty.CHESTPLATE) && matcher.isMatch(playerInventory.getChestplate(), itemStack)) { results.add(playerInventory.getChestplate()); playerInventory.setChestplate(null); } else if (properties.contains(MaterialProperty.LEGGINGS) && matcher.isMatch(playerInventory.getLeggings(), itemStack)) { results.add(playerInventory.getLeggings()); playerInventory.setLeggings(null); } else if (properties.contains(MaterialProperty.BOOTS) && matcher.isMatch(playerInventory.getBoots(), itemStack)) { results.add(playerInventory.getBoots()); playerInventory.setLeggings(null); } } } return results; } /** * Remove a specified quantity of {@link org.bukkit.inventory.ItemStack}'s from the * specified {@link org.bukkit.inventory.ItemStack} array that match the specified * {@link org.bukkit.inventory.ItemStack}. * * @param contents The inventory contents. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param qty The quantity. */ public static List<ItemStack> removeAmount(ItemStack[] contents, ItemStack itemStack, int qty) { return removeAmount(contents, itemStack, ItemStackMatcher.getTypeMetaDurability(), qty); } /** * Remove a specified quantity of {@link org.bukkit.inventory.ItemStack}'s from the * specified {@link org.bukkit.inventory.ItemStack} array that match the specified * {@link org.bukkit.inventory.ItemStack}. * * @param contents The inventory contents. * @param itemStack The {@link org.bukkit.inventory.ItemStack} to check. * @param matcher The {@link ItemStackMatcher} to use. * @param qty The quantity. */ public static List<ItemStack> removeAmount(ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher, int qty) { PreCon.notNull(contents); PreCon.notNull(itemStack); PreCon.notNull(matcher); PreCon.positiveNumber(qty); List<ItemStack> results = new ArrayList<ItemStack>(contents.length); int qtyLeft = qty; for (int i=0; i < contents.length; i++) { if (qtyLeft <= 0) return results; ItemStack item = contents[i]; if (item == null || item.getType() == Material.AIR) continue; if (matcher.isMatch(itemStack, item)) { ItemStack clone = item.clone(); if (item.getAmount() > qtyLeft) { int newAmount = item.getAmount() - qtyLeft; item.setAmount(newAmount); clone.setAmount(qtyLeft); results.add(clone); contents[i] = item; return results; } else { qtyLeft -= item.getAmount(); clone.setAmount(item.getAmount()); results.add(clone); contents[i] = ItemStackUtils.AIR; } } } return results; } /** * Clear an inventory. If the inventory is a {@link org.bukkit.inventory.PlayerInventory}, * the armor contents are also cleared. * * @param inventory The inventory to clear. */ public static void clearAll(Inventory inventory) { PreCon.notNull(inventory); inventory.clear(); inventory.setContents(new ItemStack[inventory.getSize()]); // 36 if (inventory instanceof PlayerInventory) { PlayerInventory playerInventory = (PlayerInventory)inventory; playerInventory.setHelmet(null); playerInventory.setChestplate(null); playerInventory.setLeggings(null); playerInventory.setBoots(null); playerInventory.setItemInHand(null); } } /** * Clear an inventory. If the inventory is a {@link org.bukkit.inventory.PlayerInventory}, * the armor contents are also cleared. * * @param contents The inventory contents. */ public static void clearAll(ItemStack[] contents) { PreCon.notNull(contents); for (int i=0; i < contents.length;i++) { contents[i] = null; } } /** * Repair all repairable items in an inventory. If the inventory * is a {@link org.bukkit.inventory.PlayerInventory}, the armor contents are also * repaired. * * @param inventory The inventory with items to repair. */ public static void repairAll(Inventory inventory) { PreCon.notNull(inventory); ItemStack[] contents = inventory.getContents(); repairAll(contents); if (inventory instanceof PlayerInventory) { PlayerInventory playerInventory = (PlayerInventory)inventory; ItemStack[] armor = playerInventory.getArmorContents(); repairAll(armor); } } /** * Repair all repairable items in an {@link org.bukkit.inventory.ItemStack} array. * * @param contents The inventory contents. */ public static void repairAll(ItemStack[] contents) { PreCon.notNull(contents); for (ItemStack stack : contents) { if (stack == null || !Materials.isRepairable(stack.getType())) continue; stack.setDurability((short) -32768); } } /** * Determine if an inventory is empty. If the inventory is a * {@link org.bukkit.inventory.PlayerInventory}, the armor contents are included * in the check. * * @param inventory The inventory to check. */ public static boolean isEmpty(Inventory inventory) { PreCon.notNull(inventory); boolean isContentsEmpty = isEmpty(inventory.getContents()); if (inventory instanceof PlayerInventory) { PlayerInventory playerInventory = (PlayerInventory)inventory; return isContentsEmpty && isEmpty(playerInventory.getArmorContents()); } return isContentsEmpty; } /** * Determine if an {@link org.bukkit.inventory.ItemStack} array is empty. * * @param contents The inventory contents. */ public static boolean isEmpty(ItemStack[] contents) { PreCon.notNull(contents); for (ItemStack stack : contents) { if (stack == null || stack.getType() == Material.AIR) continue; return false; } return true; } private static int getMax(ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher, int totalRequired) { PreCon.notNull(contents); PreCon.notNull(itemStack); int totalSpace = 0; int maxStackSize = itemStack.getType().getMaxStackSize(); if (maxStackSize == 0) return 0; for (ItemStack slotStack : contents) { if (slotStack == null || slotStack.getType() == Material.AIR) { totalSpace += maxStackSize; } else if (matcher.isMatch(slotStack, itemStack)) { if (slotStack.getAmount() <= maxStackSize) totalSpace += (maxStackSize - slotStack.getAmount()); } if (totalRequired > 0 && totalSpace >= totalRequired) return totalRequired; } return totalSpace; } private static int count (ItemStack[] contents, ItemStack itemStack, ItemStackMatcher matcher, int qty) { int count = 0; for (ItemStack item : contents) { if (item == null || item.getType() == Material.AIR) continue; if (matcher.isMatch(itemStack, item)) count += item.getAmount(); if (qty >= 0 && count >= qty) return count; } return count; } private static int count (Inventory inventory, ItemStack itemStack, ItemStackMatcher matcher, int qty) { ItemStack[] contents = inventory.getContents(); int count = count(contents, itemStack, matcher, qty); if (inventory instanceof PlayerInventory) { PlayerInventory playerInventory = (PlayerInventory)inventory; Set<MaterialProperty> properties = Materials.getProperties(itemStack.getType()); if (properties.contains(MaterialProperty.ARMOR)) { if (properties.contains(MaterialProperty.HELMET) && matcher.isMatch(playerInventory.getHelmet(), itemStack)) { count++; } else if (properties.contains(MaterialProperty.CHESTPLATE) && matcher.isMatch(playerInventory.getChestplate(), itemStack)) { count++; } else if (properties.contains(MaterialProperty.LEGGINGS) && matcher.isMatch(playerInventory.getLeggings(), itemStack)) { count++; } else if (properties.contains(MaterialProperty.BOOTS) && matcher.isMatch(playerInventory.getBoots(), itemStack)) { count++; } } } return count; } }