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