/* * This file is part of Spoutcraft. * * Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org/> * Spoutcraft is licensed under the GNU Lesser General Public License. * * Spoutcraft is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Spoutcraft is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.spoutcraft.client.inventory; import java.util.HashMap; import net.minecraft.src.IInventory; import org.spoutcraft.api.inventory.Inventory; import org.spoutcraft.api.inventory.ItemStack; import org.spoutcraft.api.material.Material; public class CraftInventory implements Inventory { protected IInventory inventory; private static net.minecraft.src.ItemStack[] getContents(IInventory inventory) { net.minecraft.src.ItemStack[] contents = new net.minecraft.src.ItemStack[inventory.getSizeInventory()]; for (int i = 0; i < inventory.getSizeInventory(); i++) { contents[i] = inventory.getStackInSlot(i); } return contents; } public CraftInventory(IInventory inventory) { this.inventory = inventory; } public IInventory getInventory() { return inventory; } public int getSize() { return getInventory().getSizeInventory(); } public String getName() { return getInventory().getInvName(); } public ItemStack getItem(int index) { return new CraftItemStack(getInventory().getStackInSlot(index)); } public ItemStack[] getContents() { ItemStack[] items = new ItemStack[getSize()]; net.minecraft.src.ItemStack[] mcItems = getContents(getInventory()); for (int i = 0; i < mcItems.length; i++) { items[i] = mcItems[i] == null ? null : new CraftItemStack(mcItems[i]); } return items; } public void setContents(ItemStack[] items) { net.minecraft.src.ItemStack[] mcItems = getContents(getInventory()); if (mcItems.length != items.length) { throw new IllegalArgumentException("Invalid inventory size; expected " + mcItems.length); } for (int i = 0; i < items.length; i++) { ItemStack item = items[i]; if (item == null || item.getTypeId() <= 0) { getInventory().setInventorySlotContents(i, null); } else { getInventory().setInventorySlotContents(i, new net.minecraft.src.ItemStack(item.getTypeId(), item.getAmount(), item.getDurability())); } } } public void setItem(int index, ItemStack item) { getInventory().setInventorySlotContents(index, (item == null ? null : new net.minecraft.src.ItemStack(item.getTypeId(), item.getAmount(), item.getDurability()))); } public boolean contains(int materialId) { for (ItemStack item: getContents()) { if (item != null && item.getTypeId() == materialId) { return true; } } return false; } public boolean contains(Material material) { return contains(material.getRawId()); } 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) { int amt = 0; for (ItemStack item: getContents()) { if (item != null && item.getTypeId() == materialId) { amt += item.getAmount(); } } return amt >= amount; } public boolean contains(Material material, int amount) { return contains(material.getRawId(), amount); } public boolean contains(ItemStack item, int amount) { if (item == null) { return false; } int amt = 0; for (ItemStack i: getContents()) { if (item.equals(i)) { amt += item.getAmount(); } } return amt >= amount; } public HashMap<Integer, ItemStack> all(int materialId) { HashMap<Integer, ItemStack> slots = new HashMap<Integer, ItemStack>(); 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<Integer, ItemStack> all(Material material) { return all(material.getRawId()); } public HashMap<Integer, ItemStack> all(ItemStack item) { HashMap<Integer, ItemStack> slots = new HashMap<Integer, ItemStack>(); 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) { return first(material.getRawId()); } public int first(ItemStack item) { if (item == null) { return -1; } ItemStack[] inventory = getContents(); for (int i = 0; i < inventory.length; i++) { if (item.equals(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) { return firstPartial(material.getRawId()); } public int firstPartial(ItemStack item) { ItemStack[] inventory = getContents(); if (item == null) { return -1; } for (int i = 0; i < inventory.length; i++) { ItemStack cItem = inventory[i]; if (cItem != null && cItem.getTypeId() == item.getTypeId() && cItem.getAmount() < cItem.getMaxStackSize() && cItem.getDurability() == item.getDurability()) { return i; } } return -1; } public HashMap<Integer, ItemStack> addItem(ItemStack... items) { HashMap<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>(); /* 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()) { setItem(firstFree, new CraftItemStack(item.getTypeId(), getMaxItemStack(), item.getDurability())); 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); break; } // It fits partially partialItem.setAmount(maxAmount); item.setAmount(amount + partialAmount - maxAmount); } } } return leftover; } public HashMap<Integer, ItemStack> removeItem(ItemStack... items) { HashMap<Integer, ItemStack> leftover = new HashMap<Integer, ItemStack>(); // TODO Optimization for (int i = 0; i < items.length; i++) { ItemStack item = items[i]; int toDelete = item.getAmount(); while (true) { int first = first(item.getType()); // 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().getInventoryStackLimit(); } 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) { remove(material.getRawId()); } 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); } } }