diff --git a/codechicken/lib/inventory/InventoryCopy.java b/codechicken/lib/inventory/InventoryCopy.java new file mode 100644 index 0000000..c36ba0a --- /dev/null +++ b/codechicken/lib/inventory/InventoryCopy.java @@ -0,0 +1,123 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class InventoryCopy implements IInventory +{ + public boolean[] accessible; + public ItemStack[] items; + public IInventory inv; + + public InventoryCopy(IInventory inv) + { + items = new ItemStack[inv.getSizeInventory()]; + accessible = new boolean[inv.getSizeInventory()]; + this.inv = inv; + update(); + } + + public void update() + { + for(int i = 0; i < items.length; i++) + { + ItemStack stack = inv.getStackInSlot(i); + if(stack != null) + items[i] = stack.copy(); + } + } + + public InventoryCopy open(InventoryRange access) + { + int lslot = access.lastSlot(); + if(lslot > accessible.length) + { + boolean[] l_accessable = new boolean[lslot]; + ItemStack[] l_items = new ItemStack[lslot]; + System.arraycopy(accessible, 0, l_accessable, 0, accessible.length); + System.arraycopy(items, 0, l_items, 0, items.length); + accessible = l_accessable; + items = l_items; + } + + for(int slot : access.slots) + accessible[slot] = true; + return this; + } + + @Override + public int getSizeInventory() + { + return items.length; + } + + @Override + public ItemStack getStackInSlot(int slot) + { + return items[slot]; + } + + public ItemStack decrStackSize(int slot, int amount) + { + return InventoryUtils.decrStackSize(this, slot, amount); + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return InventoryUtils.getStackInSlotOnClosing(this, slot); + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) + { + items[slot] = stack; + onInventoryChanged(); + } + + @Override + public String getInvName() + { + return "copy"; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) + { + return true; + } + + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + + @Override + public void onInventoryChanged() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return inv.isItemValidForSlot(i, itemstack); + } + + @Override + public boolean isInvNameLocalized() + { + return true; + } +} diff --git a/codechicken/lib/inventory/InventoryNBT.java b/codechicken/lib/inventory/InventoryNBT.java new file mode 100644 index 0000000..e3da78a --- /dev/null +++ b/codechicken/lib/inventory/InventoryNBT.java @@ -0,0 +1,107 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +public class InventoryNBT implements IInventory +{ + protected ItemStack[] items; + protected NBTTagCompound tag; + + public InventoryNBT(int size, NBTTagCompound tag) + { + this.tag = tag; + items = new ItemStack[size]; + readNBT(); + } + + private void writeNBT() + { + tag.setTag("items", InventoryUtils.writeItemStacksToTag(items, getInventoryStackLimit())); + } + + private void readNBT() + { + if(tag.hasKey("items")) + InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items")); + } + + @Override + public int getSizeInventory() + { + return items.length; + } + + @Override + public ItemStack getStackInSlot(int slot) + { + return items[slot]; + } + + @Override + public ItemStack decrStackSize(int slot, int amount) + { + return InventoryUtils.decrStackSize(this, slot, amount); + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return InventoryUtils.getStackInSlotOnClosing(this, slot); + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) + { + items[slot] = stack; + onInventoryChanged(); + } + + @Override + public String getInvName() + { + return "NBT"; + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public void onInventoryChanged() + { + writeNBT(); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return true; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + + @Override + public boolean isInvNameLocalized() + { + return true; + } +} diff --git a/codechicken/lib/inventory/InventoryRange.java b/codechicken/lib/inventory/InventoryRange.java new file mode 100644 index 0000000..6efc0bd --- /dev/null +++ b/codechicken/lib/inventory/InventoryRange.java @@ -0,0 +1,71 @@ +package codechicken.lib.inventory; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; + +public class InventoryRange +{ + public IInventory inv; + public int side; + public ISidedInventory sidedInv; + public int[] slots; + + public InventoryRange(IInventory inv, int side) + { + this.inv = inv; + this.side = side; + if(inv instanceof ISidedInventory) + { + sidedInv = (ISidedInventory)inv; + slots = sidedInv.getAccessibleSlotsFromSide(side); + } + else + { + slots = new int[inv.getSizeInventory()]; + for(int i = 0; i < slots.length; i++) + slots[i] = i; + } + } + + public InventoryRange(IInventory inv) + { + this(inv, 0); + } + + public InventoryRange(IInventory inv, int fslot, int lslot) + { + this.inv = inv; + slots = new int[lslot-fslot]; + for(int i = 0; i < slots.length; i++) + slots[i] = fslot+i; + } + + public InventoryRange(IInventory inv, InventoryRange access) + { + this.inv = inv; + this.slots = access.slots; + this.side = access.side; + if(inv instanceof ISidedInventory) + sidedInv = (ISidedInventory) inv; + } + + public boolean canInsertItem(int slot, ItemStack item) + { + return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canInsertItem(slot, item, side); + } + + public boolean canExtractItem(int slot, ItemStack item) + { + return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canExtractItem(slot, item, side); + } + + public int lastSlot() + { + int last = 0; + for(int slot : slots) + if(slot > last) + last = slot; + return last; + } +} diff --git a/codechicken/lib/inventory/InventorySimple.java b/codechicken/lib/inventory/InventorySimple.java new file mode 100644 index 0000000..90a24a1 --- /dev/null +++ b/codechicken/lib/inventory/InventorySimple.java @@ -0,0 +1,130 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class InventorySimple implements IInventory +{ + public ItemStack[] items; + public int limit; + public String name; + + public InventorySimple(ItemStack[] items, int limit, String name) + { + this.items = items; + this.limit = limit; + this.name = name; + } + + public InventorySimple(ItemStack[] items, String name) + { + this(items, 64, name); + } + + public InventorySimple(ItemStack[] items, int limit) + { + this(items, limit, "inv"); + } + + public InventorySimple(ItemStack[] items) + { + this(items, 64, "inv"); + } + + public InventorySimple(int size, int limit, String name) + { + this(new ItemStack[size], limit, name); + } + + public InventorySimple(int size, int limit) + { + this(size, limit, "inv"); + } + + public InventorySimple(int size, String name) + { + this(size, 64, name); + } + + public InventorySimple(int size) + { + this(size, 64, "inv"); + } + + @Override + public int getSizeInventory() + { + return items.length; + } + + @Override + public ItemStack getStackInSlot(int slot) + { + return items[slot]; + } + + @Override + public ItemStack decrStackSize(int slot, int amount) + { + return InventoryUtils.decrStackSize(this, slot, amount); + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return InventoryUtils.getStackInSlotOnClosing(this, slot); + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) + { + items[slot] = stack; + onInventoryChanged(); + } + + @Override + public String getInvName() + { + return name; + } + + @Override + public int getInventoryStackLimit() + { + return limit; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return true; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + + @Override + public boolean isInvNameLocalized() + { + return true; + } + + @Override + public void onInventoryChanged() + { + } +} diff --git a/codechicken/lib/inventory/InventoryUtils.java b/codechicken/lib/inventory/InventoryUtils.java new file mode 100644 index 0000000..64bb560 --- /dev/null +++ b/codechicken/lib/inventory/InventoryUtils.java @@ -0,0 +1,295 @@ +package codechicken.lib.inventory; + +import com.google.common.base.Objects; + +import codechicken.lib.vec.Vector3; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryLargeChest; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagShort; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; + +public class InventoryUtils +{ + public static ItemStack decrStackSize(IInventory inv, int slot, int size) + { + ItemStack item = inv.getStackInSlot(slot); + + if(item != null) + { + if(item.stackSize <= size) + { + ItemStack itemstack = item; + inv.setInventorySlotContents(slot, null); + inv.onInventoryChanged(); + return itemstack; + } + ItemStack itemstack1 = item.splitStack(size); + if(item.stackSize == 0) + { + inv.setInventorySlotContents(slot, null); + } + inv.onInventoryChanged(); + return itemstack1; + } + return null; + } + + public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) + { + ItemStack stack = inv.getStackInSlot(slot); + inv.setInventorySlotContents(slot, null); + return stack; + } + + /** + * + * @param base + * @param addition + * @return The quantity of items from addition that can be added to base + */ + public static int incrStackSize(ItemStack base, ItemStack addition) + { + if (canStack(base, addition)) + return incrStackSize(base, addition.stackSize); + + return 0; + } + + /** + * + * @param base + * @param addition + * @return The quantity of items from addition that can be added to base + */ + public static int incrStackSize(ItemStack base, int addition) + { + int totalSize = base.stackSize + addition; + + if (totalSize <= base.getMaxStackSize()) + return addition; + else if (base.stackSize < base.getMaxStackSize()) + return base.getMaxStackSize() - base.stackSize; + + return 0; + } + + public static NBTTagList writeItemStacksToTag(ItemStack[] items) + { + return writeItemStacksToTag(items, 64); + } + + public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) + { + NBTTagList tagList = new NBTTagList(); + for(int i = 0; i < items.length; i++) + { + if (items[i] != null) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setShort("Slot", (short) i); + items[i].writeToNBT(tag); + + if(maxQuantity > Short.MAX_VALUE) + tag.setInteger("Quantity", items[i].stackSize); + else if(maxQuantity > Byte.MAX_VALUE) + tag.setShort("Quantity", (short) items[i].stackSize); + + tagList.appendTag(tag); + } + } + return tagList; + } + + public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) + { + for(int i = 0; i < tagList.tagCount(); i++) + { + NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i); + int b = tag.getShort("Slot"); + items[b] = ItemStack.loadItemStackFromNBT(tag); + if(tag.hasKey("Quantity")) + { + NBTBase qtag = tag.getTag("Quantity"); + if(qtag instanceof NBTTagInt) + items[b].stackSize = ((NBTTagInt)qtag).data; + else if(qtag instanceof NBTTagShort) + items[b].stackSize = ((NBTTagShort)qtag).data; + } + } + } + + public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) + { + EntityItem item = new EntityItem(world, dropLocation.x, dropLocation.y, dropLocation.z, stack); + item.motionX = world.rand.nextGaussian() * 0.05; + item.motionY = world.rand.nextGaussian() * 0.05 + 0.2F; + item.motionZ = world.rand.nextGaussian() * 0.05; + world.spawnEntityInWorld(item); + } + + public static ItemStack copyStack(ItemStack stack, int quantity) + { + if(stack == null) + return null; + + stack = stack.copy(); + stack.stackSize = quantity; + return stack; + } + + public static int getInsertableQuantity(InventoryRange inv, ItemStack stack) + { + int quantity = 0; + stack = copyStack(stack, Integer.MAX_VALUE); + for(int slot : inv.slots) + quantity+=fitStackInSlot(inv, slot, stack); + + return quantity; + } + + public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) + { + ItemStack base = inv.inv.getStackInSlot(slot); + if(!canStack(base, stack) || !inv.canInsertItem(slot, stack)) + return 0; + + int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit()-base.stackSize) : inv.inv.getInventoryStackLimit(); + return Math.min(fit, stack.stackSize); + } + + public static boolean mergeItemStack(InventoryRange inv, ItemStack stack, boolean doMerge) + { + if(doMerge && !mergeItemStack(inv, stack, false)) + return false; + + stack = stack.copy(); + for(int pass = 0; pass < 2; pass++) + { + for(int slot : inv.slots) + { + ItemStack base = inv.inv.getStackInSlot(slot); + int fit = fitStackInSlot(inv, slot, stack); + if(fit == 0) + continue; + + if(base != null) + { + stack.stackSize-=fit; + if(doMerge) + { + base.stackSize+=fit; + inv.inv.setInventorySlotContents(slot, base); + } + } + else if(pass == 1) + { + if(doMerge) + inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); + stack.stackSize-=fit; + } + if(stack.stackSize == 0) + return true; + } + } + return false; + } + + public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) + { + if(stack1 == null || stack2 == null) + return stack1 == stack2; + return stack1.itemID == stack2.itemID + && stack1.getItemDamage() == stack2.getItemDamage() + && stack1.stackSize == stack2.stackSize + && Objects.equal(stack1.getTagCompound(), stack2.getTagCompound()); + } + + public static IInventory getInventory(World world, int x, int y, int z) + { + TileEntity tile = world.getBlockTileEntity(x, y, z); + if(!(tile instanceof IInventory)) + return null; + + if(tile instanceof TileEntityChest) + return getChest((TileEntityChest) tile); + return (IInventory)tile; + + } + + public static final ForgeDirection[] chestSides = new ForgeDirection[]{ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; + public static IInventory getChest(TileEntityChest chest) + { + for(ForgeDirection fside : chestSides) + { + if(chest.worldObj.getBlockId(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ) == chest.getBlockType().blockID) + return new InventoryLargeChest("container.chestDouble", + (TileEntityChest)chest.worldObj.getBlockTileEntity(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ), chest); + } + return chest; + } + + public static boolean canStack(ItemStack stack1, ItemStack stack2) + { + return stack1 == null || stack2 == null || + (stack1.itemID == stack2.itemID && + (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && + ItemStack.areItemStackTagsEqual(stack2, stack1)) && + stack1.isStackable(); + } + + public static void consumeItem(IInventory inv, int slot) + { + ItemStack stack = inv.getStackInSlot(slot); + Item item = stack.getItem(); + if(item.hasContainerItem()) + { + ItemStack container = item.getContainerItemStack(stack); + inv.setInventorySlotContents(slot, container); + } + else + { + inv.decrStackSize(slot, 1); + } + } + + public static int stackSize(IInventory inv, int slot) + { + ItemStack stack = inv.getStackInSlot(slot); + return stack == null ? 0 : stack.stackSize; + } + + public static ItemStack getRemovableStack(InventoryRange inv, int slot) + { + ItemStack stack = inv.inv.getStackInSlot(slot); + if(stack == null || !inv.canExtractItem(slot, stack)) + return null; + + return stack; + } + + public static void dropOnClose(EntityPlayer player, IInventory inv) + { + for (int i = 0; i < inv.getSizeInventory(); i++) + { + ItemStack stack = inv.getStackInSlotOnClosing(i); + if (stack != null) + player.dropPlayerItem(stack); + } + } + + public static int actualDamage(ItemStack stack) + { + return Item.diamond.getDamage(stack); + } +}