package com.bioxx.tfc2.containers;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.ClickType;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import com.bioxx.tfc2.api.interfaces.IFood;
import com.bioxx.tfc2.core.Food;
public class ContainerTFC extends Container
{
public int bagsSlotNum;
public EntityPlayer player;
protected boolean isLoading;
protected boolean doItemSaving;
@Override
public boolean canInteractWith(EntityPlayer var1)
{
return true;
}
/**
* Used by containers that represent items and need to save the inventory to that items NBT
*/
public void saveContents(ItemStack is)
{
}
/**
* Used by containers that represent items and need to load an item from nbt
* @return null, as it is currently ignored
*/
public ItemStack loadContents(int slot)
{
return null;
}
@Override
/**
* Handles slot click.
*
* @param mode 0 = basic click, 1 = shift click, 2 = hotbar, 3 = pick block, 4 = drop, 5 = ?, 6 = double click
*/
public ItemStack slotClick(int slotID, int dragType, ClickType clickTypeIn, EntityPlayer p)
{
if (slotID >= 0 && slotID < this.inventorySlots.size())
{
Slot sourceSlot = (Slot) this.inventorySlots.get(slotID);
ItemStack slotStack = sourceSlot.getStack();
//This section is for merging foods with differing expirations.
if(clickTypeIn == ClickType.SWAP && slotStack != null && p.inventory.getItemStack() != null)
{
ItemStack itemstack4 = p.inventory.getItemStack();
if (slotStack.getItem() == itemstack4.getItem() && slotStack.getMetadata() == itemstack4.getMetadata() && ContainerTFC.areCompoundsEqual(slotStack, itemstack4))
{
if(slotStack.getItem() instanceof IFood && itemstack4.getItem() instanceof IFood)
{
long ex1 = Food.getDecayTimer(slotStack);
long ex2 = Food.getDecayTimer(itemstack4);
if(ex2 < ex1)
Food.setDecayTimer(slotStack, ex2);
}
//int l1 = clickedButton == 0 ? itemstack4.stackSize : 1;
int l1 = itemstack4.stackSize;
if (l1 > sourceSlot.getItemStackLimit(itemstack4) - slotStack.stackSize)
{
l1 = sourceSlot.getItemStackLimit(itemstack4) - slotStack.stackSize;
}
if (l1 > itemstack4.getMaxStackSize() - slotStack.stackSize)
{
l1 = itemstack4.getMaxStackSize() - slotStack.stackSize;
}
itemstack4.splitStack(l1);
if (itemstack4.stackSize == 0)
{
p.inventory.setItemStack((ItemStack)null);
}
slotStack.stackSize += l1;
return null;
}
else if (itemstack4.stackSize <= sourceSlot.getItemStackLimit(itemstack4))
{
sourceSlot.putStack(itemstack4);
p.inventory.setItemStack(slotStack);
}
}
// Hotbar press to remove from crafting output
if (clickTypeIn == ClickType.QUICK_MOVE && slotID == 0 && slotStack != null)
{
//Removed During Port
//CraftingHandler.preCraft(p, slotStack, craftMatrix);
}
// S and D hotkeys for trimming/combining food
/*else if (mode == 7 && slotID >= 9 && slotID < 45)
{
if (sourceSlot.canTakeStack(p))
{
Slot destSlot = (Slot) this.inventorySlots.get(clickedButton);
destSlot.putStack(slotStack);
sourceSlot.putStack(null);
return null;
}
}*/
}
ItemStack is = super.slotClick(slotID, dragType, clickTypeIn, p);
saveContents(is);
return is;
}
@Override
protected boolean mergeItemStack(ItemStack is, int slotStart, int slotFinish, boolean par4)
{
boolean merged = false;
int slotIndex = slotStart;
if (par4)
slotIndex = slotFinish - 1;
Slot slot;
ItemStack slotstack;
if (is.isStackable())
{
while (is.stackSize > 0 && (!par4 && slotIndex < slotFinish || par4 && slotIndex >= slotStart))
{
slot = (Slot)this.inventorySlots.get(slotIndex);
slotstack = slot.getStack();
if (slotstack != null
&& slotstack.getItem() == is.getItem()
&& (!is.getHasSubtypes() || is.getMetadata() == slotstack.getMetadata())
&& ItemStack.areItemStackTagsEqual(is, slotstack)
&& slotstack.stackSize < slot.getSlotStackLimit())
{
int mergedStackSize = is.stackSize + getSmaller(slotstack.stackSize, slot.getSlotStackLimit());
//First we check if we can add the two stacks together and the resulting stack is smaller than the maximum size for the slot or the stack
if (mergedStackSize <= is.getMaxStackSize() && mergedStackSize <= slot.getSlotStackLimit())
{
is.stackSize = 0;
slotstack.stackSize = mergedStackSize;
slot.onSlotChanged();
merged = true;
}
else if (slotstack.stackSize < is.getMaxStackSize() && slotstack.stackSize < slot.getSlotStackLimit())
{
// Slot stack size is greater than or equal to the item's max stack size. Most containers are this case.
if (slot.getSlotStackLimit() >= is.getMaxStackSize())
{
is.stackSize -= is.getMaxStackSize() - slotstack.stackSize;
slotstack.stackSize = is.getMaxStackSize();
slot.onSlotChanged();
merged = true;
}
// Slot stack size is smaller than the item's normal max stack size. Example: Log Piles
else if (slot.getSlotStackLimit() < is.getMaxStackSize())
{
is.stackSize -= slot.getSlotStackLimit() - slotstack.stackSize;
slotstack.stackSize = slot.getSlotStackLimit();
slot.onSlotChanged();
merged = true;
}
}
}
if (par4)
--slotIndex;
else
++slotIndex;
}
}
if (is.stackSize > 0)
{
if (par4)
slotIndex = slotFinish - 1;
else
slotIndex = slotStart;
while (!par4 && slotIndex < slotFinish || par4 && slotIndex >= slotStart)
{
slot = (Slot)this.inventorySlots.get(slotIndex);
slotstack = slot.getStack();
if (slotstack == null && slot.isItemValid(is) && slot.getSlotStackLimit() < is.stackSize)
{
ItemStack copy = is.copy();
copy.stackSize = slot.getSlotStackLimit();
is.stackSize -= slot.getSlotStackLimit();
slot.putStack(copy);
slot.onSlotChanged();
merged = true;
//this.bagsSlotNum = slotIndex;
break;
}
else if (slotstack == null && slot.isItemValid(is))
{
slot.putStack(is.copy());
slot.onSlotChanged();
is.stackSize = 0;
merged = true;
break;
}
if (par4)
--slotIndex;
else
++slotIndex;
}
}
return merged;
}
protected int getSmaller(int i, int j)
{
if(i < j)
return i;
else
return j;
}
@Override
public void detectAndSendChanges()
{
boolean shouldSave = false;
boolean shouldReload = false;
for (int i = 0; i < this.inventorySlots.size(); ++i)
{
ItemStack itemstack = ((Slot)this.inventorySlots.get(i)).getStack();//the visible slot item
ItemStack itemstack1 = (ItemStack)this.inventoryItemStacks.get(i);//the real invisible item
if (!areItemStacksEqual(itemstack1, itemstack))
{
if(doItemSaving && i < inventoryItemStacks.size()-36 && !isLoading)
shouldSave = true;
itemstack1 = itemstack == null ? null : itemstack.copy();
if(itemstack1 != null && itemstack1.stackSize == 0)
itemstack1 = null;
this.inventoryItemStacks.set(i, itemstack1);
if(shouldSave)
{
int slotNum = bagsSlotNum + (inventoryItemStacks.size()-36);
this.saveContents((ItemStack)inventoryItemStacks.get(slotNum));
player.inventory.setInventorySlotContents(bagsSlotNum, (ItemStack)inventoryItemStacks.get(slotNum));
for (int j = 0; j < this.listeners.size(); ++j)
((IContainerListener)this.listeners.get(j)).sendSlotContents(this, slotNum, (ItemStack)inventoryItemStacks.get(slotNum));
}
for (int j = 0; j < this.listeners.size(); ++j)
((IContainerListener)this.listeners.get(j)).sendSlotContents(this, i, itemstack1);
}
}
for (int i = 0; i < this.inventorySlots.size()-36; ++i)
{
//ItemStack itemstack = this.loadContents(i);
//ItemStack itemstack1 = (ItemStack) this.inventoryItemStacks.get(i);//the real invisible item
// This method was mysteriously deleted with no trace on github. However adding it back causes a crash.
// if (!areItemStacksEqual(itemstack1, itemstack) && player.inventory.getItemStack() == null)
{
shouldReload = true;
}
}
if(shouldReload && !isLoading)
reloadContainer();
this.isLoading = false;
}
/**
* This is only used if the container should be reloaded due to some change in information
* that can't be updated in some other way.
*/
public void reloadContainer()
{
}
public static boolean areItemStacksEqual(ItemStack is1, ItemStack is2)
{
return is1 == null && is2 == null || (is1 != null && is2 != null) && isItemStackEqual(is1, is2);
}
public static boolean isItemStackEqual(ItemStack is1, ItemStack is2)
{
return is1.stackSize == is2.stackSize && is1.getItem() == is2.getItem() && is1.getItemDamage() == is2.getItemDamage() &&
(is1.hasTagCompound() || !is2.hasTagCompound()) &&
(!is1.hasTagCompound() || areCompoundsEqual(is1, is2));
}
public static boolean areCompoundsEqual(ItemStack is1, ItemStack is2)
{
ItemStack is3 = is1.copy();
ItemStack is4 = is2.copy();
NBTTagCompound is3Tags = is3.getTagCompound();
NBTTagCompound is4Tags = is4.getTagCompound();
if (is3Tags == null)
return is4Tags == null || is4Tags.hasNoTags();
if (is4Tags == null)
return is3Tags.hasNoTags();
//Removed during porting this code to 1.8 due to there not being any heat infrastructure at the time.
/*float temp3 = TFC_ItemHeat.getTemp(is1);
float temp4 = TFC_ItemHeat.getTemp(is2);
is3Tags.removeTag("temp");
is4Tags.removeTag("temp");*/
is3Tags.removeTag("Expiration");
is4Tags.removeTag("Expiration");
return is3Tags.equals(is4Tags) /*&& Math.abs(temp3 - temp4) < 5*/;
}
public ItemStack transferStackInSlotTFC(EntityPlayer entityplayer, int slotNum)
{
return super.transferStackInSlot(entityplayer, slotNum);
}
@Override
final public ItemStack transferStackInSlot(EntityPlayer entityplayer, int slotNum)
{
Slot slot = (Slot)this.inventorySlots.get( slotNum );
ItemStack is = transferStackInSlotTFC(entityplayer, slotNum);
// send a packet to make sure that the item is removed; that it stays removed.
if ( ! slot.getHasStack() && entityplayer instanceof EntityPlayerMP && ! entityplayer.worldObj.isRemote )
{
EntityPlayerMP mp = (EntityPlayerMP) entityplayer;
mp.sendSlotContents( this, slot.slotNumber, slot.getStack() );
}
return is;
}
}