001package net.minecraft.block;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.Random;
006import net.minecraft.block.material.Material;
007import net.minecraft.entity.EntityLiving;
008import net.minecraft.entity.item.EntityItem;
009import net.minecraft.entity.player.EntityPlayer;
010import net.minecraft.item.ItemStack;
011import net.minecraft.nbt.NBTTagCompound;
012import net.minecraft.tileentity.TileEntity;
013import net.minecraft.tileentity.TileEntityFurnace;
014import net.minecraft.util.MathHelper;
015import net.minecraft.world.IBlockAccess;
016import net.minecraft.world.World;
017
018public class BlockFurnace extends BlockContainer
019{
020    /**
021     * Is the random generator used by furnace to drop the inventory contents in random directions.
022     */
023    private Random furnaceRand = new Random();
024
025    /** True if this is an active furnace, false if idle */
026    private final boolean isActive;
027
028    /**
029     * This flag is used to prevent the furnace inventory to be dropped upon block removal, is used internally when the
030     * furnace block changes from idle to active and vice-versa.
031     */
032    private static boolean keepFurnaceInventory = false;
033
034    protected BlockFurnace(int par1, boolean par2)
035    {
036        super(par1, Material.rock);
037        this.isActive = par2;
038        this.blockIndexInTexture = 45;
039    }
040
041    /**
042     * Returns the ID of the items to drop on destruction.
043     */
044    public int idDropped(int par1, Random par2Random, int par3)
045    {
046        return Block.stoneOvenIdle.blockID;
047    }
048
049    /**
050     * Called whenever the block is added into the world. Args: world, x, y, z
051     */
052    public void onBlockAdded(World par1World, int par2, int par3, int par4)
053    {
054        super.onBlockAdded(par1World, par2, par3, par4);
055        this.setDefaultDirection(par1World, par2, par3, par4);
056    }
057
058    /**
059     * set a blocks direction
060     */
061    private void setDefaultDirection(World par1World, int par2, int par3, int par4)
062    {
063        if (!par1World.isRemote)
064        {
065            int var5 = par1World.getBlockId(par2, par3, par4 - 1);
066            int var6 = par1World.getBlockId(par2, par3, par4 + 1);
067            int var7 = par1World.getBlockId(par2 - 1, par3, par4);
068            int var8 = par1World.getBlockId(par2 + 1, par3, par4);
069            byte var9 = 3;
070
071            if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6])
072            {
073                var9 = 3;
074            }
075
076            if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5])
077            {
078                var9 = 2;
079            }
080
081            if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8])
082            {
083                var9 = 5;
084            }
085
086            if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7])
087            {
088                var9 = 4;
089            }
090
091            par1World.setBlockMetadataWithNotify(par2, par3, par4, var9);
092        }
093    }
094
095    @SideOnly(Side.CLIENT)
096
097    /**
098     * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
099     */
100    public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
101    {
102        if (par5 == 1)
103        {
104            return this.blockIndexInTexture + 17;
105        }
106        else if (par5 == 0)
107        {
108            return this.blockIndexInTexture + 17;
109        }
110        else
111        {
112            int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
113            return par5 != var6 ? this.blockIndexInTexture : (this.isActive ? this.blockIndexInTexture + 16 : this.blockIndexInTexture - 1);
114        }
115    }
116
117    @SideOnly(Side.CLIENT)
118
119    /**
120     * A randomly called display update to be able to add particles or other items for display
121     */
122    public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
123    {
124        if (this.isActive)
125        {
126            int var6 = par1World.getBlockMetadata(par2, par3, par4);
127            float var7 = (float)par2 + 0.5F;
128            float var8 = (float)par3 + 0.0F + par5Random.nextFloat() * 6.0F / 16.0F;
129            float var9 = (float)par4 + 0.5F;
130            float var10 = 0.52F;
131            float var11 = par5Random.nextFloat() * 0.6F - 0.3F;
132
133            if (var6 == 4)
134            {
135                par1World.spawnParticle("smoke", (double)(var7 - var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
136                par1World.spawnParticle("flame", (double)(var7 - var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
137            }
138            else if (var6 == 5)
139            {
140                par1World.spawnParticle("smoke", (double)(var7 + var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
141                par1World.spawnParticle("flame", (double)(var7 + var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
142            }
143            else if (var6 == 2)
144            {
145                par1World.spawnParticle("smoke", (double)(var7 + var11), (double)var8, (double)(var9 - var10), 0.0D, 0.0D, 0.0D);
146                par1World.spawnParticle("flame", (double)(var7 + var11), (double)var8, (double)(var9 - var10), 0.0D, 0.0D, 0.0D);
147            }
148            else if (var6 == 3)
149            {
150                par1World.spawnParticle("smoke", (double)(var7 + var11), (double)var8, (double)(var9 + var10), 0.0D, 0.0D, 0.0D);
151                par1World.spawnParticle("flame", (double)(var7 + var11), (double)var8, (double)(var9 + var10), 0.0D, 0.0D, 0.0D);
152            }
153        }
154    }
155
156    /**
157     * Returns the block texture based on the side being looked at.  Args: side
158     */
159    public int getBlockTextureFromSide(int par1)
160    {
161        return par1 == 1 ? this.blockIndexInTexture + 17 : (par1 == 0 ? this.blockIndexInTexture + 17 : (par1 == 3 ? this.blockIndexInTexture - 1 : this.blockIndexInTexture));
162    }
163
164    /**
165     * Called upon block activation (right click on the block.)
166     */
167    public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
168    {
169        if (par1World.isRemote)
170        {
171            return true;
172        }
173        else
174        {
175            TileEntityFurnace var10 = (TileEntityFurnace)par1World.getBlockTileEntity(par2, par3, par4);
176
177            if (var10 != null)
178            {
179                par5EntityPlayer.displayGUIFurnace(var10);
180            }
181
182            return true;
183        }
184    }
185
186    /**
187     * Update which block ID the furnace is using depending on whether or not it is burning
188     */
189    public static void updateFurnaceBlockState(boolean par0, World par1World, int par2, int par3, int par4)
190    {
191        int var5 = par1World.getBlockMetadata(par2, par3, par4);
192        TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4);
193        keepFurnaceInventory = true;
194
195        if (par0)
196        {
197            par1World.setBlockWithNotify(par2, par3, par4, Block.stoneOvenActive.blockID);
198        }
199        else
200        {
201            par1World.setBlockWithNotify(par2, par3, par4, Block.stoneOvenIdle.blockID);
202        }
203
204        keepFurnaceInventory = false;
205        par1World.setBlockMetadataWithNotify(par2, par3, par4, var5);
206
207        if (var6 != null)
208        {
209            var6.validate();
210            par1World.setBlockTileEntity(par2, par3, par4, var6);
211        }
212    }
213
214    /**
215     * Returns a new instance of a block's tile entity class. Called on placing the block.
216     */
217    public TileEntity createNewTileEntity(World par1World)
218    {
219        return new TileEntityFurnace();
220    }
221
222    /**
223     * Called when the block is placed in the world.
224     */
225    public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving)
226    {
227        int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
228
229        if (var6 == 0)
230        {
231            par1World.setBlockMetadataWithNotify(par2, par3, par4, 2);
232        }
233
234        if (var6 == 1)
235        {
236            par1World.setBlockMetadataWithNotify(par2, par3, par4, 5);
237        }
238
239        if (var6 == 2)
240        {
241            par1World.setBlockMetadataWithNotify(par2, par3, par4, 3);
242        }
243
244        if (var6 == 3)
245        {
246            par1World.setBlockMetadataWithNotify(par2, par3, par4, 4);
247        }
248    }
249
250    /**
251     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
252     */
253    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
254    {
255        if (!keepFurnaceInventory)
256        {
257            TileEntityFurnace var7 = (TileEntityFurnace)par1World.getBlockTileEntity(par2, par3, par4);
258
259            if (var7 != null)
260            {
261                for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8)
262                {
263                    ItemStack var9 = var7.getStackInSlot(var8);
264
265                    if (var9 != null)
266                    {
267                        float var10 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
268                        float var11 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
269                        float var12 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
270
271                        while (var9.stackSize > 0)
272                        {
273                            int var13 = this.furnaceRand.nextInt(21) + 10;
274
275                            if (var13 > var9.stackSize)
276                            {
277                                var13 = var9.stackSize;
278                            }
279
280                            var9.stackSize -= var13;
281                            EntityItem var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage()));
282
283                            if (var9.hasTagCompound())
284                            {
285                                var14.getEntityItem().setTagCompound((NBTTagCompound)var9.getTagCompound().copy());
286                            }
287
288                            float var15 = 0.05F;
289                            var14.motionX = (double)((float)this.furnaceRand.nextGaussian() * var15);
290                            var14.motionY = (double)((float)this.furnaceRand.nextGaussian() * var15 + 0.2F);
291                            var14.motionZ = (double)((float)this.furnaceRand.nextGaussian() * var15);
292                            par1World.spawnEntityInWorld(var14);
293                        }
294                    }
295                }
296            }
297        }
298
299        super.breakBlock(par1World, par2, par3, par4, par5, par6);
300    }
301}