    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.List;
    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.world.ColorizerFoliage;
    015    import net.minecraft.world.IBlockAccess;
    016    import net.minecraft.world.World;
    017
    018    import net.minecraftforge.common.IShearable;
    019
    020    public class BlockLeaves extends BlockLeavesBase implements IShearable
    021    {
    022        /**
    023         * The base index in terrain.png corresponding to the fancy version of the leaf texture. This is stored so we can
    024         * switch the displayed version between fancy and fast graphics (fast is this index + 1).
    025         */
    026        private int baseIndexInPNG;
    027        public static final String[] LEAF_TYPES = new String[] {"oak", "spruce", "birch", "jungle"};
    028        int[] adjacentTreeBlocks;
    029
    030        protected BlockLeaves(int par1, int par2)
    031        {
    032            super(par1, par2, Material.leaves, false);
    033            this.baseIndexInPNG = par2;
    034            this.setTickRandomly(true);
    035            this.setCreativeTab(CreativeTabs.tabDecorations);
    036        }
    037
    038        @SideOnly(Side.CLIENT)
    039        public int getBlockColor()
    040        {
    041            double var1 = 0.5D;
    042            double var3 = 1.0D;
    043            return ColorizerFoliage.getFoliageColor(var1, var3);
    044        }
    045
    046        @SideOnly(Side.CLIENT)
    047
    048        /**
    049         * Returns the color this block should be rendered. Used by leaves.
    050         */
    051        public int getRenderColor(int par1)
    052        {
    053            return (par1 & 3) == 1 ? ColorizerFoliage.getFoliageColorPine() : ((par1 & 3) == 2 ? ColorizerFoliage.getFoliageColorBirch() : ColorizerFoliage.getFoliageColorBasic());
    054        }
    055
    056        @SideOnly(Side.CLIENT)
    057
    058        /**
    059         * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called
    060         * when first determining what to render.
    061         */
    062        public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    063        {
    064            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    065
    066            if ((var5 & 3) == 1)
    067            {
    068                return ColorizerFoliage.getFoliageColorPine();
    069            }
    070            else if ((var5 & 3) == 2)
    071            {
    072                return ColorizerFoliage.getFoliageColorBirch();
    073            }
    074            else
    075            {
    076                int var6 = 0;
    077                int var7 = 0;
    078                int var8 = 0;
    079
    080                for (int var9 = -1; var9 <= 1; ++var9)
    081                {
    082                    for (int var10 = -1; var10 <= 1; ++var10)
    083                    {
    084                        int var11 = par1IBlockAccess.getBiomeGenForCoords(par2 + var10, par4 + var9).getBiomeFoliageColor();
    085                        var6 += (var11 & 16711680) >> 16;
    086                        var7 += (var11 & 65280) >> 8;
    087                        var8 += var11 & 255;
    088                    }
    089                }
    090
    091                return (var6 / 9 & 255) << 16 | (var7 / 9 & 255) << 8 | var8 / 9 & 255;
    092            }
    093        }
    094
    095        /**
    096         * ejects contained items into the world, and notifies neighbours of an update, as appropriate
    097         */
    098        public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
    099        {
    100            byte var7 = 1;
    101            int var8 = var7 + 1;
    102
    103            if (par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8, par3 + var8, par4 + var8))
    104            {
    105                for (int var9 = -var7; var9 <= var7; ++var9)
    106                {
    107                    for (int var10 = -var7; var10 <= var7; ++var10)
    108                    {
    109                        for (int var11 = -var7; var11 <= var7; ++var11)
    110                        {
    111                            int var12 = par1World.getBlockId(par2 + var9, par3 + var10, par4 + var11);
    112
    113                            if (Block.blocksList[var12] != null)
    114                            {
    115                                Block.blocksList[var12].beginLeavesDecay(par1World, par2 + var9, par3 + var10, par4 + var11);
    116                            }
    117                        }
    118                    }
    119                }
    120            }
    121        }
    122
    123        /**
    124         * Ticks the block if it's been scheduled
    125         */
    126        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    127        {
    128            if (!par1World.isRemote)
    129            {
    130                int var6 = par1World.getBlockMetadata(par2, par3, par4);
    131
    132                if ((var6 & 8) != 0 && (var6 & 4) == 0)
    133                {
    134                    byte var7 = 4;
    135                    int var8 = var7 + 1;
    136                    byte var9 = 32;
    137                    int var10 = var9 * var9;
    138                    int var11 = var9 / 2;
    139
    140                    if (this.adjacentTreeBlocks == null)
    141                    {
    142                        this.adjacentTreeBlocks = new int[var9 * var9 * var9];
    143                    }
    144
    145                    int var12;
    146
    147                    if (par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8, par3 + var8, par4 + var8))
    148                    {
    149                        int var13;
    150                        int var14;
    151                        int var15;
    152
    153                        for (var12 = -var7; var12 <= var7; ++var12)
    154                        {
    155                            for (var13 = -var7; var13 <= var7; ++var13)
    156                            {
    157                                for (var14 = -var7; var14 <= var7; ++var14)
    158                                {
    159                                    var15 = par1World.getBlockId(par2 + var12, par3 + var13, par4 + var14);
    160
    161                                    Block block = Block.blocksList[var15];
    162
    163                                    if (block != null && block.canSustainLeaves(par1World, par2 + var12, par3 + var13, par4 + var14))
    164                                    {
    165                                        this.adjacentTreeBlocks[(var12 + var11) * var10 + (var13 + var11) * var9 + var14 + var11] = 0;
    166                                    }
    167                                    else if (block != null && block.isLeaves(par1World, par2 + var12, par3 + var13, par4 + var14))
    168                                    {
    169                                        this.adjacentTreeBlocks[(var12 + var11) * var10 + (var13 + var11) * var9 + var14 + var11] = -2;
    170                                    }
    171                                    else
    172                                    {
    173                                        this.adjacentTreeBlocks[(var12 + var11) * var10 + (var13 + var11) * var9 + var14 + var11] = -1;
    174                                    }
    175                                }
    176                            }
    177                        }
    178
    179                        for (var12 = 1; var12 <= 4; ++var12)
    180                        {
    181                            for (var13 = -var7; var13 <= var7; ++var13)
    182                            {
    183                                for (var14 = -var7; var14 <= var7; ++var14)
    184                                {
    185                                    for (var15 = -var7; var15 <= var7; ++var15)
    186                                    {
    187                                        if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9 + var15 + var11] == var12 - 1)
    188                                        {
    189                                            if (this.adjacentTreeBlocks[(var13 + var11 - 1) * var10 + (var14 + var11) * var9 + var15 + var11] == -2)
    190                                            {
    191                                                this.adjacentTreeBlocks[(var13 + var11 - 1) * var10 + (var14 + var11) * var9 + var15 + var11] = var12;
    192                                            }
    193
    194                                            if (this.adjacentTreeBlocks[(var13 + var11 + 1) * var10 + (var14 + var11) * var9 + var15 + var11] == -2)
    195                                            {
    196                                                this.adjacentTreeBlocks[(var13 + var11 + 1) * var10 + (var14 + var11) * var9 + var15 + var11] = var12;
    197                                            }
    198
    199                                            if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 - 1) * var9 + var15 + var11] == -2)
    200                                            {
    201                                                this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 - 1) * var9 + var15 + var11] = var12;
    202                                            }
    203
    204                                            if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 + 1) * var9 + var15 + var11] == -2)
    205                                            {
    206                                                this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 + 1) * var9 + var15 + var11] = var12;
    207                                            }
    208
    209                                            if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9 + (var15 + var11 - 1)] == -2)
    210                                            {
    211                                                this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9 + (var15 + var11 - 1)] = var12;
    212                                            }
    213
    214                                            if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9 + var15 + var11 + 1] == -2)
    215                                            {
    216                                                this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9 + var15 + var11 + 1] = var12;
    217                                            }
    218                                        }
    219                                    }
    220                                }
    221                            }
    222                        }
    223                    }
    224
    225                    var12 = this.adjacentTreeBlocks[var11 * var10 + var11 * var9 + var11];
    226
    227                    if (var12 >= 0)
    228                    {
    229                        par1World.setBlockMetadata(par2, par3, par4, var6 & -9);
    230                    }
    231                    else
    232                    {
    233                        this.removeLeaves(par1World, par2, par3, par4);
    234                    }
    235                }
    236            }
    237        }
    238
    239        @SideOnly(Side.CLIENT)
    240
    241        /**
    242         * A randomly called display update to be able to add particles or other items for display
    243         */
    244        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
    245        {
    246            if (par1World.canLightningStrikeAt(par2, par3 + 1, par4) && !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && par5Random.nextInt(15) == 1)
    247            {
    248                double var6 = (double)((float)par2 + par5Random.nextFloat());
    249                double var8 = (double)par3 - 0.05D;
    250                double var10 = (double)((float)par4 + par5Random.nextFloat());
    251                par1World.spawnParticle("dripWater", var6, var8, var10, 0.0D, 0.0D, 0.0D);
    252            }
    253        }
    254
    255        private void removeLeaves(World par1World, int par2, int par3, int par4)
    256        {
    257            this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
    258            par1World.setBlockWithNotify(par2, par3, par4, 0);
    259        }
    260
    261        /**
    262         * Returns the quantity of items to drop on block destruction.
    263         */
    264        public int quantityDropped(Random par1Random)
    265        {
    266            return par1Random.nextInt(20) == 0 ? 1 : 0;
    267        }
    268
    269        /**
    270         * Returns the ID of the items to drop on destruction.
    271         */
    272        public int idDropped(int par1, Random par2Random, int par3)
    273        {
    274            return Block.sapling.blockID;
    275        }
    276
    277        /**
    278         * Drops the block items with a specified chance of dropping the specified items
    279         */
    280        public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7)
    281        {
    282            if (!par1World.isRemote)
    283            {
    284                byte var8 = 20;
    285
    286                if ((par5 & 3) == 3)
    287                {
    288                    var8 = 40;
    289                }
    290
    291                if (par1World.rand.nextInt(var8) == 0)
    292                {
    293                    int var9 = this.idDropped(par5, par1World.rand, par7);
    294                    this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(var9, 1, this.damageDropped(par5)));
    295                }
    296
    297                if ((par5 & 3) == 0 && par1World.rand.nextInt(200) == 0)
    298                {
    299                    this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(Item.appleRed, 1, 0));
    300                }
    301            }
    302        }
    303
    304        /**
    305         * Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the
    306         * block and l is the block's subtype/damage.
    307         */
    308        public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6)
    309        {
    310            super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
    311        }
    312
    313        /**
    314         * Determines the damage on the item the block drops. Used in cloth and wood.
    315         */
    316        public int damageDropped(int par1)
    317        {
    318            return par1 & 3;
    319        }
    320
    321        /**
    322         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    323         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    324         */
    325        public boolean isOpaqueCube()
    326        {
    327            return !this.graphicsLevel;
    328        }
    329
    330        /**
    331         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
    332         */
    333        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
    334        {
    335            return (par2 & 3) == 1 ? this.blockIndexInTexture + 80 : ((par2 & 3) == 3 ? this.blockIndexInTexture + 144 : this.blockIndexInTexture);
    336        }
    337
    338        @SideOnly(Side.CLIENT)
    339
    340        /**
    341         * Pass true to draw this block using fancy graphics, or false for fast graphics.
    342         */
    343        public void setGraphicsLevel(boolean par1)
    344        {
    345            this.graphicsLevel = par1;
    346            this.blockIndexInTexture = this.baseIndexInPNG + (par1 ? 0 : 1);
    347        }
    348
    349        @SideOnly(Side.CLIENT)
    350
    351        /**
    352         * returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
    353         */
    354        public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List)
    355        {
    356            par3List.add(new ItemStack(par1, 1, 0));
    357            par3List.add(new ItemStack(par1, 1, 1));
    358            par3List.add(new ItemStack(par1, 1, 2));
    359            par3List.add(new ItemStack(par1, 1, 3));
    360        }
    361
    362        @Override
    363        public boolean isShearable(ItemStack item, World world, int x, int y, int z)
    364        {
    365            return true;
    366        }
    367
    368        @Override
    369        public ArrayList<ItemStack> onSheared(ItemStack item, World world, int x, int y, int z, int fortune)
    370        {
    371            ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
    372            ret.add(new ItemStack(this, 1, world.getBlockMetadata(x, y, z) & 3));
    373            return ret;
    374        }
    375
    376        @Override
    377        public void beginLeavesDecay(World world, int x, int y, int z)
    378        {
    379            world.setBlockMetadata(x, y, z, world.getBlockMetadata(x, y, z) | 8);
    380        }
    381
    382        @Override
    383        public boolean isLeaves(World world, int x, int y, int z)
    384        {
    385            return true;
    386        }
    387    }