package openmods.utils;
import com.google.common.base.Preconditions;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.inventory.InventoryLargeChest;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class InventoryUtils {
public static boolean areItemAndTagEqual(final ItemStack stackA, ItemStack stackB) {
return stackA.isItemEqual(stackB) && ItemStack.areItemStackTagsEqual(stackA, stackB);
}
public static boolean areMergeCandidates(ItemStack source, ItemStack target) {
return areItemAndTagEqual(source, target) && target.stackSize < target.getMaxStackSize();
}
public static ItemStack copyAndChange(ItemStack stack, int newSize) {
ItemStack copy = stack.copy();
copy.stackSize = newSize;
return copy;
}
public static void removeFromSlot(IInventory inventory, int slot, int amount) {
ItemStack sourceStack = inventory.getStackInSlot(slot);
sourceStack.stackSize -= amount;
if (sourceStack.stackSize == 0) {
inventory.setInventorySlotContents(slot, null);
} else {
// Paranoia? Always!
inventory.setInventorySlotContents(slot, sourceStack);
}
}
private static IInventory doubleChestFix(TileEntity te) {
final World world = te.getWorldObj();
final int x = te.xCoord;
final int y = te.yCoord;
final int z = te.zCoord;
final Block block = te.getBlockType();
if (world.getBlock(x - 1, y, z) == block) return new InventoryLargeChest("Large chest", (IInventory)world.getTileEntity(x - 1, y, z), (IInventory)te);
if (world.getBlock(x + 1, y, z) == block) return new InventoryLargeChest("Large chest", (IInventory)te, (IInventory)world.getTileEntity(x + 1, y, z));
if (world.getBlock(x, y, z - 1) == block) return new InventoryLargeChest("Large chest", (IInventory)world.getTileEntity(x, y, z - 1), (IInventory)te);
if (world.getBlock(x, y, z + 1) == block) return new InventoryLargeChest("Large chest", (IInventory)te, (IInventory)world.getTileEntity(x, y, z + 1));
return (te instanceof IInventory)? (IInventory)te : null;
}
public static IInventory getInventory(World world, int x, int y, int z) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityChest) return doubleChestFix(tileEntity);
if (tileEntity instanceof IInventory) return (IInventory)tileEntity;
return null;
}
public static IInventory getInventory(World world, int x, int y, int z, ForgeDirection direction) {
if (direction != null) {
x += direction.offsetX;
y += direction.offsetY;
z += direction.offsetZ;
}
return getInventory(world, x, y, z);
}
public static IInventory getInventory(IInventory inventory) {
if (inventory instanceof TileEntityChest) return doubleChestFix((TileEntity)inventory);
return inventory;
}
public static List<ItemStack> getInventoryContents(IInventory inventory) {
List<ItemStack> result = Lists.newArrayList();
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack slot = inventory.getStackInSlot(i);
if (slot != null) result.add(slot);
}
return result;
}
/***
* Get the first slot containing an item type matching the supplied type.
*
* @param inventory
* @param stack
* @return Returns -1 if none found
*/
public static int getFirstSlotWithStack(IInventory inventory, ItemStack stack) {
inventory = getInventory(inventory);
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stackInSlot = inventory.getStackInSlot(i);
if (stackInSlot != null && stackInSlot.isItemEqual(stack)) { return i; }
}
return -1;
}
/***
* Get the indexes of all slots containing a stack of the supplied item
* type.
*
* @param inventory
* @param stack
* @return Returns a set of the slot indexes
*/
public static Set<Integer> getAllSlotsWithStack(IInventory inventory, ItemStack stack) {
inventory = getInventory(inventory);
Set<Integer> slots = Sets.newHashSet();
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stackInSlot = inventory.getStackInSlot(i);
if (stackInSlot != null && stackInSlot.isItemEqual(stack)) slots.add(i);
}
return slots;
}
public static int getFirstNonEmptySlot(IInventory inventory) {
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stack = inventory.getStackInSlot(i);
if (stack != null) { return i; }
}
return -1;
}
public static Set<Integer> getAllSlots(IInventory inventory) {
inventory = getInventory(inventory);
Set<Integer> slots = Sets.newHashSet();
for (int i = 0; i < inventory.getSizeInventory(); i++)
slots.add(i);
return slots;
}
public static Map<Integer, ItemStack> getAllItems(IInventory inventory) {
Map<Integer, ItemStack> result = Maps.newHashMap();
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stack = inventory.getStackInSlot(i);
if (stack != null) result.put(i, stack);
}
return result;
}
public static boolean inventoryIsEmpty(IInventory inventory) {
for (int i = 0, l = inventory.getSizeInventory(); i < l; i++)
if (inventory.getStackInSlot(i) != null) return false;
return true;
}
public static boolean tryMergeStacks(ItemStack stackToMerge, ItemStack stackInSlot) {
if (stackInSlot == null || !stackInSlot.isItemEqual(stackToMerge) || !ItemStack.areItemStackTagsEqual(stackToMerge, stackInSlot)) return false;
int newStackSize = stackInSlot.stackSize + stackToMerge.stackSize;
final int maxStackSize = stackToMerge.getMaxStackSize();
if (newStackSize <= maxStackSize) {
stackToMerge.stackSize = 0;
stackInSlot.stackSize = newStackSize;
return true;
} else if (stackInSlot.stackSize < maxStackSize) {
stackToMerge.stackSize -= maxStackSize - stackInSlot.stackSize;
stackInSlot.stackSize = maxStackSize;
return true;
}
return false;
}
public static ItemStack returnItem(ItemStack stack) {
return (stack == null || stack.stackSize <= 0)? null : stack.copy();
}
public static void swapStacks(IInventory inventory, int slot1, int slot2) {
swapStacks(inventory, slot1, slot2, true, true);
}
public static void swapStacks(IInventory inventory, int slot1, int slot2, boolean copy, boolean validate) {
Preconditions.checkElementIndex(slot1, inventory.getSizeInventory(), "input slot id");
Preconditions.checkElementIndex(slot2, inventory.getSizeInventory(), "output slot id");
ItemStack stack1 = inventory.getStackInSlot(slot1);
ItemStack stack2 = inventory.getStackInSlot(slot2);
if (validate) {
isItemValid(inventory, slot2, stack1);
isItemValid(inventory, slot1, stack2);
}
if (copy) {
if (stack1 != null) stack1 = stack1.copy();
if (stack2 != null) stack2 = stack2.copy();
}
inventory.setInventorySlotContents(slot1, stack2);
inventory.setInventorySlotContents(slot2, stack1);
}
public static void swapStacks(ISidedInventory inventory, int slot1, ForgeDirection side1, int slot2, ForgeDirection side2) {
swapStacks(inventory, slot1, side1, slot2, side2, true, true);
}
public static void swapStacks(ISidedInventory inventory, int slot1, ForgeDirection side1, int slot2, ForgeDirection side2, boolean copy, boolean validate) {
Preconditions.checkElementIndex(slot1, inventory.getSizeInventory(), "input slot id");
Preconditions.checkElementIndex(slot2, inventory.getSizeInventory(), "output slot id");
ItemStack stack1 = inventory.getStackInSlot(slot1);
ItemStack stack2 = inventory.getStackInSlot(slot2);
if (validate) {
isItemValid(inventory, slot2, stack1);
isItemValid(inventory, slot1, stack2);
canExtract(inventory, slot1, side1, stack1);
canInsert(inventory, slot2, side2, stack1);
canExtract(inventory, slot2, side2, stack2);
canInsert(inventory, slot1, side1, stack2);
}
if (copy) {
if (stack1 != null) stack1 = stack1.copy();
if (stack2 != null) stack2 = stack2.copy();
}
inventory.setInventorySlotContents(slot1, stack2);
inventory.setInventorySlotContents(slot2, stack1);
}
protected static void isItemValid(IInventory inventory, int slot, ItemStack stack) {
Preconditions.checkArgument(inventory.isItemValidForSlot(slot, stack), "Slot %s cannot accept item", slot);
}
protected static void canInsert(ISidedInventory inventory, int slot, ForgeDirection side, ItemStack stack) {
Preconditions.checkArgument(inventory.canInsertItem(slot, stack, side.ordinal()),
"Item cannot be inserted into slot %s on side %s", slot, side);
}
protected static void canExtract(ISidedInventory inventory, int slot, ForgeDirection side, ItemStack stack) {
Preconditions.checkArgument(inventory.canExtractItem(slot, stack, side.ordinal()),
"Item cannot be extracted from slot %s on side %s", slot, side);
}
public static Iterable<ItemStack> asIterable(final IInventory inv) {
return new Iterable<ItemStack>() {
@Override
public Iterator<ItemStack> iterator() {
return new AbstractIterator<ItemStack>() {
final int size = inv.getSizeInventory();
int slot = 0;
@Override
protected ItemStack computeNext() {
if (slot >= size) return endOfData();
return inv.getStackInSlot(slot++);
}
};
}
};
}
}