    001    package net.minecraft.block;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005    import java.util.Iterator;
    006    import java.util.Random;
    007    import net.minecraft.block.material.Material;
    008    import net.minecraft.creativetab.CreativeTabs;
    009    import net.minecraft.entity.EntityLiving;
    010    import net.minecraft.entity.item.EntityItem;
    011    import net.minecraft.entity.passive.EntityOcelot;
    012    import net.minecraft.entity.player.EntityPlayer;
    013    import net.minecraft.inventory.IInventory;
    014    import net.minecraft.inventory.InventoryLargeChest;
    015    import net.minecraft.item.ItemStack;
    016    import net.minecraft.nbt.NBTTagCompound;
    017    import net.minecraft.tileentity.TileEntity;
    018    import net.minecraft.tileentity.TileEntityChest;
    019    import net.minecraft.util.AxisAlignedBB;
    020    import net.minecraft.util.MathHelper;
    021    import net.minecraft.world.IBlockAccess;
    022    import net.minecraft.world.World;
    023
    024    import static net.minecraftforge.common.ForgeDirection.*;
    025
    026    public 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.func_92014_d().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    }