    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}