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].isIndirectlyPoweringTo(this, par1, par2, par3, par4);
440 }
441 }