    001    package net.minecraft.block;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005
    006    import java.util.ArrayList;
    007    import java.util.Random;
    008    import net.minecraft.block.material.Material;
    009    import net.minecraft.creativetab.CreativeTabs;
    010    import net.minecraft.entity.player.EntityPlayer;
    011    import net.minecraft.item.Item;
    012    import net.minecraft.item.ItemStack;
    013    import net.minecraft.stats.StatList;
    014    import net.minecraft.util.AxisAlignedBB;
    015    import net.minecraft.util.Direction;
    016    import net.minecraft.world.ColorizerFoliage;
    017    import net.minecraft.world.IBlockAccess;
    018    import net.minecraft.world.World;
    019
    020    import net.minecraftforge.common.IShearable;
    021
    022    public class BlockVine extends Block implements IShearable
    023    {
    024        public BlockVine(int par1)
    025        {
    026            super(par1, 143, Material.vine);
    027            this.setTickRandomly(true);
    028            this.setCreativeTab(CreativeTabs.tabDecorations);
    029        }
    030
    031        /**
    032         * Sets the block's bounds for rendering it as an item
    033         */
    034        public void setBlockBoundsForItemRender()
    035        {
    036            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    037        }
    038
    039        /**
    040         * The type of render function that is called for this block
    041         */
    042        public int getRenderType()
    043        {
    044            return 20;
    045        }
    046
    047        /**
    048         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    049         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    050         */
    051        public boolean isOpaqueCube()
    052        {
    053            return false;
    054        }
    055
    056        /**
    057         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    058         */
    059        public boolean renderAsNormalBlock()
    060        {
    061            return false;
    062        }
    063
    064        /**
    065         * Updates the blocks bounds based on its current state. Args: world, x, y, z
    066         */
    067        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    068        {
    069            int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    070            float var7 = 1.0F;
    071            float var8 = 1.0F;
    072            float var9 = 1.0F;
    073            float var10 = 0.0F;
    074            float var11 = 0.0F;
    075            float var12 = 0.0F;
    076            boolean var13 = var6 > 0;
    077
    078            if ((var6 & 2) != 0)
    079            {
    080                var10 = Math.max(var10, 0.0625F);
    081                var7 = 0.0F;
    082                var8 = 0.0F;
    083                var11 = 1.0F;
    084                var9 = 0.0F;
    085                var12 = 1.0F;
    086                var13 = true;
    087            }
    088
    089            if ((var6 & 8) != 0)
    090            {
    091                var7 = Math.min(var7, 0.9375F);
    092                var10 = 1.0F;
    093                var8 = 0.0F;
    094                var11 = 1.0F;
    095                var9 = 0.0F;
    096                var12 = 1.0F;
    097                var13 = true;
    098            }
    099
    100            if ((var6 & 4) != 0)
    101            {
    102                var12 = Math.max(var12, 0.0625F);
    103                var9 = 0.0F;
    104                var7 = 0.0F;
    105                var10 = 1.0F;
    106                var8 = 0.0F;
    107                var11 = 1.0F;
    108                var13 = true;
    109            }
    110
    111            if ((var6 & 1) != 0)
    112            {
    113                var9 = Math.min(var9, 0.9375F);
    114                var12 = 1.0F;
    115                var7 = 0.0F;
    116                var10 = 1.0F;
    117                var8 = 0.0F;
    118                var11 = 1.0F;
    119                var13 = true;
    120            }
    121
    122            if (!var13 && this.canBePlacedOn(par1IBlockAccess.getBlockId(par2, par3 + 1, par4)))
    123            {
    124                var8 = Math.min(var8, 0.9375F);
    125                var11 = 1.0F;
    126                var7 = 0.0F;
    127                var10 = 1.0F;
    128                var9 = 0.0F;
    129                var12 = 1.0F;
    130            }
    131
    132            this.setBlockBounds(var7, var8, var9, var10, var11, var12);
    133        }
    134
    135        /**
    136         * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    137         * cleared to be reused)
    138         */
    139        public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    140        {
    141            return null;
    142        }
    143
    144        /**
    145         * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
    146         */
    147        public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5)
    148        {
    149            switch (par5)
    150            {
    151                case 1:
    152                    return this.canBePlacedOn(par1World.getBlockId(par2, par3 + 1, par4));
    153                case 2:
    154                    return this.canBePlacedOn(par1World.getBlockId(par2, par3, par4 + 1));
    155                case 3:
    156                    return this.canBePlacedOn(par1World.getBlockId(par2, par3, par4 - 1));
    157                case 4:
    158                    return this.canBePlacedOn(par1World.getBlockId(par2 + 1, par3, par4));
    159                case 5:
    160                    return this.canBePlacedOn(par1World.getBlockId(par2 - 1, par3, par4));
    161                default:
    162                    return false;
    163            }
    164        }
    165
    166        /**
    167         * returns true if a vine can be placed on that block (checks for render as normal block and if it is solid)
    168         */
    169        private boolean canBePlacedOn(int par1)
    170        {
    171            if (par1 == 0)
    172            {
    173                return false;
    174            }
    175            else
    176            {
    177                Block var2 = Block.blocksList[par1];
    178                return var2.renderAsNormalBlock() && var2.blockMaterial.blocksMovement();
    179            }
    180        }
    181
    182        /**
    183         * Returns if the vine can stay in the world. It also changes the metadata according to neighboring blocks.
    184         */
    185        private boolean canVineStay(World par1World, int par2, int par3, int par4)
    186        {
    187            int var5 = par1World.getBlockMetadata(par2, par3, par4);
    188            int var6 = var5;
    189
    190            if (var5 > 0)
    191            {
    192                for (int var7 = 0; var7 <= 3; ++var7)
    193                {
    194                    int var8 = 1 << var7;
    195
    196                    if ((var5 & var8) != 0 && !this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var7], par3, par4 + Direction.offsetZ[var7])) && (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID || (par1World.getBlockMetadata(par2, par3 + 1, par4) & var8) == 0))
    197                    {
    198                        var6 &= ~var8;
    199                    }
    200                }
    201            }
    202
    203            if (var6 == 0 && !this.canBePlacedOn(par1World.getBlockId(par2, par3 + 1, par4)))
    204            {
    205                return false;
    206            }
    207            else
    208            {
    209                if (var6 != var5)
    210                {
    211                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var6);
    212                }
    213
    214                return true;
    215            }
    216        }
    217
    218        @SideOnly(Side.CLIENT)
    219        public int getBlockColor()
    220        {
    221            return ColorizerFoliage.getFoliageColorBasic();
    222        }
    223
    224        @SideOnly(Side.CLIENT)
    225
    226        /**
    227         * Returns the color this block should be rendered. Used by leaves.
    228         */
    229        public int getRenderColor(int par1)
    230        {
    231            return ColorizerFoliage.getFoliageColorBasic();
    232        }
    233
    234        @SideOnly(Side.CLIENT)
    235
    236        /**
    237         * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called
    238         * when first determining what to render.
    239         */
    240        public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    241        {
    242            return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeFoliageColor();
    243        }
    244
    245        /**
    246         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    247         * their own) Args: x, y, z, neighbor blockID
    248         */
    249        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    250        {
    251            if (!par1World.isRemote && !this.canVineStay(par1World, par2, par3, par4))
    252            {
    253                this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
    254                par1World.setBlockWithNotify(par2, par3, par4, 0);
    255            }
    256        }
    257
    258        /**
    259         * Ticks the block if it's been scheduled
    260         */
    261        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    262        {
    263            if (!par1World.isRemote && par1World.rand.nextInt(4) == 0)
    264            {
    265                byte var6 = 4;
    266                int var7 = 5;
    267                boolean var8 = false;
    268                int var9;
    269                int var10;
    270                int var11;
    271                label138:
    272
    273                for (var9 = par2 - var6; var9 <= par2 + var6; ++var9)
    274                {
    275                    for (var10 = par4 - var6; var10 <= par4 + var6; ++var10)
    276                    {
    277                        for (var11 = par3 - 1; var11 <= par3 + 1; ++var11)
    278                        {
    279                            if (par1World.getBlockId(var9, var11, var10) == this.blockID)
    280                            {
    281                                --var7;
    282
    283                                if (var7 <= 0)
    284                                {
    285                                    var8 = true;
    286                                    break label138;
    287                                }
    288                            }
    289                        }
    290                    }
    291                }
    292
    293                var9 = par1World.getBlockMetadata(par2, par3, par4);
    294                var10 = par1World.rand.nextInt(6);
    295                var11 = Direction.vineGrowth[var10];
    296                int var12;
    297                int var13;
    298
    299                if (var10 == 1 && par3 < 255 && par1World.isAirBlock(par2, par3 + 1, par4))
    300                {
    301                    if (var8)
    302                    {
    303                        return;
    304                    }
    305
    306                    var12 = par1World.rand.nextInt(16) & var9;
    307
    308                    if (var12 > 0)
    309                    {
    310                        for (var13 = 0; var13 <= 3; ++var13)
    311                        {
    312                            if (!this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var13], par3 + 1, par4 + Direction.offsetZ[var13])))
    313                            {
    314                                var12 &= ~(1 << var13);
    315                            }
    316                        }
    317
    318                        if (var12 > 0)
    319                        {
    320                            par1World.setBlockAndMetadataWithNotify(par2, par3 + 1, par4, this.blockID, var12);
    321                        }
    322                    }
    323                }
    324                else
    325                {
    326                    int var14;
    327
    328                    if (var10 >= 2 && var10 <= 5 && (var9 & 1 << var11) == 0)
    329                    {
    330                        if (var8)
    331                        {
    332                            return;
    333                        }
    334
    335                        var12 = par1World.getBlockId(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11]);
    336
    337                        if (var12 != 0 && Block.blocksList[var12] != null)
    338                        {
    339                            if (Block.blocksList[var12].blockMaterial.isOpaque() && Block.blocksList[var12].renderAsNormalBlock())
    340                            {
    341                                par1World.setBlockMetadataWithNotify(par2, par3, par4, var9 | 1 << var11);
    342                            }
    343                        }
    344                        else
    345                        {
    346                            var13 = var11 + 1 & 3;
    347                            var14 = var11 + 3 & 3;
    348
    349                            if ((var9 & 1 << var13) != 0 && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13])))
    350                            {
    351                                par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11], this.blockID, 1 << var13);
    352                            }
    353                            else if ((var9 & 1 << var14) != 0 && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14])))
    354                            {
    355                                par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11], this.blockID, 1 << var14);
    356                            }
    357                            else if ((var9 & 1 << var13) != 0 && par1World.isAirBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13]) && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var13])))
    358                            {
    359                                par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13], this.blockID, 1 << (var11 + 2 & 3));
    360                            }
    361                            else if ((var9 & 1 << var14) != 0 && par1World.isAirBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14]) && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var14])))
    362                            {
    363                                par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14], this.blockID, 1 << (var11 + 2 & 3));
    364                            }
    365                            else if (this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11], par3 + 1, par4 + Direction.offsetZ[var11])))
    366                            {
    367                                par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11], this.blockID, 0);
    368                            }
    369                        }
    370                    }
    371                    else if (par3 > 1)
    372                    {
    373                        var12 = par1World.getBlockId(par2, par3 - 1, par4);
    374
    375                        if (var12 == 0)
    376                        {
    377                            var13 = par1World.rand.nextInt(16) & var9;
    378
    379                            if (var13 > 0)
    380                            {
    381                                par1World.setBlockAndMetadataWithNotify(par2, par3 - 1, par4, this.blockID, var13);
    382                            }
    383                        }
    384                        else if (var12 == this.blockID)
    385                        {
    386                            var13 = par1World.rand.nextInt(16) & var9;
    387                            var14 = par1World.getBlockMetadata(par2, par3 - 1, par4);
    388
    389                            if (var14 != (var14 | var13))
    390                            {
    391                                par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var14 | var13);
    392                            }
    393                        }
    394                    }
    395                }
    396            }
    397        }
    398
    399        public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
    400        {
    401            byte var10 = 0;
    402
    403            switch (par5)
    404            {
    405                case 2:
    406                    var10 = 1;
    407                    break;
    408                case 3:
    409                    var10 = 4;
    410                    break;
    411                case 4:
    412                    var10 = 8;
    413                    break;
    414                case 5:
    415                    var10 = 2;
    416            }
    417
    418            return var10 != 0 ? var10 : par9;
    419        }
    420
    421        /**
    422         * Returns the ID of the items to drop on destruction.
    423         */
    424        public int idDropped(int par1, Random par2Random, int par3)
    425        {
    426            return 0;
    427        }
    428
    429        /**
    430         * Returns the quantity of items to drop on block destruction.
    431         */
    432        public int quantityDropped(Random par1Random)
    433        {
    434            return 0;
    435        }
    436
    437        /**
    438         * Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the
    439         * block and l is the block's subtype/damage.
    440         */
    441        public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6)
    442        {
    443            super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
    444        }
    445
    446        @Override
    447        public boolean isShearable(ItemStack item, World world, int x, int y, int z)
    448        {
    449            return true;
    450        }
    451
    452        @Override
    453        public ArrayList<ItemStack> onSheared(ItemStack item, World world, int x, int y, int z, int fortune)
    454        {
    455            ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
    456            ret.add(new ItemStack(this, 1, 0));
    457            return ret;
    458        }
    459
    460        @Override
    461        public boolean isLadder(World world, int x, int y, int z)
    462        {
    463            return true;
    464        }
    465    }