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        public Vec3Pool func_82732_R()
310        {
311            return this.worldObj.func_82732_R();
312        }
313    
314        @SideOnly(Side.CLIENT)
315    
316        /**
317         * Returns true if the block at the specified coordinates is empty
318         */
319        public boolean isAirBlock(int par1, int par2, int par3)
320        {
321            Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
322            return var4 == null;
323        }
324    
325        @SideOnly(Side.CLIENT)
326    
327        /**
328         * Brightness for SkyBlock.Sky is clear white and (through color computing it is assumed) DEPENDENT ON DAYTIME.
329         * Brightness for SkyBlock.Block is yellowish and independent.
330         */
331        public int getSkyBlockTypeBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
332        {
333            if (par3 < 0)
334            {
335                par3 = 0;
336            }
337    
338            if (par3 >= 256)
339            {
340                par3 = 255;
341            }
342    
343            if (par3 >= 0 && par3 < 256 && par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 <= 30000000)
344            {
345                int var5;
346                int var6;
347    
348                if (Block.useNeighborBrightness[this.getBlockId(par2, par3, par4)])
349                {
350                    var5 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3 + 1, par4);
351                    var6 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2 + 1, par3, par4);
352                    int var7 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2 - 1, par3, par4);
353                    int var8 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3, par4 + 1);
354                    int var9 = this.getSpecialBlockBrightness(par1EnumSkyBlock, par2, par3, par4 - 1);
355    
356                    if (var6 > var5)
357                    {
358                        var5 = var6;
359                    }
360    
361                    if (var7 > var5)
362                    {
363                        var5 = var7;
364                    }
365    
366                    if (var8 > var5)
367                    {
368                        var5 = var8;
369                    }
370    
371                    if (var9 > var5)
372                    {
373                        var5 = var9;
374                    }
375    
376                    return var5;
377                }
378                else
379                {
380                    var5 = (par2 >> 4) - this.chunkX;
381                    var6 = (par4 >> 4) - this.chunkZ;
382                    return this.chunkArray[var5][var6].getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
383                }
384            }
385            else
386            {
387                return par1EnumSkyBlock.defaultLightValue;
388            }
389        }
390    
391        @SideOnly(Side.CLIENT)
392    
393        /**
394         * is only used on stairs and tilled fields
395         */
396        public int getSpecialBlockBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
397        {
398            if (par3 < 0)
399            {
400                par3 = 0;
401            }
402    
403            if (par3 >= 256)
404            {
405                par3 = 255;
406            }
407    
408            if (par3 >= 0 && par3 < 256 && par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 <= 30000000)
409            {
410                int var5 = (par2 >> 4) - this.chunkX;
411                int var6 = (par4 >> 4) - this.chunkZ;
412                return this.chunkArray[var5][var6].getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
413            }
414            else
415            {
416                return par1EnumSkyBlock.defaultLightValue;
417            }
418        }
419    
420        @SideOnly(Side.CLIENT)
421    
422        /**
423         * Returns current world height.
424         */
425        public int getHeight()
426        {
427            return 256;
428        }
429    
430        /**
431         * Is this block powering in the specified direction Args: x, y, z, direction
432         */
433        public boolean isBlockProvidingPowerTo(int par1, int par2, int par3, int par4)
434        {
435            int var5 = this.getBlockId(par1, par2, par3);
436            return var5 == 0 ? false : Block.blocksList[var5].isIndirectlyPoweringTo(this, par1, par2, par3, par4);
437        }
438    }