package crazypants.enderio.machine.capbank;
import java.awt.Point;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import com.enderio.core.common.ContainerEnder;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import crazypants.enderio.machine.capbank.network.InventoryImpl;
import crazypants.util.BaublesUtil;
import crazypants.util.ShadowInventory;
public class ContainerCapBank extends ContainerEnder<TileCapBank> {
private InventoryImpl inv;
// Note: Modifying the Baubles inventory on the client side of an integrated
// server is a bad idea because Baubles actually shares the object between
// server and client. However, by not doing so, we prevent the callback hooks
// to be called in the client thread. It doesn't seem to matter now, but if we
// ever get reports of problems, we need to find a solution to synthesize
// these calls.
// In a multiplayer client this works well, but we need to prevent Baubles
// from calling those callbacks when the server syncs the slot contents to the
// client (packet 30) initially. They are still called every time the server
// updates the slots (which is wrong), but the original Baubles inventory
// works this way, so...
private IInventory baubles;
public ContainerCapBank(InventoryPlayer playerInv, TileCapBank cb) {
super(playerInv, cb);
}
public boolean hasBaublesSlots() {
return baubles != null;
}
@Override
protected void addSlots(final InventoryPlayer playerInv) {
if(getInv().getNetwork() != null && getInv().getNetwork().getInventory() != null) {
inv = getInv().getNetwork().getInventory();
} else {
inv = new InventoryImpl();
}
baubles = BaublesUtil.instance().getBaubles(playerInv.player);
if (baubles != null && BaublesUtil.WhoAmI.whoAmI(playerInv.player.worldObj) == BaublesUtil.WhoAmI.SPCLIENT) {
baubles = new ShadowInventory(baubles);
}
int armorOffset = 21;
for(int i = 0; i < 4; i++) {
addSlotToContainer(new SlotImpl(inv, i, 59 + armorOffset + i*20, 59));
}
//armor slots
for (int i = 0; i < 4; ++i) {
final int k = i;
addSlotToContainer(new Slot(playerInv, playerInv.getSizeInventory() - 1 - i, -15 + armorOffset, 12 + i * 18) {
@Override
public int getSlotStackLimit() {
return 1;
}
@Override
public boolean isItemValid(ItemStack par1ItemStack) {
if(par1ItemStack == null) {
return false;
}
return par1ItemStack.getItem().isValidArmor(par1ItemStack, k, playerInv.player);
}
@Override
@SideOnly(Side.CLIENT)
public IIcon getBackgroundIconIndex() {
return ItemArmor.func_94602_b(k);
}
});
}
if (hasBaublesSlots()) {
for (int i = 0; i < baubles.getSizeInventory(); i++) {
addSlotToContainer(new Slot(baubles, i, -15 + armorOffset, 84 + i * 18) {
@Override
public boolean isItemValid(ItemStack par1ItemStack) {
return inventory.isItemValidForSlot(getSlotIndex(), par1ItemStack);
}
});
}
}
}
public void updateInventory() {
if(getInv().getNetwork() != null && getInv().getNetwork().getInventory() != null) {
inv.setCapBank(getInv().getNetwork().getInventory().getCapBank());
}
}
@Override
public Point getPlayerInventoryOffset() {
Point p = super.getPlayerInventoryOffset();
p.translate(21, 0);
return p;
}
@Override
public ItemStack transferStackInSlot(EntityPlayer entityPlayer, int slotIndex) {
int startPlayerSlot = 4;
int endPlayerSlot = startPlayerSlot + 26;
int startHotBarSlot = endPlayerSlot + 1;
int endHotBarSlot = startHotBarSlot + 9;
int startBaublesSlot = endHotBarSlot + 1;
int endBaublesSlot = baubles == null ? 0 : startBaublesSlot + baubles.getSizeInventory();
ItemStack copystack = null;
Slot slot = (Slot) inventorySlots.get(slotIndex);
if(slot != null && slot.getHasStack()) {
ItemStack origStack = slot.getStack();
copystack = origStack.copy();
// Note: Merging into Baubles slots is disabled because the used vanilla
// merge method does not check if the item can go into the slot or not.
if(slotIndex < 4) {
// merge from machine input slots to inventory
if (!mergeItemStackIntoArmor(entityPlayer, origStack, slotIndex)
&& /*
* !(baubles != null && mergeItemStack(origStack,
* startBaublesSlot, endBaublesSlot, false)) &&
*/!mergeItemStack(origStack, startPlayerSlot, endHotBarSlot, false)) {
return null;
}
} else {
//Check from inv-> charge then inv->hotbar or hotbar->inv
if(slotIndex >= startPlayerSlot) {
if(!inv.isItemValidForSlot(0, origStack) || !mergeItemStack(origStack, 0, 4, false)) {
if(slotIndex <= endPlayerSlot) {
if (/*
* !(baubles != null && mergeItemStack(origStack,
* startBaublesSlot, endBaublesSlot, false)) &&
*/!mergeItemStack(origStack, startHotBarSlot, endHotBarSlot, false)) {
return null;
}
} else if(slotIndex >= startHotBarSlot && slotIndex <= endHotBarSlot) {
if (/*
* !(baubles != null && mergeItemStack(origStack,
* startBaublesSlot, endBaublesSlot, false)) &&
*/!mergeItemStack(origStack, startPlayerSlot, endPlayerSlot, false)) {
return null;
}
} else if (slotIndex >= startBaublesSlot && slotIndex <= endBaublesSlot) {
if(!mergeItemStack(origStack, startHotBarSlot, endHotBarSlot, false) &&
!mergeItemStack(origStack, startPlayerSlot, endPlayerSlot, false)) {
return null;
}
}
}
}
}
if(origStack.stackSize == 0) {
slot.putStack((ItemStack) null);
} else {
slot.onSlotChanged();
}
slot.onSlotChanged();
if(origStack.stackSize == copystack.stackSize) {
return null;
}
slot.onPickupFromSlot(entityPlayer, origStack);
}
return copystack;
}
private boolean mergeItemStackIntoArmor(EntityPlayer entityPlayer, ItemStack origStack, int slotIndex) {
if(origStack == null || !(origStack.getItem() instanceof ItemArmor)) {
return false;
}
ItemArmor armor = (ItemArmor) origStack.getItem();
int index = 3 - armor.armorType;
ItemStack[] ai = entityPlayer.inventory.armorInventory;
if(ai[index] == null) {
ai[index] = origStack.copy();
origStack.stackSize = 0;
return true;
}
return false;
}
private static class SlotImpl extends Slot {
public SlotImpl(IInventory inv, int idx, int x, int y) {
super(inv, idx, x, y);
}
@Override
public boolean isItemValid(ItemStack itemStack) {
return inventory.isItemValidForSlot(getSlotIndex(), itemStack);
}
}
/**
* called when the content of slots is synced from the server to the client
* (packet 30)
*/
@Override
@SideOnly(Side.CLIENT)
public void putStacksInSlots(ItemStack[] p_75131_1_) {
if (hasBaublesSlots() && BaublesUtil.WhoAmI.whoAmI(getInv().getWorldObj()) == BaublesUtil.WhoAmI.MPCLIENT) {
try {
BaublesUtil.instance().disableCallbacks(baubles, true);
super.putStacksInSlots(p_75131_1_);
} finally {
BaublesUtil.instance().disableCallbacks(baubles, false);
}
} else {
super.putStacksInSlots(p_75131_1_);
}
}
}