package minefantasy.block.tileentity;
import java.util.Random;
import com.google.common.io.ByteArrayDataInput;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import minefantasy.api.IMFCrafter;
import minefantasy.api.tailor.CraftingManagerTailor;
import minefantasy.api.tailor.INeedle;
import minefantasy.api.tailor.ITailor;
import minefantasy.api.tailor.StringList;
import minefantasy.block.special.BlockClickHelper;
import minefantasy.block.special.BlockTailor;
import minefantasy.container.ContainerTailor;
import minefantasy.item.ItemHotItem;
import minefantasy.system.StatListMF;
import minefantasy.system.network.PacketManagerMF;
import minefantasy.system.network.PacketUserMF;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.packet.Packet;
import net.minecraft.stats.AchievementList;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.oredict.OreDictionary;
/**
*
* @author Anonymous Productions
*
* Sources are provided for educational reasons.
* though small bits of code, or methods can be used in your own creations.
*
* BlockTailor
*/
public class TileEntityTailor extends TileEntity implements IInventory, PacketUserMF, ITailor, IMFCrafter
{
@SideOnly(Side.CLIENT)
private ItemStack tempResult;
public int direction;
private ItemStack[] inv;
public int progress;
private int maxProgress = 200;
private int ticks;
private int recipeTier;
public int reqString;
private float sewTime;
private float sewProg;
private ItemStack recipe;
public TileEntityTailor()
{
inv = new ItemStack[21];
}
//MAIN LOGIC--------------------------------------------------------------------------------------
/**
* Called when the player right clicks the block
* @return true if it does anything
*/
public boolean onUse(EntityPlayer player)
{
if(player == null)
{
return false;
}
ItemStack item = player.getHeldItem();
if(item != null && item.getItem() != null && item.getItem() instanceof INeedle && canCraft() && hasString(false))
{
if(recipeTier == 0 || ((INeedle)item.getItem()).getTier() >= recipeTier)
{
worldObj.playSound((double)xCoord + 0.5D, (double)yCoord + 0.5D, (double)zCoord + 0.5D, "step.cloth", 1.0F, (worldObj.rand.nextFloat() * 0.1F) + 0.9F, true);
sewProg += ((INeedle)item.getItem()).getEfficiency();
if(!player.capabilities.isCreativeMode)
{
item.damageItem(1, player);
}
}
else
{
worldObj.playSound((double)xCoord + 0.5D, (double)yCoord + 0.5D, (double)zCoord + 0.5D, "step.cloth", 1.0F, (worldObj.rand.nextFloat() * 0.1F) + 0.4F, true);
}
onInventoryChanged();
return true;
}
return false;
}
/**
* checks if there is string to use
* @param consume true if it consumes string false if it is checking
* @return true if there's string to use
*/
private boolean hasString(boolean consume)
{
if(this.reqString <= -1)
{
return true;
}
else
{
for(int a = 0; a < 4; a ++)
{
ItemStack slot = getStackInSlot(a);
if(slot != null)
{
if(StringList.doesMatchTier(slot, reqString))
{
if(consume)
decrStackSize(a, 1);
return true;
}
}
}
}
return false;
}
@Override
public void updateEntity()
{
super.updateEntity();
ticks ++;
if (progress >= (maxProgress))
{
progress = 0;
sewProg = 0.0F;
craft();
}
if(sewProg >= sewTime && sewTime > 0)
{
sewProg -= sewTime;
if(hasString(true))
{
progress ++;
}
}
if (!canCraft() && progress > 0)
{
progress = 0;
}
if(!worldObj.isRemote)
{
if(ticks % 20 == 0)
{
this.syncItems();
}
sendPacketToClients();
}
}
public ItemStack getResult()
{
return recipe;
}
public ItemStack getRecipe()
{
if(ticks <= 1)
return null;
ContainerTailor container = new ContainerTailor(this);
InventoryCrafting craft = new InventoryCrafting(container, 4, 4);
for(int a = 0 ; a < 16 ; a ++)
{
craft.setInventorySlotContents(a, inv[a+4]);
}
return CraftingManagerTailor.getInstance().findMatchingRecipe(this, craft);
}
public boolean canCraft()
{
return getResult() != null && canFitResult();
}
public boolean canFitResult()
{
ItemStack slot = inv[getOutputSlot()];
ItemStack result = getResult();
if(slot == null)return true;
if(result == null)return false;
if(!result.isItemEqual(slot))return false;
int ss = slot.stackSize;
int rs = result.stackSize;
int sm = slot.getMaxStackSize() - ss;
return rs <= sm;
}
private void craft()
{
if(getResult() == null)
return;
ItemStack result = getResult().copy();
if(result != null)
{
if (inv[getOutputSlot()] == null)
{
decreseAll();
this.setInventorySlotContents(getOutputSlot(), result);
}
else if (inv[getOutputSlot()] != null && inv[getOutputSlot()].isItemEqual(result))
{
int c = (inv[getOutputSlot()].stackSize + result.stackSize);
if(c <= inv[getOutputSlot()].getMaxStackSize())
{
decreseAll();
inv[getOutputSlot()].stackSize+= result.stackSize;
}
}
}
this.onInventoryChanged();
}
private void decreseAll()
{
Random rand = new Random();
for (int s = 4; s < getOutputSlot(); s++)
{
this.decrStackSize(s, 1);
}
}
private void sendPacketToClients()
{
if(!worldObj.isRemote)
{
Packet packet = PacketManagerMF.getPacketIntegerArray(this, new int[]{0, progress, maxProgress, direction});
try
{
FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(packet);
} catch(NullPointerException e)
{
System.out.println("MineFantasy: Client connection lost");
}
}
}
private void syncItems()
{
if(!worldObj.isRemote)
{
for(int a = 0; a < inv.length; a ++)
{
Packet packet = PacketManagerMF.getPacketItemStackArray(this, a, inv[a]);
try
{
FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(packet);
} catch(NullPointerException e)
{
System.out.println("MineFantasy: Client connection lost");
return;
}
}
Packet packet2 = PacketManagerMF.getPacketMFResult(this, getResult());
try
{
FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(packet2);
} catch(NullPointerException e)
{
System.out.println("MineFantasy: Client connection lost");
return;
}
}
}
@Override
public void recievePacket(ByteArrayDataInput data)
{
try
{
int id = data.readInt();
if(id == 0)
{
progress = data.readInt();
maxProgress = data.readInt();
direction = data.readInt();
}
if(id == 1)
{
int p = data.readInt();
int i = data.readInt();
int slot = data.readInt();
Entity e = worldObj.getEntityByID(p);
if(e != null && e instanceof EntityPlayer)
{
BlockTailor.useInventory(worldObj, xCoord, yCoord, zCoord, this, (EntityPlayer)e, i, slot);
}
return;
}
} catch (Exception e)
{
System.err.println("MineFantasy: Failed to process packet from Tailor Bench");
}
}
@Override
public void onInventoryChanged()
{
super.onInventoryChanged();
recipe = getRecipe();
syncItems();
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
NBTTagList itemTag = new NBTTagList();
nbt.setInteger("Dir", direction);
nbt.setFloat("Sew", sewProg);
for (int var3 = 0; var3 < this.inv.length; ++var3)
{
if (this.inv[var3] != null)
{
NBTTagCompound var4 = new NBTTagCompound();
var4.setByte("Slot", (byte) var3);
this.inv[var3].writeToNBT(var4);
itemTag.appendTag(var4);
}
}
nbt.setTag("Items", itemTag);
nbt.setInteger("Progress", progress);
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
NBTTagList itemTag = nbt.getTagList("Items");
this.inv = new ItemStack[this.getSizeInventory()];
sewProg = nbt.getFloat("Sew");
for (int var3 = 0; var3 < itemTag.tagCount(); ++var3)
{
NBTTagCompound slot = (NBTTagCompound) itemTag.tagAt(var3);
byte id = slot.getByte("Slot");
if (id >= 0 && id < this.inv.length)
{
this.inv[id] = ItemStack.loadItemStackFromNBT(slot);
}
}
direction = nbt.getInteger("Dir");
this.progress = nbt.getInteger("Progress");
}
//OTHER MECHANICS--------------------------------------------------------------------------------
@Override
public String getInvName()
{
return "Tailor Bench";
}
@Override
public boolean isInvNameLocalized()
{
return true;
}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack)
{
return i < 4 && StringList.isString(itemstack);
}
public int getProgressScale(int width)
{
return this.progress * width / (maxProgress);
}
@Override
public int getSizeInventory()
{
return inv.length;
}
@Override
public ItemStack getStackInSlot(int i)
{
return inv[i];
}
@Override
public ItemStack decrStackSize(int slot, int amount)
{
onInventoryChanged();
if (this.inv[slot] != null)
{
ItemStack result;
if (this.inv[slot].stackSize <= amount)
{
result = this.inv[slot];
this.inv[slot] = null;
onInventoryChanged();
return result;
}
else
{
result = this.inv[slot].splitStack(amount);
if (this.inv[slot].stackSize == 0)
{
this.inv[slot] = null;
}
onInventoryChanged();
return result;
}
}
else
{
onInventoryChanged();
return null;
}
}
@Override
public ItemStack getStackInSlotOnClosing(int slot)
{
if (this.inv[slot] != null)
{
ItemStack var2 = this.inv[slot];
this.inv[slot] = null;
return var2;
}
else
{
return null;
}
}
@Override
public void setInventorySlotContents(int i, ItemStack itemstack)
{
onInventoryChanged();
inv[i] = itemstack;
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer entityplayer)
{
return true;
}
@Override
public void openChest(){}
@Override
public void closeChest(){}
public int getOutputSlot()
{
return getSizeInventory()-1;
}
@Override
public void setStitchCount(int i)
{
maxProgress = i;
}
@Override
public void setString(int str)
{
this.reqString = str;
}
@Override
public void setSewTime(float f)
{
sewTime = f;
}
@Override
public void setTier(int i)
{
recipeTier = i;
}
@SideOnly(Side.CLIENT)
public ItemStack getRenderItem(int i)
{
return inv[i];
}
public int getSlotFor(float x, float y)
{
int[] coord = BlockClickHelper.getCoordsFor(x, y, 0F, 1F, 0F, 1F, 6, 6, direction);
if(coord == null)
{
return -1;
}
if(coord[0] == 1 || coord[1] < 2)
{
return -1;
}
coord[1] -= 2;
if(coord[0] == 0)
{
return coord[1];
}
coord[0] -= 2;
return (coord[1]*4 + coord[0] + 4);
}
public ItemStack getResultSlot()
{
return getStackInSlot(getSizeInventory()-1);
}
@Override
@SideOnly(Side.CLIENT)
public boolean shouldRenderCraftMetre()
{
return canCraft();
}
@Override
@SideOnly(Side.CLIENT)
public int getProgressBar(int i)
{
return this.getProgressScale(i);
}
@Override
@SideOnly(Side.CLIENT)
public String getResultName()
{
if(worldObj.isRemote)
{
return tempResult != null ? tempResult.getDisplayName() : "";
}
return "";
}
@Override
@SideOnly(Side.CLIENT)
public void setTempResult(ItemStack item)
{
tempResult = item;
}
}