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            if (var4 >= 0 && var4 < this.chunkArray.length && var5 >= 0 && var5 < this.chunkArray[var4].length)
095            {
096                Chunk var6 = this.chunkArray[var4][var5];
097                return var6 == null ? null : var6.getChunkBlockTileEntity(par1 & 15, par2, par3 & 15);
098            }
099            else
100            {
101                return null;
102            }
103        }
104    
105        @SideOnly(Side.CLIENT)
106        public float getBrightness(int par1, int par2, int par3, int par4)
107        {
108            int var5 = this.getLightValue(par1, par2, par3);
109    
110            if (var5 < par4)
111            {
112                var5 = par4;
113            }
114    
115            return this.worldObj.provider.lightBrightnessTable[var5];
116        }
117    
118        @SideOnly(Side.CLIENT)
119    
120        /**
121         * Any Light rendered on a 1.8 Block goes through here
122         */
123        public int getLightBrightnessForSkyBlocks(int par1, int par2, int par3, int par4)
124        {
125            int var5 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Sky, par1, par2, par3);
126            int var6 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Block, par1, par2, par3);
127    
128            if (var6 < par4)
129            {
130                var6 = par4;
131            }
132    
133            return var5 << 20 | var6 << 4;
134        }
135    
136        @SideOnly(Side.CLIENT)
137    
138        /**
139         * Returns how bright the block is shown as which is the block's light value looked up in a lookup table (light
140         * values aren't linear for brightness). Args: x, y, z
141         */
142        public float getLightBrightness(int par1, int par2, int par3)
143        {
144            return this.worldObj.provider.lightBrightnessTable[this.getLightValue(par1, par2, par3)];
145        }
146    
147        @SideOnly(Side.CLIENT)
148    
149        /**
150         * Gets the light value of the specified block coords. Args: x, y, z
151         */
152        public int getLightValue(int par1, int par2, int par3)
153        {
154            return this.getLightValueExt(par1, par2, par3, true);
155        }
156    
157        @SideOnly(Side.CLIENT)
158    
159        /**
160         * Get light value with flag
161         */
162        public int getLightValueExt(int par1, int par2, int par3, boolean par4)
163        {
164            if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 <= 30000000)
165            {
166                int var5;
167                int var6;
168    
169                if (par4)
170                {
171                    var5 = this.getBlockId(par1, par2, par3);
172    
173                    if (var5 == Block.stoneSingleSlab.blockID || var5 == Block.woodSingleSlab.blockID || var5 == Block.tilledField.blockID || var5 == Block.stairCompactPlanks.blockID || var5 == Block.stairCompactCobblestone.blockID)
174                    {
175                        var6 = this.getLightValueExt(par1, par2 + 1, par3, false);
176                        int var7 = this.getLightValueExt(par1 + 1, par2, par3, false);
177                        int var8 = this.getLightValueExt(par1 - 1, par2, par3, false);
178                        int var9 = this.getLightValueExt(par1, par2, par3 + 1, false);
179                        int var10 = this.getLightValueExt(par1, par2, par3 - 1, false);
180    
181                        if (var7 > var6)
182                        {
183                            var6 = var7;
184                        }
185    
186                        if (var8 > var6)
187                        {
188                            var6 = var8;
189                        }
190    
191                        if (var9 > var6)
192                        {
193                            var6 = var9;
194                        }
195    
196                        if (var10 > var6)
197                        {
198                            var6 = var10;
199                        }
200    
201                        return var6;
202                    }
203                }
204    
205                if (par2 < 0)
206                {
207                    return 0;
208                }
209                else if (par2 >= 256)
210                {
211                    var5 = 15 - this.worldObj.skylightSubtracted;
212    
213                    if (var5 < 0)
214                    {
215                        var5 = 0;
216                    }
217    
218                    return var5;
219                }
220                else
221                {
222                    var5 = (par1 >> 4) - this.chunkX;
223                    var6 = (par3 >> 4) - this.chunkZ;
224                    return this.chunkArray[var5][var6].getBlockLightValue(par1 & 15, par2, par3 & 15, this.worldObj.skylightSubtracted);
225                }
226            }
227            else
228            {
229                return 15;
230            }
231        }
232    
233        /**
234         * Returns the block metadata at coords x,y,z
235         */
236        public int getBlockMetadata(int par1, int par2, int par3)
237        {
238            if (par2 < 0)
239            {
240                return 0;
241            }
242            else if (par2 >= 256)
243            {
244                return 0;
245            }
246            else
247            {
248                int var4 = (par1 >> 4) - this.chunkX;
249                int var5 = (par3 >> 4) - this.chunkZ;
250                if (var4 >= 0 && var4 < this.chunkArray.length && var5 >= 0 && var5 < this.chunkArray[var4].length)
251                {
252                    Chunk var6 = this.chunkArray[var4][var5];
253                    return var6 == null ? 0 : var6.getBlockMetadata(par1 & 15, par2, par3 & 15);
254                }
255                return 0;
256            }
257        }
258    
259        /**
260         * Returns the block's material.
261         */
262        public Material getBlockMaterial(int par1, int par2, int par3)
263        {
264            int var4 = this.getBlockId(par1, par2, par3);
265            return var4 == 0 ? Material.air : Block.blocksList[var4].blockMaterial;
266        }
267    
268        @SideOnly(Side.CLIENT)
269    
270        /**
271         * Gets the biome for a given set of x/z coordinates
272         */
273        public BiomeGenBase getBiomeGenForCoords(int par1, int par2)
274        {
275            return this.worldObj.getBiomeGenForCoords(par1, par2);
276        }
277    
278        @SideOnly(Side.CLIENT)
279    
280        /**
281         * Returns true if the block at the specified coordinates is an opaque cube. Args: x, y, z
282         */
283        public boolean isBlockOpaqueCube(int par1, int par2, int par3)
284        {
285            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
286            return var4 == null ? false : var4.isOpaqueCube();
287        }
288    
289        /**
290         * Indicate if a material is a normal solid opaque cube.
291         */
292        public boolean isBlockNormalCube(int par1, int par2, int par3)
293        {
294            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
295            return var4 == null ? false : var4.blockMaterial.blocksMovement() && var4.renderAsNormalBlock();
296        }
297    
298        @SideOnly(Side.CLIENT)
299    
300        /**
301         * Returns true if the block at the given coordinate has a solid (buildable) top surface.
302         */
303        public boolean doesBlockHaveSolidTopSurface(int par1, int par2, int par3)
304        {
305            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
306            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)));
307        }
308    
309        @SideOnly(Side.CLIENT)
310    
311        /**
312         * Returns true if the block at the specified coordinates is empty
313         */
314        public boolean isAirBlock(int par1, int par2, int par3)
315        {
316            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
317            return var4 == null;
318        }
319    
320        @SideOnly(Side.CLIENT)
321    
322        /**
323         * Brightness for SkyBlock.Sky is clear white and (through color computing it is assumed) DEPENDENT ON DAYTIME.
324         * Brightness for SkyBlock.Block is yellowish and independent.
325         */
326        public int getSkyBlockTypeBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
327        {
328            if (par3 < 0)
329            {
330                par3 = 0;
331            }
332    
333            if (par3 >= 256)
334            {
335                par3 = 255;
336            }
337    
338            if (par3 >= 0 && par3 < 256 && par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 <= 30000000)
339            {
340                int var5;
341                int var6;
342    
343                if (Block.useNeighborBrightness[this.getBlockId(par2, par3, par4)])
344                {
345                    var5 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3 + 1, par4);
346                    var6 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2 + 1, par3, par4);
347                    int var7 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2 - 1, par3, par4);
348                    int var8 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3, par4 + 1);
349                    int var9 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3, par4 - 1);
350    
351                    if (var6 > var5)
352                    {
353                        var5 = var6;
354                    }
355    
356                    if (var7 > var5)
357                    {
358                        var5 = var7;
359                    }
360    
361                    if (var8 > var5)
362                    {
363                        var5 = var8;
364                    }
365    
366                    if (var9 > var5)
367                    {
368                        var5 = var9;
369                    }
370    
371                    return var5;
372                }
373                else
374                {
375                    var5 = (par2 >> 4) - this.chunkX;
376                    var6 = (par4 >> 4) - this.chunkZ;
377                    return this.chunkArray[var5][var6].getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
378                }
379            }
380            else
381            {
382                return par1EnumSkyBlock.defaultLightValue;
383            }
384        }
385    
386        @SideOnly(Side.CLIENT)
387    
388        /**
389         * is only used on stairs and tilled fields
390         */
391        public int getSpecialBlockBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
392        {
393            if (par3 < 0)
394            {
395                par3 = 0;
396            }
397    
398            if (par3 >= 256)
399            {
400                par3 = 255;
401            }
402    
403            if (par3 >= 0 && par3 < 256 && par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 <= 30000000)
404            {
405                int var5 = (par2 >> 4) - this.chunkX;
406                int var6 = (par4 >> 4) - this.chunkZ;
407                return this.chunkArray[var5][var6].getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
408            }
409            else
410            {
411                return par1EnumSkyBlock.defaultLightValue;
412            }
413        }
414    
415        @SideOnly(Side.CLIENT)
416    
417        /**
418         * Returns current world height.
419         */
420        public int getHeight()
421        {
422            return 256;
423        }
424    }