package openmods.container;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ICrafting;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import openmods.utils.InventoryUtils;
public abstract class ContainerBase<T> extends Container {
protected final int inventorySize;
protected final IInventory playerInventory;
protected final T owner;
protected final IInventory inventory;
protected static class RestrictedSlot extends Slot {
private final int inventoryIndex;
public RestrictedSlot(IInventory inventory, int slot, int x, int y) {
super(inventory, slot, x, y);
inventoryIndex = slot; // since slotIndex is private
}
@Override
public boolean isItemValid(ItemStack itemstack) {
return inventory.isItemValidForSlot(inventoryIndex, itemstack);
}
}
public ContainerBase(IInventory playerInventory, IInventory ownerInventory, T owner) {
this.owner = owner;
this.inventory = ownerInventory;
this.inventorySize = inventory.getSizeInventory();
this.playerInventory = playerInventory;
}
protected void addInventoryGrid(int xOffset, int yOffset, int width) {
int height = (int)Math.ceil((double)inventorySize / width);
for (int y = 0, slotId = 0; y < height; y++) {
for (int x = 0; x < width; x++, slotId++) {
addSlotToContainer(new RestrictedSlot(inventory, slotId,
xOffset + x * 18,
yOffset + y * 18));
}
}
}
protected void addInventoryLine(int xOffset, int yOffset, int start, int count) {
addInventoryLine(xOffset, yOffset, start, count, 0);
}
protected void addInventoryLine(int xOffset, int yOffset, int start, int count, int margin) {
for (int x = 0, slotId = start; x < count; x++, slotId++) {
addSlotToContainer(new RestrictedSlot(inventory, slotId,
xOffset + x * (18 + margin),
yOffset));
}
}
protected void addPlayerInventorySlots(int offsetY) {
addPlayerInventorySlots(8, offsetY);
}
protected void addPlayerInventorySlots(int offsetX, int offsetY) {
for (int row = 0; row < 3; row++)
for (int column = 0; column < 9; column++)
addSlotToContainer(new Slot(playerInventory,
column + row * 9 + 9,
offsetX + column * 18,
offsetY + row * 18));
for (int slot = 0; slot < 9; slot++)
addSlotToContainer(new Slot(playerInventory, slot, offsetX + slot
* 18, offsetY + 58));
}
@Override
public boolean canInteractWith(EntityPlayer entityplayer) {
return inventory.isUseableByPlayer(entityplayer);
}
public T getOwner() {
return owner;
}
protected boolean mergeItemStackSafe(ItemStack stackToMerge, int start, int stop, boolean reverse) {
boolean inventoryChanged = false;
final int delta = reverse? -1 : 1;
List<Slot> slots = getSlots();
if (stackToMerge.isStackable()) {
int slotId = reverse? stop - 1 : start;
while (stackToMerge.stackSize > 0 && ((!reverse && slotId < stop) || (reverse && slotId >= start))) {
Slot slot = slots.get(slotId);
if (canTransferItemsIn(slot)) {
ItemStack stackInSlot = slot.getStack();
if (InventoryUtils.tryMergeStacks(stackToMerge, stackInSlot)) {
slot.onSlotChanged();
inventoryChanged = true;
}
}
slotId += delta;
}
}
if (stackToMerge.stackSize > 0) {
int slotId = reverse? stop - 1 : start;
while ((!reverse && slotId < stop) || (reverse && slotId >= start)) {
Slot slot = slots.get(slotId);
ItemStack stackInSlot = slot.getStack();
if (stackInSlot == null && canTransferItemsIn(slot) && slot.isItemValid(stackToMerge)) {
slot.putStack(stackToMerge.copy());
slot.onSlotChanged();
stackToMerge.stackSize = 0;
return true;
}
slotId += delta;
}
}
return inventoryChanged;
}
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int slotId) {
Slot slot = (Slot)inventorySlots.get(slotId);
if (slot != null && canTransferItemOut(slot) && slot.getHasStack()) {
ItemStack itemToTransfer = slot.getStack();
ItemStack copy = itemToTransfer.copy();
if (slotId < inventorySize) {
if (!mergeItemStackSafe(itemToTransfer, inventorySize, inventorySlots.size(), true)) return null;
} else if (!mergeItemStackSafe(itemToTransfer, 0, inventorySize, false)) return null;
if (itemToTransfer.stackSize == 0) slot.putStack(null);
else slot.onSlotChanged();
if (itemToTransfer.stackSize != copy.stackSize) return copy;
}
return null;
}
protected boolean canTransferItemOut(Slot slot) {
if (slot instanceof ICustomSlot) return ((ICustomSlot)slot).canTransferItemsOut();
return true;
}
protected boolean canTransferItemsIn(Slot slot) {
if (slot instanceof ICustomSlot) return ((ICustomSlot)slot).canTransferItemsIn();
return true;
}
public int getInventorySize() {
return inventorySize;
}
@SuppressWarnings("unchecked")
protected List<Slot> getSlots() {
return inventorySlots;
}
@SuppressWarnings("unchecked")
public Set<EntityPlayer> getPlayers() {
Set<EntityPlayer> players = new HashSet<EntityPlayer>();
for (ICrafting crafter : (List<ICrafting>)crafters) {
if (crafter instanceof EntityPlayerMP) {
players.add((EntityPlayerMP)crafter);
}
}
return players;
}
public void onButtonClicked(EntityPlayer player, int buttonId) {}
@Override
public boolean enchantItem(EntityPlayer player, int buttonId) {
onButtonClicked(player, buttonId);
return false;
}
@Override
public ItemStack slotClick(int slotId, int key, int modifier, EntityPlayer player) {
if (slotId >= 0 && slotId < inventorySlots.size()) {
Slot slot = getSlot(slotId);
if (slot instanceof ICustomSlot) return ((ICustomSlot)slot).onClick(player, key, modifier);
}
return super.slotClick(slotId, key, modifier, player);
}
@Override
public boolean canDragIntoSlot(Slot slot) {
if (slot instanceof ICustomSlot) return ((ICustomSlot)slot).canDrag();
return super.canDragIntoSlot(slot);
}
}