    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    import net.minecraftforge.common.ForgeDirection;
    007    import static net.minecraftforge.common.ForgeDirection.*;
    008
    009    public class BlockFire extends Block
    010    {
    011        /** The chance this block will encourage nearby blocks to catch on fire */
    012        private int[] chanceToEncourageFire = new int[256];
    013
    014        /**
    015         * This is an array indexed by block ID the larger the number in the array the more likely a block type will catch
    016         * fires
    017         */
    018        private int[] abilityToCatchFire = new int[256];
    019
    020        protected BlockFire(int par1, int par2)
    021        {
    022            super(par1, par2, Material.fire);
    023            this.setTickRandomly(true);
    024        }
    025
    026        /**
    027         * This method is called on a block after all other blocks gets already created. You can use it to reference and
    028         * configure something on the block that needs the others ones.
    029         */
    030        public void initializeBlock()
    031        {
    032            abilityToCatchFire = Block.blockFlammability;
    033            chanceToEncourageFire = Block.blockFireSpreadSpeed;
    034            this.setBurnRate(Block.planks.blockID, 5, 20);
    035            this.setBurnRate(Block.woodDoubleSlab.blockID, 5, 20);
    036            this.setBurnRate(Block.woodSingleSlab.blockID, 5, 20);
    037            this.setBurnRate(Block.fence.blockID, 5, 20);
    038            this.setBurnRate(Block.stairCompactPlanks.blockID, 5, 20);
    039            this.setBurnRate(Block.stairsWoodBirch.blockID, 5, 20);
    040            this.setBurnRate(Block.stairsWoodSpruce.blockID, 5, 20);
    041            this.setBurnRate(Block.stairsWoodJungle.blockID, 5, 20);
    042            this.setBurnRate(Block.wood.blockID, 5, 5);
    043            this.setBurnRate(Block.leaves.blockID, 30, 60);
    044            this.setBurnRate(Block.bookShelf.blockID, 30, 20);
    045            this.setBurnRate(Block.tnt.blockID, 15, 100);
    046            this.setBurnRate(Block.tallGrass.blockID, 60, 100);
    047            this.setBurnRate(Block.cloth.blockID, 30, 60);
    048            this.setBurnRate(Block.vine.blockID, 15, 100);
    049        }
    050
    051        /**
    052         * Sets the burn rate for a block. The larger abilityToCatchFire the more easily it will catch. The larger
    053         * chanceToEncourageFire the faster it will burn and spread to other blocks. Args: blockID, chanceToEncourageFire,
    054         * abilityToCatchFire
    055         */
    056        private void setBurnRate(int par1, int par2, int par3)
    057        {
    058            Block.setBurnProperties(par1, par2, par3);
    059        }
    060
    061        /**
    062         * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    063         * cleared to be reused)
    064         */
    065        public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    066        {
    067            return null;
    068        }
    069
    070        /**
    071         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    072         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    073         */
    074        public boolean isOpaqueCube()
    075        {
    076            return false;
    077        }
    078
    079        /**
    080         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    081         */
    082        public boolean renderAsNormalBlock()
    083        {
    084            return false;
    085        }
    086
    087        /**
    088         * The type of render function that is called for this block
    089         */
    090        public int getRenderType()
    091        {
    092            return 3;
    093        }
    094
    095        /**
    096         * Returns the quantity of items to drop on block destruction.
    097         */
    098        public int quantityDropped(Random par1Random)
    099        {
    100            return 0;
    101        }
    102
    103        /**
    104         * How many world ticks before ticking
    105         */
    106        public int tickRate()
    107        {
    108            return 30;
    109        }
    110
    111        /**
    112         * Ticks the block if it's been scheduled
    113         */
    114        public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
    115        {
    116            if (par1World.func_82736_K().func_82766_b("doFireTick"))
    117            {
    118                Block base = Block.blocksList[par1World.getBlockId(par2, par3 - 1, par4)];
    119                boolean var6 = (base != null && base.isFireSource(par1World, par2, par3 - 1, par4, par1World.getBlockMetadata(par2, par3 - 1, par4), UP));
    120
    121                if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
    122                {
    123                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    124                }
    125
    126                if (!var6 && par1World.isRaining() && (par1World.canLightningStrikeAt(par2, par3, par4) || par1World.canLightningStrikeAt(par2 - 1, par3, par4) || par1World.canLightningStrikeAt(par2 + 1, par3, par4) || par1World.canLightningStrikeAt(par2, par3, par4 - 1) || par1World.canLightningStrikeAt(par2, par3, par4 + 1)))
    127                {
    128                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    129                }
    130                else
    131                {
    132                    int var7 = par1World.getBlockMetadata(par2, par3, par4);
    133
    134                    if (var7 < 15)
    135                    {
    136                        par1World.setBlockMetadata(par2, par3, par4, var7 + par5Random.nextInt(3) / 2);
    137                    }
    138
    139                    par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate() + par5Random.nextInt(10));
    140
    141                    if (!var6 && !this.canNeighborBurn(par1World, par2, par3, par4))
    142                    {
    143                        if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) || var7 > 3)
    144                        {
    145                            par1World.setBlockWithNotify(par2, par3, par4, 0);
    146                        }
    147                    }
    148                    else if (!var6 && !this.canBlockCatchFire(par1World, par2, par3 - 1, par4, UP) && var7 == 15 && par5Random.nextInt(4) == 0)
    149                    {
    150                        par1World.setBlockWithNotify(par2, par3, par4, 0);
    151                    }
    152                    else
    153                    {
    154                        boolean var8 = par1World.isBlockHighHumidity(par2, par3, par4);
    155                        byte var9 = 0;
    156
    157                        if (var8)
    158                        {
    159                            var9 = -50;
    160                        }
    161
    162                        this.tryToCatchBlockOnFire(par1World, par2 + 1, par3, par4, 300 + var9, par5Random, var7, WEST );
    163                        this.tryToCatchBlockOnFire(par1World, par2 - 1, par3, par4, 300 + var9, par5Random, var7, EAST );
    164                        this.tryToCatchBlockOnFire(par1World, par2, par3 - 1, par4, 250 + var9, par5Random, var7, UP   );
    165                        this.tryToCatchBlockOnFire(par1World, par2, par3 + 1, par4, 250 + var9, par5Random, var7, DOWN );
    166                        this.tryToCatchBlockOnFire(par1World, par2, par3, par4 - 1, 300 + var9, par5Random, var7, SOUTH);
    167                        this.tryToCatchBlockOnFire(par1World, par2, par3, par4 + 1, 300 + var9, par5Random, var7, NORTH);
    168
    169                        for (int var10 = par2 - 1; var10 <= par2 + 1; ++var10)
    170                        {
    171                            for (int var11 = par4 - 1; var11 <= par4 + 1; ++var11)
    172                            {
    173                                for (int var12 = par3 - 1; var12 <= par3 + 4; ++var12)
    174                                {
    175                                    if (var10 != par2 || var12 != par3 || var11 != par4)
    176                                    {
    177                                        int var13 = 100;
    178
    179                                        if (var12 > par3 + 1)
    180                                        {
    181                                            var13 += (var12 - (par3 + 1)) * 100;
    182                                        }
    183
    184                                        int var14 = this.getChanceOfNeighborsEncouragingFire(par1World, var10, var12, var11);
    185
    186                                        if (var14 > 0)
    187                                        {
    188                                            int var15 = (var14 + 40 + par1World.difficultySetting * 7) / (var7 + 30);
    189
    190                                            if (var8)
    191                                            {
    192                                                var15 /= 2;
    193                                            }
    194
    195                                            if (var15 > 0 && par5Random.nextInt(var13) <= var15 && (!par1World.isRaining() || !par1World.canLightningStrikeAt(var10, var12, var11)) && !par1World.canLightningStrikeAt(var10 - 1, var12, par4) && !par1World.canLightningStrikeAt(var10 + 1, var12, var11) && !par1World.canLightningStrikeAt(var10, var12, var11 - 1) && !par1World.canLightningStrikeAt(var10, var12, var11 + 1))
    196                                            {
    197                                                int var16 = var7 + par5Random.nextInt(5) / 4;
    198
    199                                                if (var16 > 15)
    200                                                {
    201                                                    var16 = 15;
    202                                                }
    203
    204                                                par1World.setBlockAndMetadataWithNotify(var10, var12, var11, this.blockID, var16);
    205                                            }
    206                                        }
    207                                    }
    208                                }
    209                            }
    210                        }
    211                    }
    212                }
    213            }
    214        }
    215
    216        public boolean func_82506_l()
    217        {
    218            return false;
    219        }
    220
    221        @Deprecated
    222        private void tryToCatchBlockOnFire(World par1World, int par2, int par3, int par4, int par5, Random par6Random, int par7)
    223        {
    224            tryToCatchBlockOnFire(par1World, par2, par3, par4, par5, par6Random, par7, UP);
    225        }
    226
    227        private void tryToCatchBlockOnFire(World par1World, int par2, int par3, int par4, int par5, Random par6Random, int par7, ForgeDirection face)
    228        {
    229            int var8 = 0;
    230            Block block = Block.blocksList[par1World.getBlockId(par2, par3, par4)];
    231            if (block != null)
    232            {
    233                var8 = block.getFlammability(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), face);
    234            }
    235
    236            if (par6Random.nextInt(par5) < var8)
    237            {
    238                boolean var9 = par1World.getBlockId(par2, par3, par4) == Block.tnt.blockID;
    239
    240                if (par6Random.nextInt(par7 + 10) < 5 && !par1World.canLightningStrikeAt(par2, par3, par4))
    241                {
    242                    int var10 = par7 + par6Random.nextInt(5) / 4;
    243
    244                    if (var10 > 15)
    245                    {
    246                        var10 = 15;
    247                    }
    248
    249                    par1World.setBlockAndMetadataWithNotify(par2, par3, par4, this.blockID, var10);
    250                }
    251                else
    252                {
    253                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    254                }
    255
    256                if (var9)
    257                {
    258                    Block.tnt.onBlockDestroyedByPlayer(par1World, par2, par3, par4, 1);
    259                }
    260            }
    261        }
    262
    263        /**
    264         * Returns true if at least one block next to this one can burn.
    265         */
    266        private boolean canNeighborBurn(World par1World, int par2, int par3, int par4)
    267        {
    268            return canBlockCatchFire(par1World, par2 + 1, par3, par4, WEST ) ||
    269                   canBlockCatchFire(par1World, par2 - 1, par3, par4, EAST ) ||
    270                   canBlockCatchFire(par1World, par2, par3 - 1, par4, UP   ) ||
    271                   canBlockCatchFire(par1World, par2, par3 + 1, par4, DOWN ) ||
    272                   canBlockCatchFire(par1World, par2, par3, par4 - 1, SOUTH) ||
    273                   canBlockCatchFire(par1World, par2, par3, par4 + 1, NORTH);
    274        }
    275
    276        /**
    277         * Gets the highest chance of a neighbor block encouraging this block to catch fire
    278         */
    279        private int getChanceOfNeighborsEncouragingFire(World par1World, int par2, int par3, int par4)
    280        {
    281            byte var5 = 0;
    282
    283            if (!par1World.isAirBlock(par2, par3, par4))
    284            {
    285                return 0;
    286            }
    287            else
    288            {
    289                int var6 = this.getChanceToEncourageFire(par1World, par2 + 1, par3, par4, var5, WEST);
    290                var6 = this.getChanceToEncourageFire(par1World, par2 - 1, par3, par4, var6, EAST);
    291                var6 = this.getChanceToEncourageFire(par1World, par2, par3 - 1, par4, var6, UP);
    292                var6 = this.getChanceToEncourageFire(par1World, par2, par3 + 1, par4, var6, DOWN);
    293                var6 = this.getChanceToEncourageFire(par1World, par2, par3, par4 - 1, var6, SOUTH);
    294                var6 = this.getChanceToEncourageFire(par1World, par2, par3, par4 + 1, var6, NORTH);
    295                return var6;
    296            }
    297        }
    298
    299        /**
    300         * Returns if this block is collidable (only used by Fire). Args: x, y, z
    301         */
    302        public boolean isCollidable()
    303        {
    304            return false;
    305        }
    306
    307        /**
    308         * Checks the specified block coordinate to see if it can catch fire.  Args: blockAccess, x, y, z
    309         * Deprecated for a side-sensitive version
    310         */
    311        @Deprecated
    312        public boolean canBlockCatchFire(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    313        {
    314            return canBlockCatchFire(par1IBlockAccess, par2, par3, par4, UP);
    315        }
    316
    317        /**
    318         * Retrieves a specified block's chance to encourage their neighbors to burn and if the number is greater than the
    319         * current number passed in it will return its number instead of the passed in one.  Args: world, x, y, z,
    320         * curChanceToEncourageFire
    321         * Deprecated for a side-sensitive version
    322         */
    323        @Deprecated
    324        public int getChanceToEncourageFire(World par1World, int par2, int par3, int par4, int par5)
    325        {
    326            return getChanceToEncourageFire(par1World, par2, par3, par4, par5, UP);
    327        }
    328
    329        /**
    330         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
    331         */
    332        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    333        {
    334            return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) || this.canNeighborBurn(par1World, par2, par3, par4);
    335        }
    336
    337        /**
    338         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    339         * their own) Args: x, y, z, neighbor blockID
    340         */
    341        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    342        {
    343            if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !this.canNeighborBurn(par1World, par2, par3, par4))
    344            {
    345                par1World.setBlockWithNotify(par2, par3, par4, 0);
    346            }
    347        }
    348
    349        /**
    350         * Called whenever the block is added into the world. Args: world, x, y, z
    351         */
    352        public void onBlockAdded(World par1World, int par2, int par3, int par4)
    353        {
    354            if (par1World.provider.dimensionId > 0 || par1World.getBlockId(par2, par3 - 1, par4) != Block.obsidian.blockID || !Block.portal.tryToCreatePortal(par1World, par2, par3, par4))
    355            {
    356                if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !this.canNeighborBurn(par1World, par2, par3, par4))
    357                {
    358                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    359                }
    360                else
    361                {
    362                    par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate() + par1World.rand.nextInt(10));
    363                }
    364            }
    365        }
    366
    367        @SideOnly(Side.CLIENT)
    368
    369        /**
    370         * A randomly called display update to be able to add particles or other items for display
    371         */
    372        public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random)
    373        {
    374            if (par5Random.nextInt(24) == 0)
    375            {
    376                par1World.playSound((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "fire.fire", 1.0F + par5Random.nextFloat(), par5Random.nextFloat() * 0.7F + 0.3F);
    377            }
    378
    379            int var6;
    380            float var7;
    381            float var8;
    382            float var9;
    383
    384            if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !Block.fire.canBlockCatchFire(par1World, par2, par3 - 1, par4, UP))
    385            {
    386                if (Block.fire.canBlockCatchFire(par1World, par2 - 1, par3, par4, EAST))
    387                {
    388                    for (var6 = 0; var6 < 2; ++var6)
    389                    {
    390                        var7 = (float)par2 + par5Random.nextFloat() * 0.1F;
    391                        var8 = (float)par3 + par5Random.nextFloat();
    392                        var9 = (float)par4 + par5Random.nextFloat();
    393                        par1World.spawnParticle("largesmoke", (double)var7, (double)var8, (double)var9, 0.0D, 0.0D, 0.0D);
    394                    }
    395                }
    396
    397                if (Block.fire.canBlockCatchFire(par1World, par2 + 1, par3, par4, WEST))
    398                {
    399                    for (var6 = 0; var6 < 2; ++var6)
    400                    {
    401                        var7 = (float)(par2 + 1) - par5Random.nextFloat() * 0.1F;
    402                        var8 = (float)par3 + par5Random.nextFloat();
    403                        var9 = (float)par4 + par5Random.nextFloat();
    404                        par1World.spawnParticle("largesmoke", (double)var7, (double)var8, (double)var9, 0.0D, 0.0D, 0.0D);
    405                    }
    406                }
    407
    408                if (Block.fire.canBlockCatchFire(par1World, par2, par3, par4 - 1, SOUTH))
    409                {
    410                    for (var6 = 0; var6 < 2; ++var6)
    411                    {
    412                        var7 = (float)par2 + par5Random.nextFloat();
    413                        var8 = (float)par3 + par5Random.nextFloat();
    414                        var9 = (float)par4 + par5Random.nextFloat() * 0.1F;
    415                        par1World.spawnParticle("largesmoke", (double)var7, (double)var8, (double)var9, 0.0D, 0.0D, 0.0D);
    416                    }
    417                }
    418
    419                if (Block.fire.canBlockCatchFire(par1World, par2, par3, par4 + 1, NORTH))
    420                {
    421                    for (var6 = 0; var6 < 2; ++var6)
    422                    {
    423                        var7 = (float)par2 + par5Random.nextFloat();
    424                        var8 = (float)par3 + par5Random.nextFloat();
    425                        var9 = (float)(par4 + 1) - par5Random.nextFloat() * 0.1F;
    426                        par1World.spawnParticle("largesmoke", (double)var7, (double)var8, (double)var9, 0.0D, 0.0D, 0.0D);
    427                    }
    428                }
    429
    430                if (Block.fire.canBlockCatchFire(par1World, par2, par3 + 1, par4, DOWN))
    431                {
    432                    for (var6 = 0; var6 < 2; ++var6)
    433                    {
    434                        var7 = (float)par2 + par5Random.nextFloat();
    435                        var8 = (float)(par3 + 1) - par5Random.nextFloat() * 0.1F;
    436                        var9 = (float)par4 + par5Random.nextFloat();
    437                        par1World.spawnParticle("largesmoke", (double)var7, (double)var8, (double)var9, 0.0D, 0.0D, 0.0D);
    438                    }
    439                }
    440            }
    441            else
    442            {
    443                for (var6 = 0; var6 < 3; ++var6)
    444                {
    445                    var7 = (float)par2 + par5Random.nextFloat();
    446                    var8 = (float)par3 + par5Random.nextFloat() * 0.5F + 0.5F;
    447                    var9 = (float)par4 + par5Random.nextFloat();
    448                    par1World.spawnParticle("largesmoke", (double)var7, (double)var8, (double)var9, 0.0D, 0.0D, 0.0D);
    449                }
    450            }
    451        }
    452
    453        /**
    454         * Side sensitive version that calls the block function.
    455         *
    456         * @param world The current world
    457         * @param x X Position
    458         * @param y Y Position
    459         * @param z Z Position
    460         * @param face The side the fire is coming from
    461         * @return True if the face can catch fire.
    462         */
    463        public boolean canBlockCatchFire(IBlockAccess world, int x, int y, int z, ForgeDirection face)
    464        {
    465            Block block = Block.blocksList[world.getBlockId(x, y, z)];
    466            if (block != null)
    467            {
    468                return block.isFlammable(world, x, y, z, world.getBlockMetadata(x, y, z), face);
    469            }
    470            return false;
    471        }
    472
    473        /**
    474         * Side sensitive version that calls the block function.
    475         *
    476         * @param world The current world
    477         * @param x X Position
    478         * @param y Y Position
    479         * @param z Z Position
    480         * @param oldChance The previous maximum chance.
    481         * @param face The side the fire is coming from
    482         * @return The chance of the block catching fire, or oldChance if it is higher
    483         */
    484        public int getChanceToEncourageFire(World world, int x, int y, int z, int oldChance, ForgeDirection face)
    485        {
    486            int newChance = 0;
    487            Block block = Block.blocksList[world.getBlockId(x, y, z)];
    488            if (block != null)
    489            {
    490                newChance = block.getFireSpreadSpeed(world, x, y, z, world.getBlockMetadata(x, y, z), face);
    491            }
    492            return (newChance > oldChance ? newChance : oldChance);
    493        }
    494    }