    001    package net.minecraft.world;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005    import net.minecraft.block.Block;
    006    import net.minecraft.block.BlockHalfSlab;
    007    import net.minecraft.block.BlockStairs;
    008    import net.minecraft.block.material.Material;
    009    import net.minecraft.tileentity.TileEntity;
    010    import net.minecraft.util.Vec3Pool;
    011    import net.minecraft.world.biome.BiomeGenBase;
    012    import net.minecraft.world.chunk.Chunk;
    013
    014    public class ChunkCache implements IBlockAccess
    015    {
    016        private int chunkX;
    017        private int chunkZ;
    018        private Chunk[][] chunkArray;
    019
    020        /** set by !chunk.getAreLevelsEmpty */
    021        private boolean hasExtendedLevels;
    022
    023        /** Reference to the World object. */
    024        private World worldObj;
    025
    026        public ChunkCache(World par1World, int par2, int par3, int par4, int par5, int par6, int par7)
    027        {
    028            this.worldObj = par1World;
    029            this.chunkX = par2 >> 4;
    030            this.chunkZ = par4 >> 4;
    031            int var8 = par5 >> 4;
    032            int var9 = par7 >> 4;
    033            this.chunkArray = new Chunk[var8 - this.chunkX + 1][var9 - this.chunkZ + 1];
    034            this.hasExtendedLevels = true;
    035
    036            for (int var10 = this.chunkX; var10 <= var8; ++var10)
    037            {
    038                for (int var11 = this.chunkZ; var11 <= var9; ++var11)
    039                {
    040                    Chunk var12 = par1World.getChunkFromChunkCoords(var10, var11);
    041
    042                    if (var12 != null)
    043                    {
    044                        this.chunkArray[var10 - this.chunkX][var11 - this.chunkZ] = var12;
    045
    046                        if (!var12.getAreLevelsEmpty(par3, par6))
    047                        {
    048                            this.hasExtendedLevels = false;
    049                        }
    050                    }
    051                }
    052            }
    053        }
    054
    055        @SideOnly(Side.CLIENT)
    056
    057        /**
    058         * set by !chunk.getAreLevelsEmpty
    059         */
    060        public boolean extendedLevelsInChunkCache()
    061        {
    062            return this.hasExtendedLevels;
    063        }
    064
    065        /**
    066         * Returns the block ID at coords x,y,z
    067         */
    068        public int getBlockId(int par1, int par2, int par3)
    069        {
    070            if (par2 < 0)
    071            {
    072                return 0;
    073            }
    074            else if (par2 >= 256)
    075            {
    076                return 0;
    077            }
    078            else
    079            {
    080                int var4 = (par1 >> 4) - this.chunkX;
    081                int var5 = (par3 >> 4) - this.chunkZ;
    082
    083                if (var4 >= 0 && var4 < this.chunkArray.length && var5 >= 0 && var5 < this.chunkArray[var4].length)
    084                {
    085                    Chunk var6 = this.chunkArray[var4][var5];
    086                    return var6 == null ? 0 : var6.getBlockID(par1 & 15, par2, par3 & 15);
    087                }
    088                else
    089                {
    090                    return 0;
    091                }
    092            }
    093        }
    094
    095        /**
    096         * Returns the TileEntity associated with a given block in X,Y,Z coordinates, or null if no TileEntity exists
    097         */
    098        public TileEntity getBlockTileEntity(int par1, int par2, int par3)
    099        {
    100            int var4 = (par1 >> 4) - this.chunkX;
    101            int var5 = (par3 >> 4) - this.chunkZ;
    102            if (var4 >= 0 && var4 < this.chunkArray.length && var5 >= 0 && var5 < this.chunkArray[var4].length)
    103            {
    104                Chunk var6 = this.chunkArray[var4][var5];
    105                return var6 == null ? null : var6.getChunkBlockTileEntity(par1 & 15, par2, par3 & 15);
    106            }
    107            else
    108            {
    109                return null;
    110            }
    111        }
    112
    113        @SideOnly(Side.CLIENT)
    114        public float getBrightness(int par1, int par2, int par3, int par4)
    115        {
    116            int var5 = this.getLightValue(par1, par2, par3);
    117
    118            if (var5 < par4)
    119            {
    120                var5 = par4;
    121            }
    122
    123            return this.worldObj.provider.lightBrightnessTable[var5];
    124        }
    125
    126        @SideOnly(Side.CLIENT)
    127
    128        /**
    129         * Any Light rendered on a 1.8 Block goes through here
    130         */
    131        public int getLightBrightnessForSkyBlocks(int par1, int par2, int par3, int par4)
    132        {
    133            int var5 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Sky, par1, par2, par3);
    134            int var6 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Block, par1, par2, par3);
    135
    136            if (var6 < par4)
    137            {
    138                var6 = par4;
    139            }
    140
    141            return var5 << 20 | var6 << 4;
    142        }
    143
    144        @SideOnly(Side.CLIENT)
    145
    146        /**
    147         * Returns how bright the block is shown as which is the block's light value looked up in a lookup table (light
    148         * values aren't linear for brightness). Args: x, y, z
    149         */
    150        public float getLightBrightness(int par1, int par2, int par3)
    151        {
    152            return this.worldObj.provider.lightBrightnessTable[this.getLightValue(par1, par2, par3)];
    153        }
    154
    155        @SideOnly(Side.CLIENT)
    156
    157        /**
    158         * Gets the light value of the specified block coords. Args: x, y, z
    159         */
    160        public int getLightValue(int par1, int par2, int par3)
    161        {
    162            return this.getLightValueExt(par1, par2, par3, true);
    163        }
    164
    165        @SideOnly(Side.CLIENT)
    166
    167        /**
    168         * Get light value with flag
    169         */
    170        public int getLightValueExt(int par1, int par2, int par3, boolean par4)
    171        {
    172            if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 <= 30000000)
    173            {
    174                int var5;
    175                int var6;
    176
    177                if (par4)
    178                {
    179                    var5 = this.getBlockId(par1, par2, par3);
    180
    181                    if (var5 == Block.stoneSingleSlab.blockID || var5 == Block.woodSingleSlab.blockID || var5 == Block.tilledField.blockID || var5 == Block.stairCompactPlanks.blockID || var5 == Block.stairCompactCobblestone.blockID)
    182                    {
    183                        var6 = this.getLightValueExt(par1, par2 + 1, par3, false);
    184                        int var7 = this.getLightValueExt(par1 + 1, par2, par3, false);
    185                        int var8 = this.getLightValueExt(par1 - 1, par2, par3, false);
    186                        int var9 = this.getLightValueExt(par1, par2, par3 + 1, false);
    187                        int var10 = this.getLightValueExt(par1, par2, par3 - 1, false);
    188
    189                        if (var7 > var6)
    190                        {
    191                            var6 = var7;
    192                        }
    193
    194                        if (var8 > var6)
    195                        {
    196                            var6 = var8;
    197                        }
    198
    199                        if (var9 > var6)
    200                        {
    201                            var6 = var9;
    202                        }
    203
    204                        if (var10 > var6)
    205                        {
    206                            var6 = var10;
    207                        }
    208
    209                        return var6;
    210                    }
    211                }
    212
    213                if (par2 < 0)
    214                {
    215                    return 0;
    216                }
    217                else if (par2 >= 256)
    218                {
    219                    var5 = 15 - this.worldObj.skylightSubtracted;
    220
    221                    if (var5 < 0)
    222                    {
    223                        var5 = 0;
    224                    }
    225
    226                    return var5;
    227                }
    228                else
    229                {
    230                    var5 = (par1 >> 4) - this.chunkX;
    231                    var6 = (par3 >> 4) - this.chunkZ;
    232                    return this.chunkArray[var5][var6].getBlockLightValue(par1 & 15, par2, par3 & 15, this.worldObj.skylightSubtracted);
    233                }
    234            }
    235            else
    236            {
    237                return 15;
    238            }
    239        }
    240
    241        /**
    242         * Returns the block metadata at coords x,y,z
    243         */
    244        public int getBlockMetadata(int par1, int par2, int par3)
    245        {
    246            if (par2 < 0)
    247            {
    248                return 0;
    249            }
    250            else if (par2 >= 256)
    251            {
    252                return 0;
    253            }
    254            else
    255            {
    256                int var4 = (par1 >> 4) - this.chunkX;
    257                int var5 = (par3 >> 4) - this.chunkZ;
    258                if (var4 >= 0 && var4 < this.chunkArray.length && var5 >= 0 && var5 < this.chunkArray[var4].length)
    259                {
    260                    Chunk var6 = this.chunkArray[var4][var5];
    261                    return var6 == null ? 0 : var6.getBlockMetadata(par1 & 15, par2, par3 & 15);
    262                }
    263                return 0;
    264            }
    265        }
    266
    267        /**
    268         * Returns the block's material.
    269         */
    270        public Material getBlockMaterial(int par1, int par2, int par3)
    271        {
    272            int var4 = this.getBlockId(par1, par2, par3);
    273            return var4 == 0 ? Material.air : Block.blocksList[var4].blockMaterial;
    274        }
    275
    276        @SideOnly(Side.CLIENT)
    277
    278        /**
    279         * Gets the biome for a given set of x/z coordinates
    280         */
    281        public BiomeGenBase getBiomeGenForCoords(int par1, int par2)
    282        {
    283            return this.worldObj.getBiomeGenForCoords(par1, par2);
    284        }
    285
    286        @SideOnly(Side.CLIENT)
    287
    288        /**
    289         * Returns true if the block at the specified coordinates is an opaque cube. Args: x, y, z
    290         */
    291        public boolean isBlockOpaqueCube(int par1, int par2, int par3)
    292        {
    293            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
    294            return var4 == null ? false : var4.isOpaqueCube();
    295        }
    296
    297        /**
    298         * Indicate if a material is a normal solid opaque cube.
    299         */
    300        public boolean isBlockNormalCube(int par1, int par2, int par3)
    301        {
    302            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
    303            return var4 == null ? false : var4.blockMaterial.blocksMovement() && var4.renderAsNormalBlock();
    304        }
    305
    306        @SideOnly(Side.CLIENT)
    307
    308        /**
    309         * Returns true if the block at the given coordinate has a solid (buildable) top surface.
    310         */
    311        public boolean doesBlockHaveSolidTopSurface(int par1, int par2, int par3)
    312        {
    313            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
    314            return var4 == null ? false : (var4.blockMaterial.isOpaque() && var4.renderAsNormalBlock() ? true : (var4 instanceof BlockStairs ? (this.getBlockMetadata(par1, par2, par3) & 4) == 4 : (var4 instanceof BlockHalfSlab ? (this.getBlockMetadata(par1, par2, par3) & 8) == 8 : false)));
    315        }
    316
    317        /**
    318         * Return the Vec3Pool object for this world.
    319         */
    320        public Vec3Pool getWorldVec3Pool()
    321        {
    322            return this.worldObj.getWorldVec3Pool();
    323        }
    324
    325        @SideOnly(Side.CLIENT)
    326
    327        /**
    328         * Returns true if the block at the specified coordinates is empty
    329         */
    330        public boolean isAirBlock(int par1, int par2, int par3)
    331        {
    332            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
    333            return var4 == null;
    334        }
    335
    336        @SideOnly(Side.CLIENT)
    337
    338        /**
    339         * Brightness for SkyBlock.Sky is clear white and (through color computing it is assumed) DEPENDENT ON DAYTIME.
    340         * Brightness for SkyBlock.Block is yellowish and independent.
    341         */
    342        public int getSkyBlockTypeBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
    343        {
    344            if (par3 < 0)
    345            {
    346                par3 = 0;
    347            }
    348
    349            if (par3 >= 256)
    350            {
    351                par3 = 255;
    352            }
    353
    354            if (par3 >= 0 && par3 < 256 && par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 <= 30000000)
    355            {
    356                if (par1EnumSkyBlock == EnumSkyBlock.Sky && this.worldObj.provider.hasNoSky)
    357                {
    358                    return 0;
    359                }
    360                else
    361                {
    362                    int var5;
    363                    int var6;
    364
    365                    if (Block.useNeighborBrightness[this.getBlockId(par2, par3, par4)])
    366                    {
    367                        var5 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3 + 1, par4);
    368                        var6 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2 + 1, par3, par4);
    369                        int var7 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2 - 1, par3, par4);
    370                        int var8 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3, par4 + 1);
    371                        int var9 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3, par4 - 1);
    372
    373                        if (var6 > var5)
    374                        {
    375                            var5 = var6;
    376                        }
    377
    378                        if (var7 > var5)
    379                        {
    380                            var5 = var7;
    381                        }
    382
    383                        if (var8 > var5)
    384                        {
    385                            var5 = var8;
    386                        }
    387
    388                        if (var9 > var5)
    389                        {
    390                            var5 = var9;
    391                        }
    392
    393                        return var5;
    394                    }
    395                    else
    396                    {
    397                        var5 = (par2 >> 4) - this.chunkX;
    398                        var6 = (par4 >> 4) - this.chunkZ;
    399                        return this.chunkArray[var5][var6].getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
    400                    }
    401                }
    402            }
    403            else
    404            {
    405                return par1EnumSkyBlock.defaultLightValue;
    406            }
    407        }
    408
    409        @SideOnly(Side.CLIENT)
    410
    411        /**
    412         * is only used on stairs and tilled fields
    413         */
    414        public int getSpecialBlockBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
    415        {
    416            if (par3 < 0)
    417            {
    418                par3 = 0;
    419            }
    420
    421            if (par3 >= 256)
    422            {
    423                par3 = 255;
    424            }
    425
    426            if (par3 >= 0 && par3 < 256 && par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 <= 30000000)
    427            {
    428                int var5 = (par2 >> 4) - this.chunkX;
    429                int var6 = (par4 >> 4) - this.chunkZ;
    430                return this.chunkArray[var5][var6].getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
    431            }
    432            else
    433            {
    434                return par1EnumSkyBlock.defaultLightValue;
    435            }
    436        }
    437
    438        @SideOnly(Side.CLIENT)
    439
    440        /**
    441         * Returns current world height.
    442         */
    443        public int getHeight()
    444        {
    445            return 256;
    446        }
    447
    448        /**
    449         * Is this block powering in the specified direction Args: x, y, z, direction
    450         */
    451        public boolean isBlockProvidingPowerTo(int par1, int par2, int par3, int par4)
    452        {
    453            int var5 = this.getBlockId(par1, par2, par3);
    454            return var5 == 0 ? false : Block.blocksList[var5].isProvidingStrongPower(this, par1, par2, par3, par4);
    455        }
    456    }