001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    import java.util.Iterator;
006    import java.util.Random;
007    import static net.minecraftforge.common.ForgeDirection.*;
008    
009    public class BlockChest extends BlockContainer
010    {
011        private Random random = new Random();
012    
013        protected BlockChest(int par1)
014        {
015            super(par1, Material.wood);
016            this.blockIndexInTexture = 26;
017            this.setCreativeTab(CreativeTabs.tabDecorations);
018            this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
019        }
020    
021        /**
022         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
023         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
024         */
025        public boolean isOpaqueCube()
026        {
027            return false;
028        }
029    
030        /**
031         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
032         */
033        public boolean renderAsNormalBlock()
034        {
035            return false;
036        }
037    
038        /**
039         * The type of render function that is called for this block
040         */
041        public int getRenderType()
042        {
043            return 22;
044        }
045    
046        /**
047         * Updates the blocks bounds based on its current state. Args: world, x, y, z
048         */
049        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
050        {
051            if (par1IBlockAccess.getBlockId(par2, par3, par4 - 1) == this.blockID)
052            {
053                this.setBlockBounds(0.0625F, 0.0F, 0.0F, 0.9375F, 0.875F, 0.9375F);
054            }
055            else if (par1IBlockAccess.getBlockId(par2, par3, par4 + 1) == this.blockID)
056            {
057                this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 1.0F);
058            }
059            else if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == this.blockID)
060            {
061                this.setBlockBounds(0.0F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
062            }
063            else if (par1IBlockAccess.getBlockId(par2 + 1, par3, par4) == this.blockID)
064            {
065                this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 1.0F, 0.875F, 0.9375F);
066            }
067            else
068            {
069                this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
070            }
071        }
072    
073        /**
074         * Called whenever the block is added into the world. Args: world, x, y, z
075         */
076        public void onBlockAdded(World par1World, int par2, int par3, int par4)
077        {
078            super.onBlockAdded(par1World, par2, par3, par4);
079            this.unifyAdjacentChests(par1World, par2, par3, par4);
080            int var5 = par1World.getBlockId(par2, par3, par4 - 1);
081            int var6 = par1World.getBlockId(par2, par3, par4 + 1);
082            int var7 = par1World.getBlockId(par2 - 1, par3, par4);
083            int var8 = par1World.getBlockId(par2 + 1, par3, par4);
084    
085            if (var5 == this.blockID)
086            {
087                this.unifyAdjacentChests(par1World, par2, par3, par4 - 1);
088            }
089    
090            if (var6 == this.blockID)
091            {
092                this.unifyAdjacentChests(par1World, par2, par3, par4 + 1);
093            }
094    
095            if (var7 == this.blockID)
096            {
097                this.unifyAdjacentChests(par1World, par2 - 1, par3, par4);
098            }
099    
100            if (var8 == this.blockID)
101            {
102                this.unifyAdjacentChests(par1World, par2 + 1, par3, par4);
103            }
104        }
105    
106        /**
107         * Called when the block is placed in the world.
108         */
109        public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving)
110        {
111            int var6 = par1World.getBlockId(par2, par3, par4 - 1);
112            int var7 = par1World.getBlockId(par2, par3, par4 + 1);
113            int var8 = par1World.getBlockId(par2 - 1, par3, par4);
114            int var9 = par1World.getBlockId(par2 + 1, par3, par4);
115            byte var10 = 0;
116            int var11 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
117    
118            if (var11 == 0)
119            {
120                var10 = 2;
121            }
122    
123            if (var11 == 1)
124            {
125                var10 = 5;
126            }
127    
128            if (var11 == 2)
129            {
130                var10 = 3;
131            }
132    
133            if (var11 == 3)
134            {
135                var10 = 4;
136            }
137    
138            if (var6 != this.blockID && var7 != this.blockID && var8 != this.blockID && var9 != this.blockID)
139            {
140                par1World.setBlockMetadataWithNotify(par2, par3, par4, var10);
141            }
142            else
143            {
144                if ((var6 == this.blockID || var7 == this.blockID) && (var10 == 4 || var10 == 5))
145                {
146                    if (var6 == this.blockID)
147                    {
148                        par1World.setBlockMetadataWithNotify(par2, par3, par4 - 1, var10);
149                    }
150                    else
151                    {
152                        par1World.setBlockMetadataWithNotify(par2, par3, par4 + 1, var10);
153                    }
154    
155                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var10);
156                }
157    
158                if ((var8 == this.blockID || var9 == this.blockID) && (var10 == 2 || var10 == 3))
159                {
160                    if (var8 == this.blockID)
161                    {
162                        par1World.setBlockMetadataWithNotify(par2 - 1, par3, par4, var10);
163                    }
164                    else
165                    {
166                        par1World.setBlockMetadataWithNotify(par2 + 1, par3, par4, var10);
167                    }
168    
169                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var10);
170                }
171            }
172        }
173    
174        /**
175         * Turns the adjacent chests to a double chest.
176         */
177        public void unifyAdjacentChests(World par1World, int par2, int par3, int par4)
178        {
179            if (!par1World.isRemote)
180            {
181                int var5 = par1World.getBlockId(par2, par3, par4 - 1);
182                int var6 = par1World.getBlockId(par2, par3, par4 + 1);
183                int var7 = par1World.getBlockId(par2 - 1, par3, par4);
184                int var8 = par1World.getBlockId(par2 + 1, par3, par4);
185                boolean var9 = true;
186                int var10;
187                int var11;
188                boolean var12;
189                byte var13;
190                int var14;
191    
192                if (var5 != this.blockID && var6 != this.blockID)
193                {
194                    if (var7 != this.blockID && var8 != this.blockID)
195                    {
196                        var13 = 3;
197    
198                        if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6])
199                        {
200                            var13 = 3;
201                        }
202    
203                        if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5])
204                        {
205                            var13 = 2;
206                        }
207    
208                        if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8])
209                        {
210                            var13 = 5;
211                        }
212    
213                        if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7])
214                        {
215                            var13 = 4;
216                        }
217                    }
218                    else
219                    {
220                        var10 = par1World.getBlockId(var7 == this.blockID ? par2 - 1 : par2 + 1, par3, par4 - 1);
221                        var11 = par1World.getBlockId(var7 == this.blockID ? par2 - 1 : par2 + 1, par3, par4 + 1);
222                        var13 = 3;
223                        var12 = true;
224    
225                        if (var7 == this.blockID)
226                        {
227                            var14 = par1World.getBlockMetadata(par2 - 1, par3, par4);
228                        }
229                        else
230                        {
231                            var14 = par1World.getBlockMetadata(par2 + 1, par3, par4);
232                        }
233    
234                        if (var14 == 2)
235                        {
236                            var13 = 2;
237                        }
238    
239                        if ((Block.opaqueCubeLookup[var5] || Block.opaqueCubeLookup[var10]) && !Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var11])
240                        {
241                            var13 = 3;
242                        }
243    
244                        if ((Block.opaqueCubeLookup[var6] || Block.opaqueCubeLookup[var11]) && !Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var10])
245                        {
246                            var13 = 2;
247                        }
248                    }
249                }
250                else
251                {
252                    var10 = par1World.getBlockId(par2 - 1, par3, var5 == this.blockID ? par4 - 1 : par4 + 1);
253                    var11 = par1World.getBlockId(par2 + 1, par3, var5 == this.blockID ? par4 - 1 : par4 + 1);
254                    var13 = 5;
255                    var12 = true;
256    
257                    if (var5 == this.blockID)
258                    {
259                        var14 = par1World.getBlockMetadata(par2, par3, par4 - 1);
260                    }
261                    else
262                    {
263                        var14 = par1World.getBlockMetadata(par2, par3, par4 + 1);
264                    }
265    
266                    if (var14 == 4)
267                    {
268                        var13 = 4;
269                    }
270    
271                    if ((Block.opaqueCubeLookup[var7] || Block.opaqueCubeLookup[var10]) && !Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var11])
272                    {
273                        var13 = 5;
274                    }
275    
276                    if ((Block.opaqueCubeLookup[var8] || Block.opaqueCubeLookup[var11]) && !Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var10])
277                    {
278                        var13 = 4;
279                    }
280                }
281    
282                par1World.setBlockMetadataWithNotify(par2, par3, par4, var13);
283            }
284        }
285    
286        @SideOnly(Side.CLIENT)
287    
288        /**
289         * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
290         */
291        public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
292        {
293            return 4;
294        }
295    
296        /**
297         * Returns the block texture based on the side being looked at.  Args: side
298         */
299        public int getBlockTextureFromSide(int par1)
300        {
301            return 4;
302        }
303    
304        /**
305         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
306         */
307        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
308        {
309            int var5 = 0;
310    
311            if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID)
312            {
313                ++var5;
314            }
315    
316            if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID)
317            {
318                ++var5;
319            }
320    
321            if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID)
322            {
323                ++var5;
324            }
325    
326            if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID)
327            {
328                ++var5;
329            }
330    
331            return var5 > 1 ? false : (this.isThereANeighborChest(par1World, par2 - 1, par3, par4) ? false : (this.isThereANeighborChest(par1World, par2 + 1, par3, par4) ? false : (this.isThereANeighborChest(par1World, par2, par3, par4 - 1) ? false : !this.isThereANeighborChest(par1World, par2, par3, par4 + 1))));
332        }
333    
334        /**
335         * Checks the neighbor blocks to see if there is a chest there. Args: world, x, y, z
336         */
337        private boolean isThereANeighborChest(World par1World, int par2, int par3, int par4)
338        {
339            return par1World.getBlockId(par2, par3, par4) != this.blockID ? false : (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID ? true : (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID ? true : (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID ? true : par1World.getBlockId(par2, par3, par4 + 1) == this.blockID)));
340        }
341    
342        /**
343         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
344         * their own) Args: x, y, z, neighbor blockID
345         */
346        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
347        {
348            super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
349            TileEntityChest var6 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4);
350    
351            if (var6 != null)
352            {
353                var6.updateContainingBlockInfo();
354            }
355        }
356    
357        /**
358         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
359         */
360        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
361        {
362            TileEntityChest var7 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4);
363    
364            if (var7 != null)
365            {
366                for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8)
367                {
368                    ItemStack var9 = var7.getStackInSlot(var8);
369    
370                    if (var9 != null)
371                    {
372                        float var10 = this.random.nextFloat() * 0.8F + 0.1F;
373                        float var11 = this.random.nextFloat() * 0.8F + 0.1F;
374                        EntityItem var14;
375    
376                        for (float var12 = this.random.nextFloat() * 0.8F + 0.1F; var9.stackSize > 0; par1World.spawnEntityInWorld(var14))
377                        {
378                            int var13 = this.random.nextInt(21) + 10;
379    
380                            if (var13 > var9.stackSize)
381                            {
382                                var13 = var9.stackSize;
383                            }
384    
385                            var9.stackSize -= var13;
386                            var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage()));
387                            float var15 = 0.05F;
388                            var14.motionX = (double)((float)this.random.nextGaussian() * var15);
389                            var14.motionY = (double)((float)this.random.nextGaussian() * var15 + 0.2F);
390                            var14.motionZ = (double)((float)this.random.nextGaussian() * var15);
391    
392                            if (var9.hasTagCompound())
393                            {
394                                var14.item.setTagCompound((NBTTagCompound)var9.getTagCompound().copy());
395                            }
396                        }
397                    }
398                }
399            }
400    
401            super.breakBlock(par1World, par2, par3, par4, par5, par6);
402        }
403    
404        /**
405         * Called upon block activation (right click on the block.)
406         */
407        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
408        {
409            Object var10 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4);
410    
411            if (var10 == null)
412            {
413                return true;
414            }
415            else if (par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN))
416            {
417                return true;
418            }
419            else if (isOcelotBlockingChest(par1World, par2, par3, par4))
420            {
421                return true;
422            }
423            else if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID && (par1World.isBlockSolidOnSide(par2 - 1, par3 + 1, par4, DOWN) || isOcelotBlockingChest(par1World, par2 - 1, par3, par4)))
424            {
425                return true;
426            }
427            else if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID && (par1World.isBlockSolidOnSide(par2 + 1, par3 + 1, par4, DOWN) || isOcelotBlockingChest(par1World, par2 + 1, par3, par4)))
428            {
429                return true;
430            }
431            else if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID && (par1World.isBlockSolidOnSide(par2, par3 + 1, par4 - 1, DOWN) || isOcelotBlockingChest(par1World, par2, par3, par4 - 1)))
432            {
433                return true;
434            }
435            else if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID && (par1World.isBlockSolidOnSide(par2, par3 + 1, par4 + 1, DOWN) || isOcelotBlockingChest(par1World, par2, par3, par4 + 1)))
436            {
437                return true;
438            }
439            else
440            {
441                if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID)
442                {
443                    var10 = new InventoryLargeChest("container.chestDouble", (TileEntityChest)par1World.getBlockTileEntity(par2 - 1, par3, par4), (IInventory)var10);
444                }
445    
446                if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID)
447                {
448                    var10 = new InventoryLargeChest("container.chestDouble", (IInventory)var10, (TileEntityChest)par1World.getBlockTileEntity(par2 + 1, par3, par4));
449                }
450    
451                if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID)
452                {
453                    var10 = new InventoryLargeChest("container.chestDouble", (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4 - 1), (IInventory)var10);
454                }
455    
456                if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID)
457                {
458                    var10 = new InventoryLargeChest("container.chestDouble", (IInventory)var10, (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4 + 1));
459                }
460    
461                if (par1World.isRemote)
462                {
463                    return true;
464                }
465                else
466                {
467                    par5EntityPlayer.displayGUIChest((IInventory)var10);
468                    return true;
469                }
470            }
471        }
472    
473        /**
474         * Returns a new instance of a block's tile entity class. Called on placing the block.
475         */
476        public TileEntity createNewTileEntity(World par1World)
477        {
478            return new TileEntityChest();
479        }
480    
481        /**
482         * Looks for a sitting ocelot within certain bounds. Such an ocelot is considered to be blocking access to the
483         * chest.
484         */
485        public static boolean isOcelotBlockingChest(World par0World, int par1, int par2, int par3)
486        {
487            Iterator var4 = par0World.getEntitiesWithinAABB(EntityOcelot.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par1, (double)(par2 + 1), (double)par3, (double)(par1 + 1), (double)(par2 + 2), (double)(par3 + 1))).iterator();
488            EntityOcelot var6;
489    
490            do
491            {
492                if (!var4.hasNext())
493                {
494                    return false;
495                }
496    
497                EntityOcelot var5 = (EntityOcelot)var4.next();
498                var6 = (EntityOcelot)var5;
499            }
500            while (!var6.isSitting());
501    
502            return true;
503        }
504    }