    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.util.Random;
    006
    007    public abstract class BlockFluid extends Block
    008    {
    009        protected BlockFluid(int par1, Material par2Material)
    010        {
    011            super(par1, (par2Material == Material.lava ? 14 : 12) * 16 + 13, par2Material);
    012            float var3 = 0.0F;
    013            float var4 = 0.0F;
    014            this.setBlockBounds(0.0F + var4, 0.0F + var3, 0.0F + var4, 1.0F + var4, 1.0F + var3, 1.0F + var4);
    015            this.setTickRandomly(true);
    016        }
    017
    018        public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    019        {
    020            return this.blockMaterial != Material.lava;
    021        }
    022
    023        @SideOnly(Side.CLIENT)
    024        public int getBlockColor()
    025        {
    026            return 16777215;
    027        }
    028
    029        @SideOnly(Side.CLIENT)
    030
    031        /**
    032         * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called
    033         * when first determining what to render.
    034         */
    035        public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    036        {
    037            if (this.blockMaterial != Material.water)
    038            {
    039                return 16777215;
    040            }
    041            else
    042            {
    043                int var5 = 0;
    044                int var6 = 0;
    045                int var7 = 0;
    046
    047                for (int var8 = -1; var8 <= 1; ++var8)
    048                {
    049                    for (int var9 = -1; var9 <= 1; ++var9)
    050                    {
    051                        int var10 = par1IBlockAccess.getBiomeGenForCoords(par2 + var9, par4 + var8).waterColorMultiplier;
    052                        var5 += (var10 & 16711680) >> 16;
    053                        var6 += (var10 & 65280) >> 8;
    054                        var7 += var10 & 255;
    055                    }
    056                }
    057
    058                return (var5 / 9 & 255) << 16 | (var6 / 9 & 255) << 8 | var7 / 9 & 255;
    059            }
    060        }
    061
    062        /**
    063         * Returns the percentage of the fluid block that is air, based on the given flow decay of the fluid.
    064         */
    065        public static float getFluidHeightPercent(int par0)
    066        {
    067            if (par0 >= 8)
    068            {
    069                par0 = 0;
    070            }
    071
    072            return (float)(par0 + 1) / 9.0F;
    073        }
    074
    075        /**
    076         * Returns the block texture based on the side being looked at.  Args: side
    077         */
    078        public int getBlockTextureFromSide(int par1)
    079        {
    080            return par1 != 0 && par1 != 1 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture;
    081        }
    082
    083        /**
    084         * Returns the amount of fluid decay at the coordinates, or -1 if the block at the coordinates is not the same
    085         * material as the fluid.
    086         */
    087        protected int getFlowDecay(World par1World, int par2, int par3, int par4)
    088        {
    089            return par1World.getBlockMaterial(par2, par3, par4) == this.blockMaterial ? par1World.getBlockMetadata(par2, par3, par4) : -1;
    090        }
    091
    092        /**
    093         * Returns the flow decay but converts values indicating falling liquid (values >=8) to their effective source block
    094         * value of zero.
    095         */
    096        protected int getEffectiveFlowDecay(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    097        {
    098            if (par1IBlockAccess.getBlockMaterial(par2, par3, par4) != this.blockMaterial)
    099            {
    100                return -1;
    101            }
    102            else
    103            {
    104                int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    105
    106                if (var5 >= 8)
    107                {
    108                    var5 = 0;
    109                }
    110
    111                return var5;
    112            }
    113        }
    114
    115        /**
    116         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    117         */
    118        public boolean renderAsNormalBlock()
    119        {
    120            return false;
    121        }
    122
    123        /**
    124         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    125         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    126         */
    127        public boolean isOpaqueCube()
    128        {
    129            return false;
    130        }
    131
    132        /**
    133         * Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag
    134         */
    135        public boolean canCollideCheck(int par1, boolean par2)
    136        {
    137            return par2 && par1 == 0;
    138        }
    139
    140        /**
    141         * Returns Returns true if the given side of this block type should be rendered (if it's solid or not), if the
    142         * adjacent block is at the given coordinates. Args: blockAccess, x, y, z, side
    143         */
    144        public boolean isBlockSolid(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    145        {
    146            Material var6 = par1IBlockAccess.getBlockMaterial(par2, par3, par4);
    147            return var6 == this.blockMaterial ? false : (par5 == 1 ? true : (var6 == Material.ice ? false : super.isBlockSolid(par1IBlockAccess, par2, par3, par4, par5)));
    148        }
    149
    150        @SideOnly(Side.CLIENT)
    151
    152        /**
    153         * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
    154         * coordinates.  Args: blockAccess, x, y, z, side
    155         */
    156        public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    157        {
    158            Material var6 = par1IBlockAccess.getBlockMaterial(par2, par3, par4);
    159            return var6 == this.blockMaterial ? false : (par5 == 1 ? true : (var6 == Material.ice ? false : super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5)));
    160        }
    161
    162        /**
    163         * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    164         * cleared to be reused)
    165         */
    166        public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    167        {
    168            return null;
    169        }
    170
    171        /**
    172         * The type of render function that is called for this block
    173         */
    174        public int getRenderType()
    175        {
    176            return 4;
    177        }
    178
    179        /**
    180         * Returns the ID of the items to drop on destruction.
    181         */
    182        public int idDropped(int par1, Random par2Random, int par3)
    183        {
    184            return 0;
    185        }
    186
    187        /**
    188         * Returns the quantity of items to drop on block destruction.
    189         */
    190        public int quantityDropped(Random par1Random)
    191        {
    192            return 0;
    193        }
    194
    195        /**
    196         * Returns a vector indicating the direction and intensity of fluid flow.
    197         */
    198        private Vec3 getFlowVector(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    199        {
    200            Vec3 var5 = par1IBlockAccess.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D);
    201            int var6 = this.getEffectiveFlowDecay(par1IBlockAccess, par2, par3, par4);
    202
    203            for (int var7 = 0; var7 < 4; ++var7)
    204            {
    205                int var8 = par2;
    206                int var10 = par4;
    207
    208                if (var7 == 0)
    209                {
    210                    var8 = par2 - 1;
    211                }
    212
    213                if (var7 == 1)
    214                {
    215                    var10 = par4 - 1;
    216                }
    217
    218                if (var7 == 2)
    219                {
    220                    ++var8;
    221                }
    222
    223                if (var7 == 3)
    224                {
    225                    ++var10;
    226                }
    227
    228                int var11 = this.getEffectiveFlowDecay(par1IBlockAccess, var8, par3, var10);
    229                int var12;
    230
    231                if (var11 < 0)
    232                {
    233                    if (!par1IBlockAccess.getBlockMaterial(var8, par3, var10).blocksMovement())
    234                    {
    235                        var11 = this.getEffectiveFlowDecay(par1IBlockAccess, var8, par3 - 1, var10);
    236
    237                        if (var11 >= 0)
    238                        {
    239                            var12 = var11 - (var6 - 8);
    240                            var5 = var5.addVector((double)((var8 - par2) * var12), (double)((par3 - par3) * var12), (double)((var10 - par4) * var12));
    241                        }
    242                    }
    243                }
    244                else if (var11 >= 0)
    245                {
    246                    var12 = var11 - var6;
    247                    var5 = var5.addVector((double)((var8 - par2) * var12), (double)((par3 - par3) * var12), (double)((var10 - par4) * var12));
    248                }
    249            }
    250
    251            if (par1IBlockAccess.getBlockMetadata(par2, par3, par4) >= 8)
    252            {
    253                boolean var13 = false;
    254
    255                if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3, par4 - 1, 2))
    256                {
    257                    var13 = true;
    258                }
    259
    260                if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3, par4 + 1, 3))
    261                {
    262                    var13 = true;
    263                }
    264
    265                if (var13 || this.isBlockSolid(par1IBlockAccess, par2 - 1, par3, par4, 4))
    266                {
    267                    var13 = true;
    268                }
    269
    270                if (var13 || this.isBlockSolid(par1IBlockAccess, par2 + 1, par3, par4, 5))
    271                {
    272                    var13 = true;
    273                }
    274
    275                if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3 + 1, par4 - 1, 2))
    276                {
    277                    var13 = true;
    278                }
    279
    280                if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3 + 1, par4 + 1, 3))
    281                {
    282                    var13 = true;
    283                }
    284
    285                if (var13 || this.isBlockSolid(par1IBlockAccess, par2 - 1, par3 + 1, par4, 4))
    286                {
    287                    var13 = true;
    288                }
    289
    290                if (var13 || this.isBlockSolid(par1IBlockAccess, par2 + 1, par3 + 1, par4, 5))
    291                {
    292                    var13 = true;
    293                }
    294
    295                if (var13)
    296                {
    297                    var5 = var5.normalize().addVector(0.0D, -6.0D, 0.0D);
    298                }
    299            }
    300
    301            var5 = var5.normalize();
    302            return var5;
    303        }
    304
    305        /**
    306         * Can add to the passed in vector for a movement vector to be applied to the entity. Args: x, y, z, entity, vec3d
    307         */
    308        public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3)
    309        {
    310            Vec3 var7 = this.getFlowVector(par1World, par2, par3, par4);
    311            par6Vec3.xCoord += var7.xCoord;
    312            par6Vec3.yCoord += var7.yCoord;
    313            par6Vec3.zCoord += var7.zCoord;
    314        }
    315
    316        /**
    317         * How many world ticks before ticking
    318         */
    319        public int tickRate()
    320        {
    321            return this.blockMaterial == Material.water ? 5 : (this.blockMaterial == Material.lava ? 30 : 0);
    322        }
    323
    324        @SideOnly(Side.CLIENT)
    325
    326        /**
    327         * Goes straight to getLightBrightnessForSkyBlocks for Blocks, does some fancy computing for Fluids
    328         */
    329        public int getMixedBrightnessForBlock(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    330        {
    331            int var5 = par1IBlockAccess.getLightBrightnessForSkyBlocks(par2, par3, par4, 0);
    332            int var6 = par1IBlockAccess.getLightBrightnessForSkyBlocks(par2, par3 + 1, par4, 0);
    333            int var7 = var5 & 255;
    334            int var8 = var6 & 255;
    335            int var9 = var5 >> 16 & 255;
    336            int var10 = var6 >> 16 & 255;
    337            return (var7 > var8 ? var7 : var8) | (var9 > var10 ? var9 : var10) << 16;
    338        }
    339
    340        @SideOnly(Side.CLIENT)
    341
    342        /**
    343         * How bright to render this block based on the light its receiving. Args: iBlockAccess, x, y, z
    344         */
    345        public float getBlockBrightness(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    346        {
    347            float var5 = par1IBlockAccess.getLightBrightness(par2, par3, par4);
    348            float var6 = par1IBlockAccess.getLightBrightness(par2, par3 + 1, par4);
    349            return var5 > var6 ? var5 : var6;
    350        }
    351
    352        @SideOnly(Side.CLIENT)
    353
    354        /**
    355         * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha
    356         */
    357        public int getRenderBlockPass()
    358        {
    359            return this.blockMaterial == Material.water ? 1 : 0;
    360        }
    361
    362        @SideOnly(Side.CLIENT)
    363
    364        /**
    365         * A randomly called display update to be able to add particles or other items for display
    366         */
    367        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
    368        {
    369            int var6;
    370
    371            if (this.blockMaterial == Material.water)
    372            {
    373                if (par5Random.nextInt(10) == 0)
    374                {
    375                    var6 = par1World.getBlockMetadata(par2, par3, par4);
    376
    377                    if (var6 <= 0 || var6 >= 8)
    378                    {
    379                        par1World.spawnParticle("suspended", (double)((float)par2 + par5Random.nextFloat()), (double)((float)par3 + par5Random.nextFloat()), (double)((float)par4 + par5Random.nextFloat()), 0.0D, 0.0D, 0.0D);
    380                    }
    381                }
    382
    383                for (var6 = 0; var6 < 0; ++var6)
    384                {
    385                    int var7 = par5Random.nextInt(4);
    386                    int var8 = par2;
    387                    int var9 = par4;
    388
    389                    if (var7 == 0)
    390                    {
    391                        var8 = par2 - 1;
    392                    }
    393
    394                    if (var7 == 1)
    395                    {
    396                        ++var8;
    397                    }
    398
    399                    if (var7 == 2)
    400                    {
    401                        var9 = par4 - 1;
    402                    }
    403
    404                    if (var7 == 3)
    405                    {
    406                        ++var9;
    407                    }
    408
    409                    if (par1World.getBlockMaterial(var8, par3, var9) == Material.air && (par1World.getBlockMaterial(var8, par3 - 1, var9).blocksMovement() || par1World.getBlockMaterial(var8, par3 - 1, var9).isLiquid()))
    410                    {
    411                        float var10 = 0.0625F;
    412                        double var11 = (double)((float)par2 + par5Random.nextFloat());
    413                        double var13 = (double)((float)par3 + par5Random.nextFloat());
    414                        double var15 = (double)((float)par4 + par5Random.nextFloat());
    415
    416                        if (var7 == 0)
    417                        {
    418                            var11 = (double)((float)par2 - var10);
    419                        }
    420
    421                        if (var7 == 1)
    422                        {
    423                            var11 = (double)((float)(par2 + 1) + var10);
    424                        }
    425
    426                        if (var7 == 2)
    427                        {
    428                            var15 = (double)((float)par4 - var10);
    429                        }
    430
    431                        if (var7 == 3)
    432                        {
    433                            var15 = (double)((float)(par4 + 1) + var10);
    434                        }
    435
    436                        double var17 = 0.0D;
    437                        double var19 = 0.0D;
    438
    439                        if (var7 == 0)
    440                        {
    441                            var17 = (double)(-var10);
    442                        }
    443
    444                        if (var7 == 1)
    445                        {
    446                            var17 = (double)var10;
    447                        }
    448
    449                        if (var7 == 2)
    450                        {
    451                            var19 = (double)(-var10);
    452                        }
    453
    454                        if (var7 == 3)
    455                        {
    456                            var19 = (double)var10;
    457                        }
    458
    459                        par1World.spawnParticle("splash", var11, var13, var15, var17, 0.0D, var19);
    460                    }
    461                }
    462            }
    463
    464            if (this.blockMaterial == Material.water && par5Random.nextInt(64) == 0)
    465            {
    466                var6 = par1World.getBlockMetadata(par2, par3, par4);
    467
    468                if (var6 > 0 && var6 < 8)
    469                {
    470                    par1World.playSound((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "liquid.water", par5Random.nextFloat() * 0.25F + 0.75F, par5Random.nextFloat() * 1.0F + 0.5F);
    471                }
    472            }
    473
    474            double var21;
    475            double var23;
    476            double var22;
    477
    478            if (this.blockMaterial == Material.lava && par1World.getBlockMaterial(par2, par3 + 1, par4) == Material.air && !par1World.isBlockOpaqueCube(par2, par3 + 1, par4))
    479            {
    480                if (par5Random.nextInt(100) == 0)
    481                {
    482                    var21 = (double)((float)par2 + par5Random.nextFloat());
    483                    var22 = (double)par3 + this.maxY;
    484                    var23 = (double)((float)par4 + par5Random.nextFloat());
    485                    par1World.spawnParticle("lava", var21, var22, var23, 0.0D, 0.0D, 0.0D);
    486                    par1World.playSound(var21, var22, var23, "liquid.lavapop", 0.2F + par5Random.nextFloat() * 0.2F, 0.9F + par5Random.nextFloat() * 0.15F);
    487                }
    488
    489                if (par5Random.nextInt(200) == 0)
    490                {
    491                    par1World.playSound((double)par2, (double)par3, (double)par4, "liquid.lava", 0.2F + par5Random.nextFloat() * 0.2F, 0.9F + par5Random.nextFloat() * 0.15F);
    492                }
    493            }
    494
    495            if (par5Random.nextInt(10) == 0 && par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !par1World.getBlockMaterial(par2, par3 - 2, par4).blocksMovement())
    496            {
    497                var21 = (double)((float)par2 + par5Random.nextFloat());
    498                var22 = (double)par3 - 1.05D;
    499                var23 = (double)((float)par4 + par5Random.nextFloat());
    500
    501                if (this.blockMaterial == Material.water)
    502                {
    503                    par1World.spawnParticle("dripWater", var21, var22, var23, 0.0D, 0.0D, 0.0D);
    504                }
    505                else
    506                {
    507                    par1World.spawnParticle("dripLava", var21, var22, var23, 0.0D, 0.0D, 0.0D);
    508                }
    509            }
    510        }
    511
    512        @SideOnly(Side.CLIENT)
    513
    514        /**
    515         * the sin and cos of this number determine the surface gradient of the flowing block.
    516         */
    517        public static double getFlowDirection(IBlockAccess par0IBlockAccess, int par1, int par2, int par3, Material par4Material)
    518        {
    519            Vec3 var5 = null;
    520
    521            if (par4Material == Material.water)
    522            {
    523                var5 = ((BlockFluid)Block.waterMoving).getFlowVector(par0IBlockAccess, par1, par2, par3);
    524            }
    525
    526            if (par4Material == Material.lava)
    527            {
    528                var5 = ((BlockFluid)Block.lavaMoving).getFlowVector(par0IBlockAccess, par1, par2, par3);
    529            }
    530
    531            return var5.xCoord == 0.0D && var5.zCoord == 0.0D ? -1000.0D : Math.atan2(var5.zCoord, var5.xCoord) - (Math.PI / 2D);
    532        }
    533
    534        /**
    535         * Called whenever the block is added into the world. Args: world, x, y, z
    536         */
    537        public void onBlockAdded(World par1World, int par2, int par3, int par4)
    538        {
    539            this.checkForHarden(par1World, par2, par3, par4);
    540        }
    541
    542        /**
    543         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    544         * their own) Args: x, y, z, neighbor blockID
    545         */
    546        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    547        {
    548            this.checkForHarden(par1World, par2, par3, par4);
    549        }
    550
    551        /**
    552         * Forces lava to check to see if it is colliding with water, and then decide what it should harden to.
    553         */
    554        private void checkForHarden(World par1World, int par2, int par3, int par4)
    555        {
    556            if (par1World.getBlockId(par2, par3, par4) == this.blockID)
    557            {
    558                if (this.blockMaterial == Material.lava)
    559                {
    560                    boolean var5 = false;
    561
    562                    if (var5 || par1World.getBlockMaterial(par2, par3, par4 - 1) == Material.water)
    563                    {
    564                        var5 = true;
    565                    }
    566
    567                    if (var5 || par1World.getBlockMaterial(par2, par3, par4 + 1) == Material.water)
    568                    {
    569                        var5 = true;
    570                    }
    571
    572                    if (var5 || par1World.getBlockMaterial(par2 - 1, par3, par4) == Material.water)
    573                    {
    574                        var5 = true;
    575                    }
    576
    577                    if (var5 || par1World.getBlockMaterial(par2 + 1, par3, par4) == Material.water)
    578                    {
    579                        var5 = true;
    580                    }
    581
    582                    if (var5 || par1World.getBlockMaterial(par2, par3 + 1, par4) == Material.water)
    583                    {
    584                        var5 = true;
    585                    }
    586
    587                    if (var5)
    588                    {
    589                        int var6 = par1World.getBlockMetadata(par2, par3, par4);
    590
    591                        if (var6 == 0)
    592                        {
    593                            par1World.setBlockWithNotify(par2, par3, par4, Block.obsidian.blockID);
    594                        }
    595                        else if (var6 <= 4)
    596                        {
    597                            par1World.setBlockWithNotify(par2, par3, par4, Block.cobblestone.blockID);
    598                        }
    599
    600                        this.triggerLavaMixEffects(par1World, par2, par3, par4);
    601                    }
    602                }
    603            }
    604        }
    605
    606        /**
    607         * Creates fizzing sound and smoke. Used when lava flows over block or mixes with water.
    608         */
    609        protected void triggerLavaMixEffects(World par1World, int par2, int par3, int par4)
    610        {
    611            par1World.playSoundEffect((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "random.fizz", 0.5F, 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F);
    612
    613            for (int var5 = 0; var5 < 8; ++var5)
    614            {
    615                par1World.spawnParticle("largesmoke", (double)par2 + Math.random(), (double)par3 + 1.2D, (double)par4 + Math.random(), 0.0D, 0.0D, 0.0D);
    616            }
    617        }
    618    }