package minefantasy.block.tileentity;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import minefantasy.api.aesthetic.IChimney;
import minefantasy.api.anvil.ITongs;
import minefantasy.api.cooking.IHeatSource;
import minefantasy.api.forge.IBellowsUseable;
import minefantasy.api.forge.ItemHandler;
import minefantasy.api.forge.TongsHelper;
import minefantasy.api.refine.Alloy;
import minefantasy.api.refine.AlloyRecipes;
import minefantasy.api.refine.BloomRecipe;
import minefantasy.block.BlockChimney;
import minefantasy.block.BlockListMF;
import minefantasy.item.ItemBloom;
import minefantasy.item.ItemListMF;
import minefantasy.item.tool.ItemTongs;
import minefantasy.system.cfg;
import minefantasy.system.network.PacketManagerMF;
import minefantasy.system.network.PacketUserMF;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.packet.Packet;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.oredict.OreDictionary;
import com.google.common.io.ByteArrayDataInput;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.common.registry.GameRegistry;
public class TileEntitySmelter extends TileEntity implements IBellowsUseable, IInventory, ISidedInventory,
PacketUserMF
{
private ItemStack inv[];
public int fuel;
public int maxFuel;
public int progress;
public int direction;
public int itemMetadata;
private int lastTemp = 0;
private int ticksExisted;
public int maxTime = 400;
private int bellows;
private static List<ItemStack>allowedSmelts = getAllowedSmelts();
/**
* weather the model displays a hot ingot(CLIENT SYNC)
*/
public boolean showIngot;
public TileEntitySmelter() {
inv = new ItemStack[18];
fuel = 0;
maxFuel = 0;
progress = 0;
}
public TileEntitySmelter(int metadata)
{
this();
itemMetadata = metadata;
}
public int getSizeInventory() {
return inv.length;
}
public ItemStack getStackInSlot(int i) {
return inv[i];
}
public ItemStack decrStackSize(int i, int j)
{
if (inv[i] != null)
{
if (inv[i].stackSize <= j)
{
ItemStack itemstack = inv[i];
inv[i] = null;
return itemstack;
}
ItemStack itemstack1 = inv[i].splitStack(j);
if (inv[i].stackSize == 0)
{
inv[i] = null;
}
return itemstack1;
} else
{
return null;
}
}
public void setInventorySlotContents(int i, ItemStack itemstack) {
inv[i] = itemstack;
if (itemstack != null && itemstack.stackSize > getInventoryStackLimit()) {
itemstack.stackSize = getInventoryStackLimit();
}
}
public String getInvName() {
return "Bloomery";
}
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
NBTTagList nbttaglist = nbt.getTagList("Items");
inv = new ItemStack[getSizeInventory()];
for (int i = 0; i < nbttaglist.tagCount(); i++) {
NBTTagCompound nbttagcompound1 = (NBTTagCompound) nbttaglist
.tagAt(i);
byte byte0 = nbttagcompound1.getByte("Slot");
if (byte0 >= 0 && byte0 < inv.length) {
inv[byte0] = ItemStack
.loadItemStackFromNBT(nbttagcompound1);
}
}
lastTemp = nbt.getInteger("LastTemp");
bellows = nbt.getInteger("bellows");
maxTime = nbt.getInteger("maxTime");
fuel = nbt.getInteger("BurnTime");
direction = nbt.getInteger("Dir");
progress = nbt.getInteger("CookTime");
maxFuel = getItemBurnTime(inv[0]);
}
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
nbt.setInteger("LastTemp", lastTemp);
nbt.setInteger("BurnTime", fuel);
nbt.setInteger("Dir", direction);
nbt.setInteger("bellows", bellows);
nbt.setInteger("CookTime", progress);
nbt.setInteger("maxTime", maxTime);
NBTTagList nbttaglist = new NBTTagList();
for (int i = 0; i < inv.length; i++) {
if (inv[i] != null) {
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
nbttagcompound1.setByte("Slot", (byte) i);
inv[i].writeToNBT(nbttagcompound1);
nbttaglist.appendTag(nbttagcompound1);
}
}
nbt.setTag("Items", nbttaglist);
}
public int getInventoryStackLimit() {
return 64;
}
public int getCookProgressScaled(int i) {
return (progress * i) / maxTime;
}
public int getBurnTimeRemainingScaled(int i) {
if (maxFuel == 0) {
maxFuel = maxTime;
}
return (fuel * i) / maxFuel;
}
public boolean isBurning() {
if(getTier() == 0)
{
return fuel > 0;
}
if(worldObj != null && worldObj.isRemote)
{
return showIngot;
}
return getHeatSource() > 0 && getRecipe() != null;
}
public void updateEntity()
{
if(!worldObj.isRemote)
showIngot = getTier() == 0 ? hasSmelted() : isBurning();
if(bellows > 0)bellows --;
if(getTier() >= 1)
{
int time = 400;
for(int a = 1; a < getSizeInventory()-1; a ++)
{
if(inv[a] != null)
{
time += 50;
}
}
if(!worldObj.isRemote)
maxTime = time;
}
else
{
maxTime = BloomRecipe.getTime(inv[1]);
}
boolean flag = fuel > 0;
boolean flag1 = false;
boolean flag2 = isBurning();
if (getTier() == 0 && fuel > 0)
{
fuel -= 2;
}
if (!worldObj.isRemote)
{
++ticksExisted;
if(getTier() > 0 && ticksExisted % 20 == 0)
{
this.lastTemp = getTemperature();
}
if (getTier() == 0 && fuel <= 0 && canSmelt())
{
maxFuel = fuel = getItemBurnTime(inv[0]);
if (fuel > 0)
{
flag1 = true;
if (inv[0] != null)
{
if(inv[0].getItem().hasContainerItem())
{
inv[0] = inv[0].getItem().getContainerItemStack(inv[0]);
}
else
{
inv[0].stackSize--;
if (inv[0].stackSize == 0)
{
inv[0] = null;
}
}
}
}
}
if (isBurning() && canSmelt() && (getTier() > 0 || fuel > 0)) {
progress += getHeatSource();
if (progress >= maxTime) {
progress = 0;
smeltItem();
flag1 = true;
}
} else {
progress = 0;
}
}
if (flag1) {
onInventoryChanged();
}
if (this.isBurning())
{
int x = (int) xCoord;
int y = (int) yCoord;
int z = (int) zCoord;
Random rand = new Random();
if (!worldObj.isBlockSolidOnSide(x, y + 1, z, ForgeDirection.DOWN))
worldObj.spawnParticle("largesmoke", x + 0.5F, y, z + 0.5F, 0,
0.065F, 0);
}
if(!worldObj.isRemote)
{
int off = getOffMetadata();
int on = getOnMetadata();
boolean update = false;
if(isBurning() && worldObj.getBlockMetadata(xCoord, yCoord, zCoord) != on)
{
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, on, 3);
worldObj.updateAllLightTypes(xCoord, yCoord, zCoord);
update=true;
}
if(!isBurning() && worldObj.getBlockMetadata(xCoord, yCoord, zCoord) != off)
{
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, off, 3);
worldObj.updateAllLightTypes(xCoord, yCoord, zCoord);
update=true;
}
if(getTier() > 0 && update)
{
this.lastTemp = getTemperature();
}
}
if(this.isBurning())
{
puffSmoke(new Random(), worldObj, xCoord, yCoord, zCoord);
}
sendPacketToClients();
}
public void puffSmoke(Random rand, World world, int x, int y, int z)
{
if(getTier() >= 1)
{
if(rand.nextInt(10) == 0)
{
world.spawnParticle("smoke", x+0.5F, y+1, z+0.5F, (rand.nextFloat()-0.5F)/6, 0.065F, (rand.nextFloat()-0.5F)/6);
}
return;
}
Block block = Block.blocksList[world.getBlockId(x, y+1, z)];
IChimney chimney = null;
if(block instanceof IChimney)
chimney = (IChimney)block;
if(chimney == null
|| (chimney != null && !chimney.puffSmoke(world, x, y+1, z, (float)1/6, 1, 1)))
{
for(int a = 0; a < 5 ; a ++)
{
world.spawnParticle("largesmoke", x+0.5F, y+1, z+0.5F, (rand.nextFloat()-0.5F)/6, 0.065F, (rand.nextFloat()-0.5F)/6);
}
}
}
private boolean canSmelt() {
if(getTier() >= 1 && worldObj != null)
{
if(getHeatSource() <= 0)return false;
}
ItemStack result = getRecipe();
if (result == null)
return false;
if (inv[getOutSlot()] == null)
return true;
if (inv[getOutSlot()] != null
&& inv[getOutSlot()].isItemEqual(result)
&& inv[getOutSlot()].stackSize < (inv[getOutSlot()]
.getMaxStackSize() - (result.stackSize - 1)))
return true;
return false;
}
private int getHeatSource()
{
if(getTier() == 0)
{
if(bellows > 0)
{
return 3;
}
return 1;
}
return (int)Math.floor(lastTemp/250F);
}
public int getTemperature()
{
if(worldObj == null)
{
return 0;
}
Material mat = worldObj.getBlockMaterial(xCoord, yCoord-1, zCoord);
if(mat != null)
{
if(mat == Material.fire)
{
return 200;
}
if(mat == Material.lava)
{
return 1000;
}
}
TileEntity tile = worldObj.getBlockTileEntity(xCoord, yCoord-1, zCoord);
if(tile != null)
{
if(tile instanceof IHeatSource)
{
return ((IHeatSource)tile).getHeat();
}
}
return 0;
}
/**
* @return If the output is occupied(SERVER) and if told by packet sync(CLIENT)
*/
public boolean hasSmelted()
{
if(worldObj == null)return false;
if(worldObj.isRemote)
{
return showIngot;
}
return inv[getOutSlot()] != null;
}
public int getOutSlot()
{
return getSizeInventory()-1;
}
public void smeltItem() {
if (!canSmelt())
{
return;
}
ItemStack itemstack = getRecipe();
if (inv[getOutSlot()] == null)
{
inv[getOutSlot()] = itemstack.copy();
}
else if (inv[getOutSlot()].itemID == itemstack.itemID)
{
inv[getOutSlot()].stackSize += itemstack.stackSize;
}
for(int a = 1; a < (getSizeInventory()-1); a ++)
{
if (inv[a] != null)
{
inv[a].stackSize--;
if (inv[a].stackSize <= 0) {
inv[a] = null;
}
}
}
}
private boolean isWrought(ItemStack itemstack)
{
if(itemstack == null)
{
return false;
}
return itemstack.isItemEqual(ItemListMF.component(ItemListMF.ingotWroughtIron));
}
public int getItemBurnTime(ItemStack itemstack) {
if (itemstack == null) {
return 0;
}
if(getTier() == 0)
{
return (int)((float)TileEntityFurnace.getItemBurnTime(itemstack));
}
return TileEntityFurnace.getItemBurnTime(itemstack)/4;
}
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
if (worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) != this) {
return false;
}
return entityplayer.getDistanceSq((double) xCoord + 0.5D,
(double) yCoord + 0.5D, (double) zCoord + 0.5D) <= 64D;
}
public void openChest() {
}
public void closeChest() {
}
@Override
public ItemStack getStackInSlotOnClosing(int var1) {
return null;
}
private ItemStack getRecipe() {
if(getTier() == 0)
{
if(getResult(inv[1]) != null)
{
return ItemHandler.isCarbon(inv[2]) ? getResult(inv[1]) : null;
}
else
return null;
}
if(getTier() == 1)
{
ItemStack[] input = new ItemStack[getSizeInventory()-2];
for(int a = 1; a < 10; a ++)
{
input[a-1] = inv[a];
}
Alloy alloy = AlloyRecipes.getResult(input);
if(alloy != null)
{
if(alloy.getLevel() <= 0)
{
return AlloyRecipes.getResult(input).getRecipeOutput();
}
}
}
if(getTier() == 2)
{
ItemStack[] input = new ItemStack[getSizeInventory()-2];
for(int a = 1; a < 17; a ++)
{
input[a-1] = inv[a];
}
Alloy alloy = AlloyRecipes.getResult(input);
if(alloy != null)
{
if(alloy.getLevel() <= 1)
{
return AlloyRecipes.getResult(input).getRecipeOutput();
}
}
}
return null;
}
private ItemStack getResult(ItemStack itemStack) {
if(BloomRecipe.getResult(itemStack) != null)
{
return BloomRecipe.getResult(itemStack);
}
ItemStack furnaceRec = FurnaceRecipes.smelting().getSmeltingResult(itemStack);
if(furnaceRec != null && this.canAcceptOut(furnaceRec))
{
if(cfg.easyBlooms)
{
return furnaceRec;
}
return ItemBloom.createBloom(furnaceRec);
}
return null;
}
private boolean canAcceptOut(ItemStack result) {
if(result == null)
{
return false;
}
ItemStack result2 = result;
if(result.itemID == ItemListMF.bloom.itemID)
{
result2 = ItemBloom.getItem(result);
}
for(ItemStack compare : allowedSmelts)
{
if(compare.isItemEqual(result2))
{
return true;
}
if(compare.itemID == result2.itemID && compare.getItemDamage() == OreDictionary.WILDCARD_VALUE)
{
return true;
}
}
return false;
}
private void sendPacketToClients() {
if (!worldObj.isRemote) {
try {
boolean display = hasSmelted();
if(getTier() > 0)
{
display = isBurning();
}
Packet packet = PacketManagerMF.getPacketIntegerArray(this,
new int[] { fuel, maxFuel,
progress, direction, showIngot ? 1 : 0, maxTime, lastTemp});
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
@Deprecated
private void sendPacketToServer() {
if (worldObj.isRemote) {
try {
Packet packet = PacketManagerMF.getPacketIntegerArray(this,
new int[] { fuel, maxFuel,
progress, direction });
PacketDispatcher.sendPacketToServer(packet);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
@Override
public void recievePacket(ByteArrayDataInput data) {
fuel = data.readInt();
maxFuel = data.readInt();
progress = data.readInt();
direction = data.readInt();
int smelt = data.readInt();
showIngot = smelt == 1;
maxTime = data.readInt();
lastTemp = data.readInt();
}
public int getBlockMetadata()
{
if(worldObj == null)
return itemMetadata*2;
if (this.blockMetadata == -1)
{
this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord);
}
return this.blockMetadata;
}
public int getTier()
{
int meta = getBlockMetadata();
return (int)Math.floor(meta/2);
}
private int getOnMetadata()
{
return getTier()*2 + 1;
}
private int getOffMetadata()
{
return getTier()*2;
}
@Override
public boolean isInvNameLocalized() {
return true;
}
public boolean canPutInFuel(ItemStack itemstack) {
if(itemstack == null)return false;
if(this.getItemBurnTime(itemstack) <= 0)
return false;
ItemStack fs = getStackInSlot(1);
if(fs != null)
{
if(!fs.isItemEqual(itemstack))
return false;
else
{
if(fs.stackSize >= fs.getMaxStackSize())return false;
}
}
return true;
}
@Override
public int[] getAccessibleSlotsFromSide(int side) {
if(getTier() == 0)
{
if(side == 1)//TOP
{
return new int[]{2, 1};
}
if(side == 0)//BOTTOM
{
return new int[]{getOutSlot(), 0};
}
return new int[]{0};
}
return new int[]{0, getOutSlot()};
}
private int getFrontSide()
{
switch(direction)
{
case 0:
return 2;
case 1:
return 3;
case 2:
return 4;
case 3:
return 5;
}
return 2;
}
private int getLeftSide()
{
switch(direction)
{
case 0:
return 5;
case 1:
return 2;
case 2:
return 3;
case 3:
return 4;
}
return 2;
}
private int getRightSide()
{
switch(direction)
{
case 0:
return 4;
case 1:
return 5;
case 2:
return 2;
case 3:
return 3;
}
return 2;
}
@Override
public boolean canInsertItem(int i, ItemStack itemstack, int j) {
if(j == 0)
{
return false;
}
if(this.getTier() == 0)
{
return this.isItemValidForSlot(i, itemstack);
}
if(i == 0)
{
return this.canPutInFuel(itemstack);
}
return false;
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack item)
{
if(slot == 0)
{
return isItemFuel(item);
}
if(slot == 1)
{
return true;
}
if(slot == 2)
{
return ItemHandler.isCarbon(item);
}
return false;
}
private boolean isItemFuel(ItemStack item) {
return this.getItemBurnTime(item) > 0;
}
@Override
public boolean canExtractItem(int i, ItemStack itemstack, int j) {
if(this.getTier() == 0)
{
if(i == 0)
{
if(!isItemFuel(itemstack))
{
return true;
}
}
if(i == 3)
{
return true;
}
}
return i == getOutSlot() && !isItemFuel(itemstack);
}
public boolean goesInCarbon(ItemStack itemSlot) {
if(ItemHandler.isCarbon(itemSlot))
{
if(getItemBurnTime(itemSlot)> 0)
{
if(getResult(inv[1]) == null)
{
return false;
}
}
return true;
}
return false;
}
public boolean goesInFuel(ItemStack itemSlot) {
if(ItemHandler.isCarbon(itemSlot))
{
if(getResult(inv[1]) != null)
{
return false;
}
}
return getItemBurnTime(itemSlot)> 0;
}
private static List<ItemStack> getAllowedSmelts() {
List list = new ArrayList();
list.add(new ItemStack(Item.ingotGold));
list = addOresIng("Copper", list);
list = addOresIng("Tin", list);
list = addOresIng("Bronze", list);
list = addOresIng("Iron", list);
list = addOresIng("Gold", list);
list = addOresIng("Silver", list);
list = addOresIng("RefinedIron", list);
list = addOresIng("Zinc", list);
list = addOresIng("Nickel", list);
list = addOresIng("Tungsten", list);
list = addOresIng("Bismuth", list);
list = addOresIng("Lead", list);
list = addOresIng("Steel", list);
list = addOresIng("Mithril", list);
return list;
}
private static List addOresIng(String ores, List list) {
return addOres("ingot"+ores, list);
}
private static List addOres(String ores, List list) {
for(ItemStack ore: OreDictionary.getOres(ores))
{
list.add(ore);
}
return list;
}
public boolean tryTakeItem(EntityPlayer player)
{
if(getTier() != 0)return false;
if(player == null)
{
return false;
}
if(player.getHeldItem() != null && player.getHeldItem().getItem() instanceof ITongs)
{
ItemStack tongs = player.getHeldItem();
if(TongsHelper.getHeldItem(tongs) == null)
{
int s = getOutSlot();
ItemStack slot = inv[s];
if(slot != null)
{
if(TongsHelper.trySetHeldItem(tongs, slot))
{
if(!player.worldObj.isRemote)
{
System.out.println("Pickup");
}
decrStackSize(s, 1);
return true;
}
}
}
}
return false;
}
public ItemStack getResultSlot() {
return inv[getOutSlot()];
}
@Override
public void onUsedWithBellows(float powerLevel)
{
bellows = (int)(20F*powerLevel);
}
public int getHeatScaled(int height)
{
if(lastTemp <= 0)return 0;
return lastTemp * height / ItemHandler.forgeMaxTemp;
}
public boolean willShowBase()
{
if(worldObj == null)
{
return false;
}
if(this.getTier() == 0)
{
return false;
}
if(worldObj.getBlockMaterial(xCoord, yCoord-1, zCoord) != null && worldObj.getBlockMaterial(xCoord, yCoord-1, zCoord) == Material.fire)
{
return true;
}
if(worldObj.getBlockMaterial(xCoord, yCoord-1, zCoord) != null && worldObj.getBlockMaterial(xCoord, yCoord-1, zCoord) == Material.lava)
{
return true;
}
TileEntity tile = worldObj.getBlockTileEntity(xCoord, yCoord-1, zCoord);
if(tile == null)
{
return false;
}
if(tile instanceof IHeatSource)
{
return ((IHeatSource)tile).canPlaceAbove();
}
if(tile instanceof TileEntityForge)
{
return true;
}
return false;
}
}