    001package net.minecraft.world;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import net.minecraft.block.Block;
    006import net.minecraft.block.BlockHalfSlab;
    007import net.minecraft.block.BlockStairs;
    008import net.minecraft.block.material.Material;
    009import net.minecraft.tileentity.TileEntity;
    010import net.minecraft.util.Vec3Pool;
    011import net.minecraft.world.biome.BiomeGenBase;
    012import net.minecraft.world.chunk.Chunk;
    013
    014public 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    public 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}