org.bukkit.craftbukkit.inventory.CraftInventory Maven / Gradle / Ivy
package org.bukkit.craftbukkit.inventory;
import net.minecraft.server.*;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
public class CraftInventory implements Inventory {
protected final IInventory inventory;
public CraftInventory(IInventory inventory) {
this.inventory = inventory;
}
public IInventory getInventory() {
return inventory;
}
public int getSize() {
return getInventory().getSize();
}
public String getName() {
return getInventory().getName();
}
public ItemStack getItem(int index) {
net.minecraft.server.ItemStack item = getInventory().getItem(index);
return item == null ? null : CraftItemStack.asCraftMirror(item);
}
public ItemStack[] getContents() {
ItemStack[] items = new ItemStack[getSize()];
net.minecraft.server.ItemStack[] mcItems = getInventory().getContents();
int size = Math.min(items.length, mcItems.length);
for (int i = 0; i < size; i++) {
items[i] = mcItems[i] == null ? null : CraftItemStack.asCraftMirror(mcItems[i]);
}
return items;
}
public void setContents(ItemStack[] items) {
if (getInventory().getContents().length < items.length) {
throw new IllegalArgumentException("Invalid inventory size; expected " + getInventory().getContents().length + " or less");
}
net.minecraft.server.ItemStack[] mcItems = getInventory().getContents();
for (int i = 0; i < mcItems.length; i++) {
if (i >= items.length) {
mcItems[i] = null;
} else {
mcItems[i] = CraftItemStack.asNMSCopy(items[i]);
}
}
}
public void setItem(int index, ItemStack item) {
getInventory().setItem(index, ((item == null || item.getTypeId() == 0) ? null : CraftItemStack.asNMSCopy(item)));
}
public boolean contains(int materialId) {
for (ItemStack item : getContents()) {
if (item != null && item.getTypeId() == materialId) {
return true;
}
}
return false;
}
public boolean contains(Material material) {
Validate.notNull(material, "Material cannot be null");
return contains(material.getId());
}
public boolean contains(ItemStack item) {
if (item == null) {
return false;
}
for (ItemStack i : getContents()) {
if (item.equals(i)) {
return true;
}
}
return false;
}
public boolean contains(int materialId, int amount) {
if (amount <= 0) {
return true;
}
for (ItemStack item : getContents()) {
if (item != null && item.getTypeId() == materialId) {
if ((amount -= item.getAmount()) <= 0) {
return true;
}
}
}
return false;
}
public boolean contains(Material material, int amount) {
Validate.notNull(material, "Material cannot be null");
return contains(material.getId(), amount);
}
public boolean contains(ItemStack item, int amount) {
if (item == null) {
return false;
}
if (amount <= 0) {
return true;
}
for (ItemStack i : getContents()) {
if (item.equals(i) && --amount <= 0) {
return true;
}
}
return false;
}
public boolean containsAtLeast(ItemStack item, int amount) {
if (item == null) {
return false;
}
if (amount <= 0) {
return true;
}
for (ItemStack i : getContents()) {
if (item.isSimilar(i) && (amount -= i.getAmount()) <= 0) {
return true;
}
}
return false;
}
public HashMap all(int materialId) {
HashMap slots = new HashMap<>();
ItemStack[] inventory = getContents();
for (int i = 0; i < inventory.length; i++) {
ItemStack item = inventory[i];
if (item != null && item.getTypeId() == materialId) {
slots.put(i, item);
}
}
return slots;
}
public HashMap all(Material material) {
Validate.notNull(material, "Material cannot be null");
return all(material.getId());
}
public HashMap all(ItemStack item) {
HashMap slots = new HashMap();
if (item != null) {
ItemStack[] inventory = getContents();
for (int i = 0; i < inventory.length; i++) {
if (item.equals(inventory[i])) {
slots.put(i, inventory[i]);
}
}
}
return slots;
}
public int first(int materialId) {
ItemStack[] inventory = getContents();
for (int i = 0; i < inventory.length; i++) {
ItemStack item = inventory[i];
if (item != null && item.getTypeId() == materialId) {
return i;
}
}
return -1;
}
public int first(Material material) {
Validate.notNull(material, "Material cannot be null");
return first(material.getId());
}
public int first(ItemStack item) {
return first(item, true);
}
private int first(ItemStack item, boolean withAmount) {
if (item == null) {
return -1;
}
ItemStack[] inventory = getContents();
for (int i = 0; i < inventory.length; i++) {
if (inventory[i] == null) continue;
if (withAmount ? item.equals(inventory[i]) : item.isSimilar(inventory[i])) {
return i;
}
}
return -1;
}
public int firstEmpty() {
ItemStack[] inventory = getContents();
for (int i = 0; i < inventory.length; i++) {
if (inventory[i] == null) {
return i;
}
}
return -1;
}
public int firstPartial(int materialId) {
ItemStack[] inventory = getContents();
for (int i = 0; i < inventory.length; i++) {
ItemStack item = inventory[i];
if (item != null && item.getTypeId() == materialId && item.getAmount() < item.getMaxStackSize()) {
return i;
}
}
return -1;
}
public int firstPartial(Material material) {
Validate.notNull(material, "Material cannot be null");
return firstPartial(material.getId());
}
private int firstPartial(ItemStack item) {
ItemStack[] inventory = getContents();
ItemStack filteredItem = CraftItemStack.asCraftCopy(item);
if (item == null) {
return -1;
}
for (int i = 0; i < inventory.length; i++) {
ItemStack cItem = inventory[i];
if (cItem != null && cItem.getAmount() < cItem.getMaxStackSize() && cItem.isSimilar(filteredItem)) {
return i;
}
}
return -1;
}
public HashMap addItem(ItemStack... items) {
Validate.noNullElements(items, "Item cannot be null");
HashMap leftover = new HashMap<>();
/* TODO: some optimization
* - Create a 'firstPartial' with a 'fromIndex'
* - Record the lastPartial per Material
* - Cache firstEmpty result
*/
for (int i = 0; i < items.length; i++) {
ItemStack item = items[i];
while (true) {
// Do we already have a stack of it?
int firstPartial = firstPartial(item);
// Drat! no partial stack
if (firstPartial == -1) {
// Find a free spot!
int firstFree = firstEmpty();
if (firstFree == -1) {
// No space at all!
leftover.put(i, item);
break;
} else {
// More than a single stack!
if (item.getAmount() > getMaxItemStack()) {
CraftItemStack stack = CraftItemStack.asCraftCopy(item);
stack.setAmount(getMaxItemStack());
setItem(firstFree, stack);
item.setAmount(item.getAmount() - getMaxItemStack());
} else {
// Just store it
setItem(firstFree, item);
break;
}
}
} else {
// So, apparently it might only partially fit, well lets do just that
ItemStack partialItem = getItem(firstPartial);
int amount = item.getAmount();
int partialAmount = partialItem.getAmount();
int maxAmount = partialItem.getMaxStackSize();
// Check if it fully fits
if (amount + partialAmount <= maxAmount) {
partialItem.setAmount(amount + partialAmount);
// To make sure the packet is sent to the client
setItem(firstPartial, partialItem);
break;
}
// It fits partially
partialItem.setAmount(maxAmount);
// To make sure the packet is sent to the client
setItem(firstPartial, partialItem);
item.setAmount(amount + partialAmount - maxAmount);
}
}
}
return leftover;
}
public HashMap removeItem(ItemStack... items) {
Validate.notNull(items, "Items cannot be null");
HashMap leftover = new HashMap<>();
// TODO: optimization
for (int i = 0; i < items.length; i++) {
ItemStack item = items[i];
int toDelete = item.getAmount();
while (true) {
int first = first(item, false);
// Drat! we don't have this type in the inventory
if (first == -1) {
item.setAmount(toDelete);
leftover.put(i, item);
break;
} else {
ItemStack itemStack = getItem(first);
int amount = itemStack.getAmount();
if (amount <= toDelete) {
toDelete -= amount;
// clear the slot, all used up
clear(first);
} else {
// split the stack and store
itemStack.setAmount(amount - toDelete);
setItem(first, itemStack);
toDelete = 0;
}
}
// Bail when done
if (toDelete <= 0) {
break;
}
}
}
return leftover;
}
private int getMaxItemStack() {
return getInventory().getMaxStackSize();
}
public void remove(int materialId) {
ItemStack[] items = getContents();
for (int i = 0; i < items.length; i++) {
if (items[i] != null && items[i].getTypeId() == materialId) {
clear(i);
}
}
}
public void remove(Material material) {
Validate.notNull(material, "Material cannot be null");
remove(material.getId());
}
public void remove(ItemStack item) {
ItemStack[] items = getContents();
for (int i = 0; i < items.length; i++) {
if (items[i] != null && items[i].equals(item)) {
clear(i);
}
}
}
public void clear(int index) {
setItem(index, null);
}
public void clear() {
for (int i = 0; i < getSize(); i++) {
clear(i);
}
}
public ListIterator iterator() {
return new InventoryIterator(this);
}
public ListIterator iterator(int index) {
if (index < 0) {
index += getSize() + 1; // ie, with -1, previous() will return the last element
}
return new InventoryIterator(this, index);
}
public List getViewers() {
return this.inventory.getViewers();
}
public String getTitle() {
return inventory.getName();
}
public InventoryType getType() {
// Thanks to Droppers extending Dispensers, order is important.
if (inventory instanceof InventoryCrafting) {
return inventory.getSize() >= 9 ? InventoryType.WORKBENCH : InventoryType.CRAFTING;
} else if (inventory instanceof PlayerInventory) {
return InventoryType.PLAYER;
} else if (inventory instanceof TileEntityDropper) {
return InventoryType.DROPPER;
} else if (inventory instanceof TileEntityDispenser) {
return InventoryType.DISPENSER;
} else if (inventory instanceof TileEntityFurnace) {
return InventoryType.FURNACE;
} else if (this instanceof CraftInventoryEnchanting) {
return InventoryType.ENCHANTING;
} else if (inventory instanceof TileEntityBrewingStand) {
return InventoryType.BREWING;
} else if (inventory instanceof CraftInventoryCustom.MinecraftInventory) {
return ((CraftInventoryCustom.MinecraftInventory) inventory).getType();
} else if (inventory instanceof InventoryEnderChest) {
return InventoryType.ENDER_CHEST;
} else if (inventory instanceof InventoryMerchant) {
return InventoryType.MERCHANT;
} else if (inventory instanceof TileEntityBeacon) {
return InventoryType.BEACON;
} else if (this instanceof CraftInventoryAnvil) {
return InventoryType.ANVIL;
} else if (inventory instanceof IHopper) {
return InventoryType.HOPPER;
} else {
return InventoryType.CHEST;
}
}
public InventoryHolder getHolder() {
return inventory.getOwner();
}
@Override
public void setHolder(InventoryHolder holder) {
inventory.setOwner(holder);
}
public int getMaxStackSize() {
return inventory.getMaxStackSize();
}
public void setMaxStackSize(int size) {
inventory.setMaxStackSize(size);
}
@Override
public int hashCode() {
return inventory.hashCode();
}
@Override
public boolean equals(final Object obj) {
return obj instanceof CraftInventory && ((CraftInventory) obj).inventory.equals(this.inventory);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy