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 }