package crazypants.enderio.conduit.gui; import java.awt.Point; import java.util.ArrayList; import java.util.List; 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.ItemStack; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import com.enderio.core.client.gui.widget.GhostBackgroundItemSlot; import com.enderio.core.client.gui.widget.GhostSlot; import com.enderio.core.common.ContainerEnder; import com.enderio.core.common.util.ItemUtil; import crazypants.enderio.EnderIO; import crazypants.enderio.conduit.IConduitBundle; import crazypants.enderio.conduit.gui.item.InventoryUpgrades; import crazypants.enderio.conduit.item.IItemConduit; import crazypants.enderio.conduit.item.SpeedUpgrade; import crazypants.enderio.network.PacketHandler; public class ExternalConnectionContainer extends ContainerEnder<InventoryUpgrades> { private final IItemConduit itemConduit; private int speedUpgradeSlotLimit = 15; private static final int outputFilterUpgradeSlot = 36; private static final int inputFilterUpgradeSlot = 37; private static final int speedUpgradeSlot = 38; private static final int functionUpgradeSlot = 39; private Slot slotSpeedUpgrades; private Slot slotFunctionUpgrades; private Slot slotInputFilterUpgrades; private Slot slotOutputFilterUpgrades; private final List<Point> slotLocations = new ArrayList<Point>(); final List<FilterChangeListener> filterListeners = new ArrayList<FilterChangeListener>(); final List<GhostBackgroundItemSlot> bgSlots = new ArrayList<GhostBackgroundItemSlot>(); public ExternalConnectionContainer(InventoryPlayer playerInv, IConduitBundle bundle, ForgeDirection dir) { super(playerInv, new InventoryUpgrades(bundle.getConduit(IItemConduit.class), dir)); this.itemConduit = bundle.getConduit(IItemConduit.class); slotLocations.addAll(playerSlotLocations.values()); int x; int y; if (itemConduit != null) { x = 10; y = 47; slotOutputFilterUpgrades = addSlotToContainer(new FilterSlot(getInv(), 3, x, y)); slotLocations.add(new Point(x, y)); bgSlots.add(new GhostBackgroundItemSlot(EnderIO.itemBasicFilterUpgrade, slotOutputFilterUpgrades)); x = 10; y = 47; slotInputFilterUpgrades = addSlotToContainer(new FilterSlot(getInv(), 2, x, y)); slotLocations.add(new Point(x, y)); bgSlots.add(new GhostBackgroundItemSlot(EnderIO.itemBasicFilterUpgrade, slotInputFilterUpgrades)); x = 28; y = 47; slotSpeedUpgrades = addSlotToContainer(new Slot(getInv(), 0, x, y) { @Override public boolean isItemValid(ItemStack par1ItemStack) { return getInv().isItemValidForSlot(0, par1ItemStack); } @Override public int getSlotStackLimit() { return speedUpgradeSlotLimit; } }); slotLocations.add(new Point(x, y)); bgSlots.add(new GhostBackgroundItemSlot(EnderIO.itemExtractSpeedUpgrade, slotSpeedUpgrades)); x = 10; y = 65; slotFunctionUpgrades = addSlotToContainer(new Slot(getInv(), 1, x, y) { @Override public boolean isItemValid(ItemStack par1ItemStack) { return getInv().isItemValidForSlot(1, par1ItemStack); } @Override public int getSlotStackLimit() { return 1; } }); slotLocations.add(new Point(x, y)); bgSlots.add(new GhostBackgroundItemSlot(EnderIO.itemFunctionUpgrade, slotFunctionUpgrades)); } } public void createGhostSlots(List<GhostSlot> slots) { slots.addAll(bgSlots); } @Override public Point getPlayerInventoryOffset() { return new Point(23, 113); } public void addFilterListener(FilterChangeListener list) { filterListeners.add(list); } protected void filterChanged() { for (FilterChangeListener list : filterListeners) { list.onFilterChanged(); } } public boolean hasSpeedUpgrades() { return slotSpeedUpgrades != null && slotSpeedUpgrades.getHasStack(); } public boolean hasFunctionUpgrades() { return slotFunctionUpgrades != null && slotFunctionUpgrades.getHasStack(); } public boolean hasFilterUpgrades(boolean input) { Slot slot = input ? slotInputFilterUpgrades : slotOutputFilterUpgrades; return slot != null && slot.getHasStack(); } public void setInoutSlotsVisible(boolean inputVisible, boolean outputVisible) { if(itemConduit == null) { return; } setSlotsVisible(inputVisible, inputFilterUpgradeSlot, inputFilterUpgradeSlot + 1); setSlotsVisible(inputVisible, speedUpgradeSlot, speedUpgradeSlot + 1); setSlotsVisible(outputVisible, outputFilterUpgradeSlot, outputFilterUpgradeSlot + 1); setSlotsVisible(inputVisible || outputVisible, functionUpgradeSlot, functionUpgradeSlot + 1); World world = itemConduit.getBundle().getWorld(); if(world.isRemote) { PacketHandler.INSTANCE.sendToServer(new PacketSlotVisibility(inputVisible, outputVisible)); } } public void setInventorySlotsVisible(boolean visible) { setSlotsVisible(visible, 0, 36); } private void setSlotsVisible(boolean visible, int startIndex, int endIndex) { for (int i = startIndex; i < endIndex; i++) { Slot s = (Slot) inventorySlots.get(i); if(visible) { s.xDisplayPosition = slotLocations.get(i).x; s.yDisplayPosition = slotLocations.get(i).y; } else { s.xDisplayPosition = -3000; s.yDisplayPosition = -3000; } } } @Override public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer par4EntityPlayer) { ItemStack st = par4EntityPlayer.inventory.getItemStack(); setSpeedUpgradeSlotLimit(st); try { return super.slotClick(par1, par2, par3, par4EntityPlayer); } catch (Exception e) { //Horrible work around for a bug when double clicking on a stack in inventory which matches a filter item //This does does double clicking to fill a stack from working with this GUI open. return null; } } private void setSpeedUpgradeSlotLimit(ItemStack st) { if(st != null && st.getItem() == EnderIO.itemExtractSpeedUpgrade) { SpeedUpgrade speedUpgrade = EnderIO.itemExtractSpeedUpgrade.getSpeedUpgrade(st); speedUpgradeSlotLimit = speedUpgrade.maxStackSize; } } private boolean mergeItemStackSpecial(ItemStack origStack, Slot targetSlot) { if (!targetSlot.isItemValid(origStack)) { return false; } setSpeedUpgradeSlotLimit(origStack); ItemStack curStack = targetSlot.getStack(); int maxStackSize = Math.min(origStack.getMaxStackSize(), targetSlot.getSlotStackLimit()); if(curStack == null) { curStack = origStack.copy(); curStack.stackSize = Math.min(origStack.stackSize, maxStackSize); origStack.stackSize -= curStack.stackSize; targetSlot.putStack(curStack); targetSlot.onSlotChanged(); return true; } else if(ItemUtil.areStackMergable(curStack, origStack)) { int mergedSize = curStack.stackSize + origStack.stackSize; if(mergedSize <= maxStackSize) { origStack.stackSize = 0; curStack.stackSize = mergedSize; targetSlot.onSlotChanged(); return true; } else if(curStack.stackSize < maxStackSize) { origStack.stackSize -= maxStackSize - curStack.stackSize; curStack.stackSize = maxStackSize; targetSlot.onSlotChanged(); return true; } } return false; } @Override public ItemStack transferStackInSlot(EntityPlayer entityPlayer, int slotIndex) { ItemStack copystack = null; Slot slot = (Slot) inventorySlots.get(slotIndex); if(slot != null && slot.getHasStack()) { ItemStack origStack = slot.getStack(); copystack = origStack.copy(); boolean merged = false; if (slotIndex < outputFilterUpgradeSlot) { for (int targetSlotIdx = outputFilterUpgradeSlot; targetSlotIdx <= functionUpgradeSlot; targetSlotIdx++) { Slot targetSlot = (Slot) inventorySlots.get(targetSlotIdx); if(targetSlot.xDisplayPosition >= 0 && mergeItemStackSpecial(origStack, targetSlot)) { merged = true; break; } } } else { merged = mergeItemStack(origStack, 0, outputFilterUpgradeSlot, false); } if(!merged) { return null; } slot.onSlotChange(origStack, copystack); if(origStack.stackSize == 0) { slot.putStack((ItemStack) null); } else { slot.onSlotChanged(); } if(origStack.stackSize == copystack.stackSize) { return null; } slot.onPickupFromSlot(entityPlayer, origStack); } return copystack; } private class FilterSlot extends Slot { public FilterSlot(IInventory par1iInventory, int par2, int par3, int par4) { super(par1iInventory, par2, par3, par4); } @Override public int getSlotStackLimit() { return 1; } @Override public void onSlotChanged() { filterChanged(); } @Override public boolean isItemValid(ItemStack par1ItemStack) { return inventory.isItemValidForSlot(getSlotIndex(), par1ItemStack); } } }