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