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