/*
* Copyright (c) CovertJaguar, 2014 http://railcraft.info
*
* This code is the property of CovertJaguar
* and may only be used with explicit written
* permission unless otherwise specified on the
* license page at http://railcraft.info/wiki/info:license.
*/
package mods.railcraft.common.gui.containers;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import mods.railcraft.common.gui.widgets.Widget;
import net.minecraft.inventory.Container;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.inventory.Slot;
import mods.railcraft.common.gui.slots.SlotRailcraft;
import mods.railcraft.common.util.inventory.InvTools;
import mods.railcraft.common.util.network.PacketBuilder;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.ICrafting;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public abstract class RailcraftContainer extends Container {
private final IInventory callback;
private List<Widget> widgets = new ArrayList<Widget>();
public RailcraftContainer(IInventory inv) {
this.callback = inv;
}
public RailcraftContainer() {
this.callback = null;
}
public List<Widget> getElements() {
return widgets;
}
public void addSlot(Slot slot) {
addSlotToContainer(slot);
}
public void addWidget(Widget widget) {
widget.addToContainer(this);
widgets.add(widget);
}
@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);
}
}
}
public void sendWidgetDataToClient(Widget widget, ICrafting player, byte[] data) {
PacketBuilder.instance().sendGuiWidgetPacket((EntityPlayerMP) player, windowId, widgets.indexOf(widget), data);
}
public void handleWidgetClientData(int widgetId, DataInputStream data) throws IOException {
widgets.get(widgetId).handleClientPacketData(data);
}
@SideOnly(Side.CLIENT)
public void updateString(byte id, String data) {
}
@Override
public boolean canInteractWith(EntityPlayer entityplayer) {
if (callback == null) return true;
return callback.isUseableByPlayer(entityplayer);
}
@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 SlotRailcraft && ((SlotRailcraft) slot).isPhantom())
return slotClickPhantom((SlotRailcraft) slot, mouseButton, modifier, player);
return super.slotClick(slotNum, mouseButton, modifier, player);
}
private ItemStack slotClickPhantom(SlotRailcraft slot, int mouseButton, int modifier, EntityPlayer player) {
ItemStack stack = null;
if (mouseButton == 2) {
if (slot.canAdjustPhantom())
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 (InvTools.isItemEqual(stackSlot, stackHeld))
adjustPhantomSlot(slot, mouseButton, modifier);
else
fillPhantomSlot(slot, stackHeld, mouseButton, modifier);
}
return stack;
}
protected void adjustPhantomSlot(SlotRailcraft slot, int mouseButton, int modifier) {
if (!slot.canAdjustPhantom())
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((ItemStack) null);
}
protected void fillPhantomSlot(SlotRailcraft slot, ItemStack stackHeld, int mouseButton, int modifier) {
if (!slot.canAdjustPhantom())
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 && InvTools.isItemEqual(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 SlotRailcraft) {
SlotRailcraft slotRailcraft = (SlotRailcraft) slot;
if (slotRailcraft.isPhantom())
continue;
if (!slotRailcraft.canShift())
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;
}
}