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 }