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 }