package minefantasy.block.tileentity;
import java.util.Random;
import minefantasy.MineFantasyBase;
import minefantasy.api.aesthetic.IChimney;
import minefantasy.api.forge.IBellowsUseable;
import minefantasy.api.forge.ItemHandler;
import minefantasy.api.refine.BlastRecipes;
import minefantasy.block.BlockChimney;
import minefantasy.block.BlockListMF;
import minefantasy.item.ItemListMF;
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.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemHoe;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.ItemTool;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.packet.Packet;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.ForgeDirection;
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;
public class TileEntityBFurnace extends TileEntity
implements IInventory, PacketUserMF, ISidedInventory, IBellowsUseable{
public byte direction;
private ItemStack[] inventory;
public int fuel;
public int maxFuel;
public int cookTime;
public static int requiredTime = 500;
public int ticksExisted;
public int heat;
public static int requiredHeat = 2400;
public boolean canCook;
private boolean isBuilt;
private int bellowsBonus;
private final ItemStack slag = ItemListMF.component(ItemListMF.slag, 1);
public TileEntityBFurnace()
{
inventory = new ItemStack[3];
}
public void updateFurnace()
{
if(!this.furnaceExists())
{
fuel = maxFuel = cookTime = 0;
return;
}
if(getFuelBlock() != null)
{
getFuelBlock().canCook = canCook();
}
boolean var1 = this.fuel > 0;
boolean var2 = false;
if (this.fuel > 0)
{
--this.fuel;
}
if (!this.worldObj.isRemote)
{
if(this.getFuelBlock() != null)
if (this.fuel == 0 && this.getFuelBlock().canRefuel())
{
this.maxFuel = this.fuel = getItemBurnTime(getFuelSlot());
if (this.fuel > 0)
{
var2 = true;
this.getFuelBlock().decrStackSize(0, 1);
}
}
if (this.isBurning() && this.canSmelt())
{
++this.cookTime;
if(getFuelBlock() != null && getFuelBlock().bellowsBonus > 0)
{
cookTime += 2;
}
if (this.cookTime >= requiredTime)
{
this.cookTime = 0;
this.smeltItem();
var2 = true;
}
}
else
{
this.cookTime = 0;
}
if (var1 != this.fuel > 0)
{
var2 = true;
}
}
if (var2)
{
this.onInventoryChanged();
}
if(getFuelBlock() != null)
{
this.getFuelBlock().fuel = this.fuel;
this.getFuelBlock().maxFuel = this.maxFuel;
}
if(isBurning() && ticksExisted % 5 == 0)
{
puffSmoke(3);
}
}
private boolean canSmelt()
{
int h = 0;
if(getFuelBlock() != null)
{
h = getFuelBlock().heat;
}
return canCook() && h >= requiredHeat;
}
private boolean canRefuel()
{
if(this.blockMetadata == 2)
{
if(worldObj.isBlockIndirectlyGettingPowered((int)xCoord, (int)yCoord, (int)zCoord))
return false;
}
return true;
}
private boolean canCook()
{
if (this.inventory[0] == null || this.inventory[1] == null || this.inventory[2] == null)
{
return false;
}
else
if(!isCoal(0) || !isLimestone(1))
{
return false;
}
else
{
ItemStack var1 = BlastRecipes.getResult(this.inventory[2]);
if (var1 == null) return false;
if (this.getResultSlot() == null) return true;
if (!this.getResultSlot().isItemEqual(var1)) return false;
int result = getResultSlot().stackSize + var1.stackSize;
return canFitSlag() && (result <= getInventoryStackLimit() && result <= var1.getMaxStackSize());
}
}
private boolean canFitSlag()
{
if (this.getSlagSlot() == null) return true;
if (!this.getSlagSlot().isItemEqual(slag)) return false;
int result = getSlagSlot().stackSize + slag.stackSize;
return (result <= 64);
}
private boolean isLimestone(int i) {
return ItemHandler.isFlux(inventory[i]);
}
private boolean isCoal(int i) {
return ItemHandler.isCarbon(inventory[i]);
}
public void smeltItem()
{
if (this.canSmelt())
{
ItemStack var1 = BlastRecipes.getResult(this.inventory[2]);
if (this.getResultSlot() == null)
{
this.setResult(var1.copy());
}
else if (this.getResultSlot().isItemEqual(var1))
{
this.getResultBlock().incrStackSize(0, var1.stackSize);
}
if (this.getSlagSlot() == null)
{
this.setSlag(slag.copy());
}
else if (this.getSlagSlot().isItemEqual(slag))
{
this.getResultBlock().incrStackSize(1, slag.stackSize);
}
for(int a = 0; a < 3; a ++)
{
--this.inventory[a].stackSize;
if (this.inventory[a].stackSize <= 0)
{
this.inventory[a] = null;
}
}
}
}
public static int getItemBurnTime(ItemStack stack)
{
if (stack == null)
{
return 0;
}
else
{
if(ItemHandler.getBlastFuel(stack) > 0)
{
return (int)ItemHandler.getBlastFuel(stack)*requiredTime;
}
return 0;
}
}
/**
* Applies the update for the Fuel Block
*/
public void updateFuel()
{
if(worldObj.isRemote)
{
return;
}
if(getInput() != null)
{
if(fuel > 0 && heat < requiredHeat)
{
heat += 4;
if(bellowsBonus > 0)heat += 2;
fuel -= 5;
}
if(fuel <= 0)
{
if(heat > 0) heat -= 2;
if(heat < 0) heat = 0;
}
}
else
{
if(heat > 0) heat -= 10;
if(heat < 0) heat = 0;
}
//if(heat < 0)heat = 0;
}
public void setFuelStack(ItemStack item)
{
if(this.hasFuelBlock())
{
getFuelBlock().setInventorySlotContents(0, item);
}
}
@SideOnly(Side.CLIENT)
/**
* Returns an integer between 0 and the passed value representing how close the current item is to being completely
* cooked
*/
public int getCookProgressScaled(int width)
{
return this.cookTime * width / requiredTime;
}
@SideOnly(Side.CLIENT)
public int getHeatProgressScaled(int width)
{
return this.heat * width / requiredHeat;
}
@SideOnly(Side.CLIENT)
/**
* Returns an integer between 0 and the passed value representing how much burn time is left on the current fuel
* item, where 0 means that the item is exhausted and the passed value means that the item is fresh
*/
public int getBurnTimeRemainingScaled(int height)
{
if(fuel <= 0)return 0;
if (this.maxFuel == 0)
{
this.maxFuel = 200;
}
return this.fuel * height / this.maxFuel;
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
bellowsBonus = nbt.getInteger("Bellows");
ticksExisted = nbt.getInteger("Time");
heat = nbt.getInteger("heat");
direction = nbt.getByte("Facing");
fuel = nbt.getInteger("Fuel");
maxFuel = nbt.getInteger("MFuel");
cookTime = nbt.getInteger("Cook");
isBuilt = nbt.getBoolean("Build");
NBTTagList var2 = nbt.getTagList("Items");
this.inventory = new ItemStack[3];
for (int var3 = 0; var3 < var2.tagCount(); ++var3)
{
NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
byte var5 = var4.getByte("Slot");
if (var5 >= 0 && var5 < this.inventory.length)
{
this.inventory[var5] = ItemStack.loadItemStackFromNBT(var4);
}
}
if(nbt.hasKey("CustomName"))
{
customName = nbt.getString("CustomName");
}
}
@Override
public void updateEntity()
{
ticksExisted ++;
if(bellowsBonus > 0)bellowsBonus --;
if(ticksExisted % 10 == 0)
{
isBuilt = structureExists();
}
boolean wasBurning = isBurning();
super.updateEntity();
if(blockMetadata == 2 && furnaceExists())
{
updateFuel();
}
if(blockMetadata == 1 && furnaceExists())
updateFurnace();
if(!furnaceExists())
{
fuel = maxFuel = cookTime = 0;
}
this.sendPacketToClients();
if(ticksExisted % 20 == 0 || wasBurning != isBurning())
{
onSecondUpdate();
}
}
/**
* @return 0 = shaft, 1 = furnace 2 = fuel 3 = out
*/
public int getType()
{
return worldObj.getBlockMetadata(xCoord, yCoord, zCoord);
}
/**
* Is Called every second. or when status is updated
*/
private void onSecondUpdate() {
worldObj.updateAllLightTypes(xCoord, yCoord, zCoord);
int radius = 10;
int height = 10;
for(int a = -radius; a <= radius; a ++)
{
for(int b = -height; b <= height; b ++)
{
for(int c = -radius; c <= radius; c ++)
{
Random rand = new Random();
if(rand .nextInt(30) == 0 && canCutSnow(a, b, c, radius))
{
Material mat = worldObj.getBlockMaterial((int)xCoord + a, (int)yCoord + b, (int)zCoord + c);
if(mat != null && mat == Material.snow)
{
worldObj.setBlock((int)xCoord + a, (int)yCoord + b, (int)zCoord + c, 0);
}
}
}
}
}
}
private boolean canCutSnow(int a, int b, int c, int r) {
if(!isBurning())
return false;
if(this.getDistanceFromPos(a, yCoord, c) > r)
return false;
return true;
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
nbt.setInteger("Bellows", bellowsBonus);
nbt.setInteger("heat", heat);
nbt.setInteger("Time", ticksExisted);
nbt.setByte("Facing", direction);
nbt.setInteger("Fuel", fuel);
nbt.setInteger("MFuel", maxFuel);
nbt.setInteger("Cook", cookTime);
nbt.setBoolean("Build", isBuilt);
NBTTagList var2 = new NBTTagList();
for (int var3 = 0; var3 < this.inventory.length; ++var3)
{
if (this.inventory[var3] != null)
{
NBTTagCompound var4 = new NBTTagCompound();
var4.setByte("Slot", (byte)var3);
this.inventory[var3].writeToNBT(var4);
var2.appendTag(var4);
}
}
nbt.setTag("Items", var2);
if(isInvNameLocalized())
{
nbt.setString("CustomName", customName);
}
}
public TileEntityBFurnace getFuelBlock()
{
int stepDown = 5;
if(worldObj.getBlockMetadata(xCoord, yCoord-stepDown, zCoord) != 2)
return null;
return getBFurnAt(xCoord, yCoord-stepDown, zCoord);
}
public TileEntityBFurnace getInput()
{
int stepUp = 5;
if(worldObj.getBlockMetadata(xCoord, yCoord+stepUp, zCoord) != 1)
return null;
return getBFurnAt(xCoord, yCoord+stepUp, zCoord);
}
public TileEntityBFurnace getResultBlock()
{
TileEntityBFurnace r = null;
int stepDown = 6;
r = getBFurnAt(xCoord-2, yCoord-stepDown, zCoord);
if(r != null && worldObj.getBlockMetadata(xCoord-2, yCoord-stepDown, zCoord) == 3)
return r;
r = getBFurnAt(xCoord+2,yCoord-stepDown, zCoord);
if(r != null && worldObj.getBlockMetadata(xCoord+2, yCoord-stepDown, zCoord) == 3)
return r;
r = getBFurnAt(xCoord, yCoord-stepDown, zCoord-2);
if(r != null && worldObj.getBlockMetadata(xCoord, yCoord-stepDown, zCoord-2) == 3)
return r;
r = getBFurnAt(xCoord, yCoord-stepDown, zCoord+2);
if(r != null && worldObj.getBlockMetadata(xCoord, yCoord-stepDown, zCoord+2) == 3)
return r;
return null;
}
public boolean hasFuelBlock()
{
return getFuelBlock() != null;
}
public boolean hasResultBlock()
{
return getResultBlock() != null;
}
public boolean furnaceExists()
{
return isBuilt;
}
public boolean structureExists() {
if(blockMetadata != 1)
return true;
if(this.hasFuelBlock())
;//System.out.println("Has Fuel");
else
return false;
if(this.hasResultBlock())
;//System.out.println("Has Output");
else
return false;
if(!isChamberBlock(xCoord, yCoord+1, zCoord))
return false;
if(!isChamberBlock(xCoord, yCoord+2, zCoord))
return false;
if(!isChamberBlock(xCoord, yCoord-1, zCoord))
return false;
if(!isChamberBlock(xCoord, yCoord-2, zCoord))
return false;
if(!isChamberBlock(xCoord, yCoord-3, zCoord))
return false;
if(!isChamberBlock(xCoord, yCoord-4, zCoord))
return false;
for(int x = -1; x < 2; x ++)
{
for(int z = -1; z < 2; z ++)
{
int id = Block.stoneBrick.blockID;
if(x == 0 && z == 0)
id = Block.lavaStill.blockID;
if(worldObj.getBlockId(xCoord+x, yCoord-6, zCoord+z) != id)
{
return false;
}
}
}
for(int x = -1; x < 2; x ++)
{
for(int z = -1; z < 2; z ++)
{
if(worldObj.getBlockId(xCoord+x, yCoord-7, zCoord+z) != Block.stoneBrick.blockID)
{
return false;
}
}
}
return worldObj.canBlockSeeTheSky(xCoord, yCoord+3, zCoord);
}
public int getFuel()
{
if(!hasFuelBlock())
return 0;
else
return getFuelBlock().fuel;
}
public ItemStack getFuelSlot()
{
if(!hasFuelBlock())
return null;
else
return getFuelBlock().getStackInSlot(0);
}
public ItemStack getResultSlot()
{
if(!hasResultBlock())
return null;
else
return getResultBlock().getStackInSlot(0);
}
public ItemStack getSlagSlot()
{
if(!hasResultBlock())
return null;
else
return getResultBlock().getStackInSlot(1);
}
public boolean interact(EntityPlayer player)
{
if(blockMetadata != 0)
player.openGui(MineFantasyBase.instance, 7, worldObj, xCoord, yCoord, zCoord);
return true;
}
public String getTexture()
{
switch(getBlockMetadata())
{
case 1:
return "in";
case 2:
return "fuel";
case 3:
return "out";
}
return "";
}
private boolean isChamberBlock(int x, int y, int z) {
if(worldObj.getBlockMaterial(x+1, y, z) != Material.rock)return false;
if(worldObj.getBlockMaterial(x-1, y, z) != Material.rock)return false;
if(worldObj.getBlockMaterial(x, y, z+1) != Material.rock)return false;
if(worldObj.getBlockMaterial(x, y, z-1) != Material.rock)return false;
return worldObj.getBlockId(x, y, z) == BlockListMF.Blast.blockID && worldObj.getBlockMetadata(x, y, z) == 0;
}
public String getDefaultName() {
switch(getBlockMetadata())
{
case 1:
return "container.blastfurn";
case 2:
return "container.blastfurn.fuel";
case 3:
return "container.blastfurn.out";
}
return "";
}
@Override
public int getInventoryStackLimit() {
return 64;
}
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
if (getBFurnAt(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() {
}
private void sendPacketToClients() {
if (!worldObj.isRemote) {
try {
Packet packet = PacketManagerMF.getPacketIntegerArray(this,
new int[] { fuel, maxFuel,
cookTime, direction, heat });
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
public void setResult(ItemStack item)
{
if(hasResultBlock())
{
getResultBlock().setInventorySlotContents(0, item);
}
}
public void setSlag(ItemStack item)
{
if(hasResultBlock())
{
getResultBlock().setInventorySlotContents(1, item);
}
}
@Override
public void recievePacket(ByteArrayDataInput data) {
fuel = data.readInt();
maxFuel = data.readInt();
cookTime = data.readInt();
direction = (byte)data.readInt();
heat = data.readInt();
}
public boolean isBurning() {
if(this.getBlockMetadata() == 2)
{
return heat > 0;
}
if(this.getBlockMetadata() == 1)
{
if(getFuelBlock() != null)
{
return getFuelBlock().heat > 0;
}
}
if(blockMetadata == 1)return fuel > 0;
TileEntityBFurnace furn = getBFurnAt(xCoord, yCoord+4, zCoord);
if(furn != null)
{
return furn.isBurning();
}
return false;
}
public int getSizeInventory() {
return inventory.length;
}
public ItemStack getStackInSlot(int i) {
return inventory[i];
}
public ItemStack decrStackSize(int i, int j) {
if(inventory[i] != null && inventory[i].getItem() != null)
{
if(inventory[i].getItem().hasContainerItem())
{
inventory[i] = inventory[i].getItem().getContainerItemStack(inventory[i]);
return inventory[i];
}
}
if (inventory[i] != null) {
if (inventory[i].stackSize <= j) {
ItemStack itemstack = inventory[i];
inventory[i] = null;
return itemstack;
}
ItemStack itemstack1 = inventory[i].splitStack(j);
if (inventory[i].stackSize == 0) {
inventory[i] = null;
}
return itemstack1;
} else {
return null;
}
}
public void setInventorySlotContents(int i, ItemStack itemstack) {
inventory[i] = itemstack;
if (itemstack != null && itemstack.stackSize > getInventoryStackLimit()) {
itemstack.stackSize = getInventoryStackLimit();
}
}
public void incrStackSize(int slot, int num)
{
inventory[slot].stackSize += num;
}
@Override
public ItemStack getStackInSlotOnClosing(int var1) {
return null;
}
public void puffSmoke(int height)
{
Random rand = new Random();
float dense = getSmokeDensity();
IChimney chimney = (IChimney)Block.blocksList[worldObj.getBlockId(xCoord, yCoord+1, zCoord)];
if(chimney == null
|| (chimney != null && !chimney.puffSmoke(worldObj, xCoord, yCoord+1, zCoord, (float)1/2*dense, 1, 1*height)))
{
worldObj.spawnParticle("largesmoke", xCoord+0.5F, yCoord+1, zCoord+0.5F, (rand.nextFloat()-0.5F)/2 * dense, 0.065F, (rand.nextFloat()-0.5F)/2 * height);
}
}
private float getSmokeDensity() {
float sc = 1.0F;
if(getFuelBlock() != null)
{
sc = getFuelBlock().getTempEmitions();
}
return 1.0F * sc;
}
private TileEntityBFurnace getBFurnAt(int x, int y, int z) {
TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
if(tile == null)
return null;
if(tile instanceof TileEntityBFurnace)
return (TileEntityBFurnace)tile;
return null;
}
public float getTempEmitions()
{
if(requiredHeat <= 0)requiredHeat = 1;
return heat / requiredHeat;
}
public ForgeDirection getFacing()
{
switch(direction)
{
case 2:
return ForgeDirection.NORTH;
case 3:
return ForgeDirection.SOUTH;
case 5:
return ForgeDirection.EAST;
case 4:
return ForgeDirection.WEST;
}
return ForgeDirection.NORTH;
}
public ForgeDirection getBack()
{
switch(direction)
{
case 2:
return ForgeDirection.SOUTH;
case 3:
return ForgeDirection.NORTH;
case 5:
return ForgeDirection.WEST;
case 4:
return ForgeDirection.EAST;
}
return ForgeDirection.NORTH;
}
public ForgeDirection getLeft()
{
switch(direction)
{
case 2:
return ForgeDirection.WEST;
case 3:
return ForgeDirection.EAST;
case 5:
return ForgeDirection.NORTH;
case 4:
return ForgeDirection.SOUTH;
}
return ForgeDirection.NORTH;
}
public ForgeDirection getRight()
{
switch(direction)
{
case 2:
return ForgeDirection.EAST;
case 3:
return ForgeDirection.WEST;
case 5:
return ForgeDirection.SOUTH;
case 4:
return ForgeDirection.NORTH;
}
return ForgeDirection.NORTH;
}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack) {
if(this.getType() == 1)
{
if(i == 0)//COAL
return ItemHandler.isCarbon(itemstack);
if(i == 1)//LIME
return ItemHandler.isFlux(itemstack);
if(i == 2)//IN
return BlastRecipes.getResult(itemstack) != null;
}
if(this.getType() == 2)//FUEL
return this.getItemBurnTime(itemstack) > 0;
return false;
}
public double getDistanceFromPos(double x, double y, double z)
{
double d3 = (double)this.xCoord + 0.5D - x;
double d4 = (double)this.yCoord + 0.5D - y;
double d5 = (double)this.zCoord + 0.5D - z;
return d3 * d3 + d4 * d4 + d5 * d5;
}
@Override
public int[] getAccessibleSlotsFromSide(int slot) {
switch(this.getType())
{
case 0://SHAFT
return null;
case 1://IN
return new int[]{0, 1, 2};
case 3://FUEL
return new int[]{0, 1};
}
return new int[]{0};
}
@Override
/**
* Put In
*/
public boolean canInsertItem(int slot, ItemStack item, int side) {
return isItemValidForSlot(slot, item);
}
@Override
/**
* Take From
*/
public boolean canExtractItem(int slot, ItemStack item, int side) {
if(getType() == 1) //IN
{
if(slot == 2)
return true;
}
if(getType() == 2 || getType() == 3) //FUEL
{
return side == 0;
}
return true;
}
@Override
public void onUsedWithBellows(float powerLevel)
{
bellowsBonus = (int)(20F*powerLevel);
}
private String customName;
public void setCustomName(String name)
{
customName = name;
}
@Override
public String getInvName()
{
return isInvNameLocalized() ? customName : getDefaultName();
}
@Override
public boolean isInvNameLocalized()
{
return customName != null && customName.length() > 0;
}
}