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