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