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