All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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