2011-03-19 22:39:51 +00:00
|
|
|
package com.earth2me.essentials;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
2011-06-06 12:01:56 +00:00
|
|
|
import java.util.Map;
|
2011-05-22 17:29:59 +00:00
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.entity.Item;
|
2011-04-08 11:13:33 +00:00
|
|
|
import org.bukkit.inventory.Inventory;
|
2011-03-19 22:39:51 +00:00
|
|
|
import org.bukkit.inventory.ItemStack;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This class can be removed when
|
|
|
|
* https://github.com/Bukkit/CraftBukkit/pull/193
|
|
|
|
* is accepted to CraftBukkit
|
|
|
|
*/
|
|
|
|
|
2011-06-01 10:40:12 +00:00
|
|
|
public final class InventoryWorkaround
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-06-01 10:40:12 +00:00
|
|
|
private InventoryWorkaround()
|
|
|
|
{
|
|
|
|
}
|
2011-06-12 20:55:08 +00:00
|
|
|
|
2011-06-06 12:01:56 +00:00
|
|
|
public static int first(final Inventory inventory, final ItemStack item, final boolean forceDurability, final boolean forceAmount)
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
return next(inventory, item, 0, forceDurability, forceAmount);
|
2011-03-19 22:39:51 +00:00
|
|
|
}
|
|
|
|
|
2011-06-06 12:01:56 +00:00
|
|
|
public static int next(final Inventory cinventory, final ItemStack item, final int start, final boolean forceDurability, final boolean forceAmount)
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final ItemStack[] inventory = cinventory.getContents();
|
2011-05-22 17:29:59 +00:00
|
|
|
for (int i = start; i < inventory.length; i++)
|
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final ItemStack cItem = inventory[i];
|
2011-05-22 17:29:59 +00:00
|
|
|
if (cItem == null)
|
|
|
|
{
|
2011-04-08 11:45:14 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-11-27 05:00:58 +00:00
|
|
|
if (item.getTypeId() == cItem.getTypeId() && (!forceAmount || item.getAmount() == cItem.getAmount()) && (!forceDurability || cItem.getDurability() == item.getDurability()) && cItem.getEnchantments().equals(item.getEnchantments()))
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-06-12 20:57:43 +00:00
|
|
|
public static int firstPartial(final Inventory cinventory, final ItemStack item, final boolean forceDurability)
|
2011-12-04 21:45:47 +00:00
|
|
|
{
|
|
|
|
return firstPartial(cinventory, item, forceDurability, item.getType().getMaxStackSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int firstPartial(final Inventory cinventory, final ItemStack item, final boolean forceDurability, final int maxAmount)
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
|
|
|
if (item == null)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
final ItemStack[] inventory = cinventory.getContents();
|
|
|
|
for (int i = 0; i < inventory.length; i++)
|
|
|
|
{
|
|
|
|
final ItemStack cItem = inventory[i];
|
|
|
|
if (cItem == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2011-12-04 21:45:47 +00:00
|
|
|
if (item.getTypeId() == cItem.getTypeId() && cItem.getAmount() < maxAmount && (!forceDurability || cItem.getDurability() == item.getDurability()) && cItem.getEnchantments().equals(item.getEnchantments()))
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-10-09 20:25:15 +00:00
|
|
|
public static boolean addAllItems(final Inventory cinventory, final boolean forceDurability, final ItemStack... items)
|
|
|
|
{
|
|
|
|
final Inventory fake = new FakeInventory(cinventory.getContents());
|
|
|
|
if (addItem(fake, forceDurability, items).isEmpty())
|
|
|
|
{
|
|
|
|
addItem(cinventory, forceDurability, items);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-12 20:57:43 +00:00
|
|
|
public static Map<Integer, ItemStack> addItem(final Inventory cinventory, final boolean forceDurability, final ItemStack... items)
|
2011-11-27 09:59:28 +00:00
|
|
|
{
|
2011-11-28 18:55:51 +00:00
|
|
|
return addItem(cinventory, forceDurability, 0, items);
|
2011-11-27 09:59:28 +00:00
|
|
|
}
|
|
|
|
|
2011-11-28 18:55:51 +00:00
|
|
|
public static Map<Integer, ItemStack> addItem(final Inventory cinventory, final boolean forceDurability, final int oversizedStacks, final ItemStack... items)
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
|
|
|
final Map<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>();
|
|
|
|
|
|
|
|
/* TODO: some optimization
|
|
|
|
* - Create a 'firstPartial' with a 'fromIndex'
|
|
|
|
* - Record the lastPartial per Material
|
|
|
|
* - Cache firstEmpty result
|
|
|
|
*/
|
|
|
|
|
|
|
|
// combine items
|
|
|
|
|
|
|
|
ItemStack[] combined = new ItemStack[items.length];
|
|
|
|
for (int i = 0; i < items.length; i++)
|
|
|
|
{
|
2011-06-30 23:31:20 +00:00
|
|
|
if (items[i] == null || items[i].getAmount() < 1)
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (int j = 0; j < combined.length; j++)
|
|
|
|
{
|
|
|
|
if (combined[j] == null)
|
|
|
|
{
|
2011-11-27 05:10:11 +00:00
|
|
|
combined[j] = items[i].clone();
|
2011-06-12 20:55:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-11-27 05:00:58 +00:00
|
|
|
if (combined[j].getTypeId() == items[i].getTypeId() && (!forceDurability || combined[j].getDurability() == items[i].getDurability()) && combined[j].getEnchantments().equals(items[i].getEnchantments()))
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
|
|
|
combined[j].setAmount(combined[j].getAmount() + items[i].getAmount());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-18 02:59:47 +00:00
|
|
|
for (int i = 0; i < combined.length; i++)
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
2011-07-18 02:59:47 +00:00
|
|
|
final ItemStack item = combined[i];
|
2011-07-18 20:39:01 +00:00
|
|
|
if (item == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2011-10-09 20:25:15 +00:00
|
|
|
|
2011-06-12 20:55:08 +00:00
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
// Do we already have a stack of it?
|
2011-12-04 21:45:47 +00:00
|
|
|
final int maxAmount = oversizedStacks > item.getType().getMaxStackSize() ? oversizedStacks : item.getType().getMaxStackSize();
|
|
|
|
final int firstPartial = firstPartial(cinventory, item, forceDurability, maxAmount);
|
2011-06-12 20:55:08 +00:00
|
|
|
|
|
|
|
// Drat! no partial stack
|
|
|
|
if (firstPartial == -1)
|
|
|
|
{
|
|
|
|
// Find a free spot!
|
|
|
|
final int firstFree = cinventory.firstEmpty();
|
|
|
|
|
|
|
|
if (firstFree == -1)
|
|
|
|
{
|
|
|
|
// No space at all!
|
|
|
|
leftover.put(i, item);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// More than a single stack!
|
2011-11-28 18:55:51 +00:00
|
|
|
if (item.getAmount() > maxAmount)
|
2011-06-12 20:55:08 +00:00
|
|
|
{
|
2011-11-28 18:55:51 +00:00
|
|
|
final ItemStack stack = item.clone();
|
|
|
|
stack.setAmount(maxAmount);
|
2011-11-30 18:31:21 +00:00
|
|
|
cinventory.setItem(firstFree, stack);
|
2011-11-28 18:55:51 +00:00
|
|
|
item.setAmount(item.getAmount() - maxAmount);
|
2011-06-12 20:55:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Just store it
|
2011-11-30 18:31:21 +00:00
|
|
|
cinventory.setItem(firstFree, item);
|
2011-06-12 20:55:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// So, apparently it might only partially fit, well lets do just that
|
|
|
|
final ItemStack partialItem = cinventory.getItem(firstPartial);
|
|
|
|
|
|
|
|
final int amount = item.getAmount();
|
|
|
|
final int partialAmount = partialItem.getAmount();
|
2011-12-04 21:45:47 +00:00
|
|
|
|
2011-06-12 20:55:08 +00:00
|
|
|
// Check if it fully fits
|
|
|
|
if (amount + partialAmount <= maxAmount)
|
|
|
|
{
|
|
|
|
partialItem.setAmount(amount + partialAmount);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It fits partially
|
|
|
|
partialItem.setAmount(maxAmount);
|
|
|
|
item.setAmount(amount + partialAmount - maxAmount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return leftover;
|
|
|
|
}
|
|
|
|
|
2011-06-06 12:01:56 +00:00
|
|
|
public static Map<Integer, ItemStack> removeItem(final Inventory cinventory, final boolean forceDurability, final ItemStack... items)
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final Map<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>();
|
2011-03-19 22:39:51 +00:00
|
|
|
|
|
|
|
// TODO: optimization
|
|
|
|
|
2011-05-22 17:29:59 +00:00
|
|
|
for (int i = 0; i < items.length; i++)
|
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final ItemStack item = items[i];
|
2011-05-22 17:29:59 +00:00
|
|
|
if (item == null)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int toDelete = item.getAmount();
|
|
|
|
|
2011-05-22 17:29:59 +00:00
|
|
|
while (true)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
|
|
|
|
// Bail when done
|
2011-05-22 17:29:59 +00:00
|
|
|
if (toDelete <= 0)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get first Item, ignore the amount
|
2011-06-06 12:01:56 +00:00
|
|
|
final int first = first(cinventory, item, forceDurability, false);
|
2011-03-19 22:39:51 +00:00
|
|
|
|
|
|
|
// Drat! we don't have this type in the inventory
|
2011-05-22 17:29:59 +00:00
|
|
|
if (first == -1)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
item.setAmount(toDelete);
|
|
|
|
leftover.put(i, item);
|
|
|
|
break;
|
2011-05-22 17:29:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final ItemStack itemStack = cinventory.getItem(first);
|
|
|
|
final int amount = itemStack.getAmount();
|
2011-03-19 22:39:51 +00:00
|
|
|
|
2011-05-22 17:29:59 +00:00
|
|
|
if (amount <= toDelete)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
toDelete -= amount;
|
|
|
|
// clear the slot, all used up
|
2011-06-06 12:01:56 +00:00
|
|
|
cinventory.clear(first);
|
2011-05-22 17:29:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
// split the stack and store
|
|
|
|
itemStack.setAmount(amount - toDelete);
|
2011-11-30 18:31:21 +00:00
|
|
|
cinventory.setItem(first, itemStack);
|
2011-03-19 22:39:51 +00:00
|
|
|
toDelete = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return leftover;
|
|
|
|
}
|
|
|
|
|
2011-06-06 12:01:56 +00:00
|
|
|
public static boolean containsItem(final Inventory cinventory, final boolean forceDurability, final ItemStack... items)
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final Map<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>();
|
2011-03-19 22:39:51 +00:00
|
|
|
|
|
|
|
// TODO: optimization
|
|
|
|
|
|
|
|
// combine items
|
|
|
|
|
|
|
|
ItemStack[] combined = new ItemStack[items.length];
|
2011-05-22 17:29:59 +00:00
|
|
|
for (int i = 0; i < items.length; i++)
|
|
|
|
{
|
|
|
|
if (items[i] == null)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-05-22 17:29:59 +00:00
|
|
|
for (int j = 0; j < combined.length; j++)
|
|
|
|
{
|
|
|
|
if (combined[j] == null)
|
|
|
|
{
|
2011-11-27 05:10:11 +00:00
|
|
|
combined[j] = items[i].clone();
|
2011-03-19 22:39:51 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-11-27 05:00:58 +00:00
|
|
|
if (combined[j].getTypeId() == items[i].getTypeId() && (!forceDurability || combined[j].getDurability() == items[i].getDurability()) && combined[j].getEnchantments().equals(items[i].getEnchantments()))
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
combined[j].setAmount(combined[j].getAmount() + items[i].getAmount());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-22 17:29:59 +00:00
|
|
|
for (int i = 0; i < combined.length; i++)
|
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final ItemStack item = combined[i];
|
2011-05-22 17:29:59 +00:00
|
|
|
if (item == null)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int mustHave = item.getAmount();
|
|
|
|
int position = 0;
|
|
|
|
|
2011-05-22 17:29:59 +00:00
|
|
|
while (true)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
// Bail when done
|
2011-05-22 17:29:59 +00:00
|
|
|
if (mustHave <= 0)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-06-06 12:01:56 +00:00
|
|
|
final int slot = next(cinventory, item, position, forceDurability, false);
|
2011-03-19 22:39:51 +00:00
|
|
|
|
|
|
|
// Drat! we don't have this type in the inventory
|
2011-05-22 17:29:59 +00:00
|
|
|
if (slot == -1)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
leftover.put(i, item);
|
|
|
|
break;
|
2011-05-22 17:29:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final ItemStack itemStack = cinventory.getItem(slot);
|
|
|
|
final int amount = itemStack.getAmount();
|
2011-03-19 22:39:51 +00:00
|
|
|
|
2011-05-22 17:29:59 +00:00
|
|
|
if (amount <= mustHave)
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
mustHave -= amount;
|
2011-05-22 17:29:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-19 22:39:51 +00:00
|
|
|
mustHave = 0;
|
|
|
|
}
|
|
|
|
position = slot + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return leftover.isEmpty();
|
|
|
|
}
|
2011-05-22 17:29:59 +00:00
|
|
|
|
2011-06-06 12:01:56 +00:00
|
|
|
public static Item[] dropItem(final Location loc, final ItemStack itm)
|
2011-05-22 17:29:59 +00:00
|
|
|
{
|
2011-06-06 12:01:56 +00:00
|
|
|
final int maxStackSize = itm.getType().getMaxStackSize();
|
|
|
|
final int stacks = itm.getAmount() / maxStackSize;
|
|
|
|
final int leftover = itm.getAmount() % maxStackSize;
|
2011-11-27 05:00:58 +00:00
|
|
|
final Item[] itemStacks = new Item[stacks + (leftover > 0 ? 1 : 0)];
|
2011-06-12 20:55:08 +00:00
|
|
|
for (int i = 0; i < stacks; i++)
|
|
|
|
{
|
2011-11-27 05:10:11 +00:00
|
|
|
final ItemStack stack = itm.clone();
|
|
|
|
stack.setAmount(maxStackSize);
|
2011-11-27 05:00:58 +00:00
|
|
|
itemStacks[i] = loc.getWorld().dropItem(loc, stack);
|
2011-05-22 17:29:59 +00:00
|
|
|
}
|
2011-06-12 20:55:08 +00:00
|
|
|
if (leftover > 0)
|
|
|
|
{
|
2011-11-27 05:10:11 +00:00
|
|
|
final ItemStack stack = itm.clone();
|
|
|
|
stack.setAmount(leftover);
|
2011-11-27 05:00:58 +00:00
|
|
|
itemStacks[stacks] = loc.getWorld().dropItem(loc, stack);
|
2011-05-22 17:29:59 +00:00
|
|
|
}
|
|
|
|
return itemStacks;
|
|
|
|
}
|
2011-03-19 22:39:51 +00:00
|
|
|
}
|