/** * Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team * http://www.mod-buildcraft.com * <p/> * BuildCraft is distributed under the terms of the Minecraft Mod Public * License 1.0, or MMPL. Please check the contents of the license located in * http://www.mod-buildcraft.com/MMPL-1.0.txt */ package buildcraft.core.lib.gui; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.ICrafting; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import buildcraft.BuildCraftCore; import buildcraft.core.lib.gui.slots.IPhantomSlot; import buildcraft.core.lib.gui.slots.SlotBase; import buildcraft.core.lib.gui.widgets.Widget; import buildcraft.core.lib.inventory.StackHelper; import buildcraft.core.lib.network.PacketGuiWidget; public abstract class BuildCraftContainer extends Container { private List<Widget> widgets = new ArrayList<Widget>(); private int inventorySize; public BuildCraftContainer(int inventorySize) { this.inventorySize = inventorySize; } public List<Widget> getWidgets() { return widgets; } public void addSlot(Slot slot) { addSlotToContainer(slot); } public void addWidget(Widget widget) { widget.addToContainer(this); widgets.add(widget); } public void sendWidgetDataToClient(Widget widget, ICrafting player, byte[] data) { PacketGuiWidget pkt = new PacketGuiWidget(windowId, widgets.indexOf(widget), data); BuildCraftCore.instance.sendToPlayer((EntityPlayer) player, pkt); } public void handleWidgetClientData(int widgetId, ByteBuf data) { InputStream input = new ByteBufInputStream(data); DataInputStream stream = new DataInputStream(input); try { widgets.get(widgetId).handleClientPacketData(stream); } catch (IOException e) { e.printStackTrace(); } } @Override public void addCraftingToCrafters(ICrafting player) { super.addCraftingToCrafters(player); for (Widget widget : widgets) { widget.initWidget(player); } } @Override public void detectAndSendChanges() { super.detectAndSendChanges(); for (Widget widget : widgets) { for (ICrafting player : (List<ICrafting>) crafters) { widget.updateWidget(player); } } } @Override public ItemStack slotClick(int slotNum, int mouseButton, int modifier, EntityPlayer player) { Slot slot = slotNum < 0 ? null : (Slot) this.inventorySlots.get(slotNum); if (slot instanceof IPhantomSlot) { return slotClickPhantom(slot, mouseButton, modifier, player); } return super.slotClick(slotNum, mouseButton, modifier, player); } private ItemStack slotClickPhantom(Slot slot, int mouseButton, int modifier, EntityPlayer player) { ItemStack stack = null; if (mouseButton == 2) { if (((IPhantomSlot) slot).canAdjust()) { slot.putStack(null); } } else if (mouseButton == 0 || mouseButton == 1) { InventoryPlayer playerInv = player.inventory; slot.onSlotChanged(); ItemStack stackSlot = slot.getStack(); ItemStack stackHeld = playerInv.getItemStack(); if (stackSlot != null) { stack = stackSlot.copy(); } if (stackSlot == null) { if (stackHeld != null && slot.isItemValid(stackHeld)) { fillPhantomSlot(slot, stackHeld, mouseButton, modifier); } } else if (stackHeld == null) { adjustPhantomSlot(slot, mouseButton, modifier); slot.onPickupFromSlot(player, playerInv.getItemStack()); } else if (slot.isItemValid(stackHeld)) { if (StackHelper.canStacksMerge(stackSlot, stackHeld)) { adjustPhantomSlot(slot, mouseButton, modifier); } else { fillPhantomSlot(slot, stackHeld, mouseButton, modifier); } } } return stack; } protected void adjustPhantomSlot(Slot slot, int mouseButton, int modifier) { if (!((IPhantomSlot) slot).canAdjust()) { return; } ItemStack stackSlot = slot.getStack(); int stackSize; if (modifier == 1) { stackSize = mouseButton == 0 ? (stackSlot.stackSize + 1) / 2 : stackSlot.stackSize * 2; } else { stackSize = mouseButton == 0 ? stackSlot.stackSize - 1 : stackSlot.stackSize + 1; } if (stackSize > slot.getSlotStackLimit()) { stackSize = slot.getSlotStackLimit(); } stackSlot.stackSize = stackSize; if (stackSlot.stackSize <= 0) { slot.putStack(null); } } protected void fillPhantomSlot(Slot slot, ItemStack stackHeld, int mouseButton, int modifier) { if (!((IPhantomSlot) slot).canAdjust()) { return; } int stackSize = mouseButton == 0 ? stackHeld.stackSize : 1; if (stackSize > slot.getSlotStackLimit()) { stackSize = slot.getSlotStackLimit(); } ItemStack phantomStack = stackHeld.copy(); phantomStack.stackSize = stackSize; slot.putStack(phantomStack); } protected boolean shiftItemStack(ItemStack stackToShift, int start, int end) { boolean changed = false; if (stackToShift.isStackable()) { for (int slotIndex = start; stackToShift.stackSize > 0 && slotIndex < end; slotIndex++) { Slot slot = (Slot) inventorySlots.get(slotIndex); ItemStack stackInSlot = slot.getStack(); if (stackInSlot != null && StackHelper.canStacksMerge(stackInSlot, stackToShift)) { int resultingStackSize = stackInSlot.stackSize + stackToShift.stackSize; int max = Math.min(stackToShift.getMaxStackSize(), slot.getSlotStackLimit()); if (resultingStackSize <= max) { stackToShift.stackSize = 0; stackInSlot.stackSize = resultingStackSize; slot.onSlotChanged(); changed = true; } else if (stackInSlot.stackSize < max) { stackToShift.stackSize -= max - stackInSlot.stackSize; stackInSlot.stackSize = max; slot.onSlotChanged(); changed = true; } } } } if (stackToShift.stackSize > 0) { for (int slotIndex = start; stackToShift.stackSize > 0 && slotIndex < end; slotIndex++) { Slot slot = (Slot) inventorySlots.get(slotIndex); ItemStack stackInSlot = slot.getStack(); if (stackInSlot == null) { int max = Math.min(stackToShift.getMaxStackSize(), slot.getSlotStackLimit()); stackInSlot = stackToShift.copy(); stackInSlot.stackSize = Math.min(stackToShift.stackSize, max); stackToShift.stackSize -= stackInSlot.stackSize; slot.putStack(stackInSlot); slot.onSlotChanged(); changed = true; } } } return changed; } private boolean tryShiftItem(ItemStack stackToShift, int numSlots) { for (int machineIndex = 0; machineIndex < numSlots - 9 * 4; machineIndex++) { Slot slot = (Slot) inventorySlots.get(machineIndex); if (slot instanceof SlotBase && !((SlotBase) slot).canShift()) { continue; } if (slot instanceof IPhantomSlot) { continue; } if (!slot.isItemValid(stackToShift)) { continue; } if (shiftItemStack(stackToShift, machineIndex, machineIndex + 1)) { return true; } } return false; } @Override public ItemStack transferStackInSlot(EntityPlayer player, int slotIndex) { ItemStack originalStack = null; Slot slot = (Slot) inventorySlots.get(slotIndex); int numSlots = inventorySlots.size(); if (slot != null && slot.getHasStack()) { ItemStack stackInSlot = slot.getStack(); originalStack = stackInSlot.copy(); if (slotIndex >= numSlots - 9 * 4 && tryShiftItem(stackInSlot, numSlots)) { // NOOP } else if (slotIndex >= numSlots - 9 * 4 && slotIndex < numSlots - 9) { if (!shiftItemStack(stackInSlot, numSlots - 9, numSlots)) { return null; } } else if (slotIndex >= numSlots - 9 && slotIndex < numSlots) { if (!shiftItemStack(stackInSlot, numSlots - 9 * 4, numSlots - 9)) { return null; } } else if (!shiftItemStack(stackInSlot, numSlots - 9 * 4, numSlots)) { return null; } slot.onSlotChange(stackInSlot, originalStack); if (stackInSlot.stackSize <= 0) { slot.putStack(null); } else { slot.onSlotChanged(); } if (stackInSlot.stackSize == originalStack.stackSize) { return null; } slot.onPickupFromSlot(player, stackInSlot); } return originalStack; } public int getInventorySize() { return inventorySize; } }