001    package net.minecraft.block;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.Random;
006    import net.minecraft.block.material.Material;
007    import net.minecraft.entity.EntityLiving;
008    import net.minecraft.entity.item.EntityItem;
009    import net.minecraft.entity.player.EntityPlayer;
010    import net.minecraft.item.ItemStack;
011    import net.minecraft.nbt.NBTTagCompound;
012    import net.minecraft.tileentity.TileEntity;
013    import net.minecraft.tileentity.TileEntityFurnace;
014    import net.minecraft.util.MathHelper;
015    import net.minecraft.world.IBlockAccess;
016    import net.minecraft.world.World;
017    
018    public 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.func_92014_d().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    }