001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 import java.util.ArrayList; 006 import java.util.Collection; 007 import java.util.HashSet; 008 import java.util.Iterator; 009 import java.util.List; 010 import java.util.Random; 011 import java.util.Set; 012 013 import net.minecraftforge.common.MinecraftForge; 014 import net.minecraftforge.common.ForgeDirection; 015 import net.minecraftforge.event.entity.EntityEvent; 016 import net.minecraftforge.event.world.WorldEvent; 017 import net.minecraftforge.event.entity.PlaySoundAtEntityEvent; 018 019 public abstract class World implements IBlockAccess 020 { 021 /** 022 * Used in the getEntitiesWithinAABB functions to expand the search area for entities. 023 * Modders should change this variable to a higher value if it is less then the radius 024 * of one of there entities. 025 */ 026 public static double MAX_ENTITY_RADIUS = 2.0D; 027 028 /** 029 * boolean; if true updates scheduled by scheduleBlockUpdate happen immediately 030 */ 031 public boolean scheduledUpdatesAreImmediate = false; 032 033 /** A list of all Entities in all currently-loaded chunks */ 034 public List loadedEntityList = new ArrayList(); 035 protected List unloadedEntityList = new ArrayList(); 036 037 /** A list of all TileEntities in all currently-loaded chunks */ 038 public List loadedTileEntityList = new ArrayList(); 039 private List addedTileEntityList = new ArrayList(); 040 041 /** Entities marked for removal. */ 042 private List entityRemoval = new ArrayList(); 043 044 /** Array list of players in the world. */ 045 public List playerEntities = new ArrayList(); 046 047 /** a list of all the lightning entities */ 048 public List weatherEffects = new ArrayList(); 049 private long cloudColour = 16777215L; 050 051 /** How much light is subtracted from full daylight */ 052 public int skylightSubtracted = 0; 053 054 /** 055 * Contains the current Linear Congruential Generator seed for block updates. Used with an A value of 3 and a C 056 * value of 0x3c6ef35f, producing a highly planar series of values ill-suited for choosing random blocks in a 057 * 16x128x16 field. 058 */ 059 protected int updateLCG = (new Random()).nextInt(); 060 061 /** 062 * magic number used to generate fast random numbers for 3d distribution within a chunk 063 */ 064 protected final int DIST_HASH_MAGIC = 1013904223; 065 protected float prevRainingStrength; 066 protected float rainingStrength; 067 protected float prevThunderingStrength; 068 protected float thunderingStrength; 069 070 /** 071 * Set to 2 whenever a lightning bolt is generated in SSP. Decrements if > 0 in updateWeather(). Value appears to be 072 * unused. 073 */ 074 protected int lastLightningBolt = 0; 075 076 /** 077 * If > 0, the sky and skylight colors are illuminated by a lightning flash 078 */ 079 public int lightningFlash = 0; 080 081 /** true while the world is editing blocks */ 082 public boolean editingBlocks = false; 083 084 /** Option > Difficulty setting (0 - 3) */ 085 public int difficultySetting; 086 087 /** RNG for World. */ 088 public Random rand = new Random(); 089 090 /** The WorldProvider instance that World uses. */ 091 public final WorldProvider provider; 092 protected List worldAccesses = new ArrayList(); 093 094 /** Handles chunk operations and caching */ 095 protected IChunkProvider chunkProvider; 096 protected final ISaveHandler saveHandler; 097 098 /** 099 * holds information about a world (size on disk, time, spawn point, seed, ...) 100 */ 101 protected WorldInfo worldInfo; 102 103 /** Boolean that is set to true when trying to find a spawn point */ 104 public boolean findingSpawnPoint; 105 public MapStorage mapStorage; 106 public final VillageCollection villageCollectionObj = new VillageCollection(this); 107 protected final VillageSiege villageSiegeObj = new VillageSiege(this); 108 public final Profiler theProfiler; 109 private ArrayList collidingBoundingBoxes = new ArrayList(); 110 private boolean scanningTileEntities; 111 112 /** indicates if enemies are spawned or not */ 113 protected boolean spawnHostileMobs = true; 114 115 /** A flag indicating whether we should spawn peaceful mobs. */ 116 protected boolean spawnPeacefulMobs = true; 117 118 /** Positions to update */ 119 protected Set activeChunkSet = new HashSet(); 120 121 /** number of ticks until the next random ambients play */ 122 private int ambientTickCountdown; 123 124 /** 125 * is a temporary list of blocks and light values used when updating light levels. Holds up to 32x32x32 blocks (the 126 * maximum influence of a light source.) Every element is a packed bit value: 0000000000LLLLzzzzzzyyyyyyxxxxxx. The 127 * 4-bit L is a light level used when darkening blocks. 6-bit numbers x, y and z represent the block's offset from 128 * the original block, plus 32 (i.e. value of 31 would mean a -1 offset 129 */ 130 int[] lightUpdateBlockList; 131 132 /** 133 * entities within AxisAlignedBB excluding one, set and returned in getEntitiesWithinAABBExcludingEntity(Entity 134 * var1, AxisAlignedBB var2) 135 */ 136 private List entitiesWithinAABBExcludingEntity; 137 138 /** 139 * This is set to true when you are a client connected to a multiplayer world, false otherwise. As of Minecraft 1.3 140 * and the integrated server, this will always return true. 141 */ 142 public boolean isRemote; 143 144 /** 145 * Gets the biome for a given set of x/z coordinates 146 */ 147 public BiomeGenBase getBiomeGenForCoords(int par1, int par2) 148 { 149 if (this.blockExists(par1, 0, par2)) 150 { 151 Chunk var3 = this.getChunkFromBlockCoords(par1, par2); 152 153 if (var3 != null) 154 { 155 return var3.getBiomeGenForWorldCoords(par1 & 15, par2 & 15, this.provider.worldChunkMgr); 156 } 157 } 158 159 return this.provider.worldChunkMgr.getBiomeGenAt(par1, par2); 160 } 161 162 public WorldChunkManager getWorldChunkManager() 163 { 164 return this.provider.worldChunkMgr; 165 } 166 167 @SideOnly(Side.CLIENT) 168 public World(ISaveHandler par1ISaveHandler, String par2Str, WorldProvider par3WorldProvider, WorldSettings par4WorldSettings, Profiler par5Profiler) 169 { 170 this.ambientTickCountdown = this.rand.nextInt(12000); 171 this.lightUpdateBlockList = new int[32768]; 172 this.entitiesWithinAABBExcludingEntity = new ArrayList(); 173 this.isRemote = false; 174 this.saveHandler = par1ISaveHandler; 175 this.theProfiler = par5Profiler; 176 this.worldInfo = new WorldInfo(par4WorldSettings, par2Str); 177 this.provider = par3WorldProvider; 178 this.mapStorage = new MapStorage(par1ISaveHandler); 179 par3WorldProvider.registerWorld(this); 180 this.chunkProvider = this.createChunkProvider(); 181 this.calculateInitialSkylight(); 182 this.calculateInitialWeather(); 183 MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(this)); 184 } 185 186 public World(ISaveHandler par1ISaveHandler, String par2Str, WorldSettings par3WorldSettings, WorldProvider par4WorldProvider, Profiler par5Profiler) 187 { 188 this.ambientTickCountdown = this.rand.nextInt(12000); 189 this.lightUpdateBlockList = new int[32768]; 190 this.entitiesWithinAABBExcludingEntity = new ArrayList(); 191 this.isRemote = false; 192 this.saveHandler = par1ISaveHandler; 193 this.theProfiler = par5Profiler; 194 this.mapStorage = new MapStorage(par1ISaveHandler); 195 this.worldInfo = par1ISaveHandler.loadWorldInfo(); 196 197 if (par4WorldProvider != null) 198 { 199 this.provider = par4WorldProvider; 200 } 201 else if (this.worldInfo != null && this.worldInfo.getDimension() != 0) 202 { 203 this.provider = WorldProvider.getProviderForDimension(this.worldInfo.getDimension()); 204 } 205 else 206 { 207 this.provider = WorldProvider.getProviderForDimension(0); 208 } 209 210 if (this.worldInfo == null) 211 { 212 this.worldInfo = new WorldInfo(par3WorldSettings, par2Str); 213 } 214 else 215 { 216 this.worldInfo.setWorldName(par2Str); 217 } 218 219 this.provider.registerWorld(this); 220 this.chunkProvider = this.createChunkProvider(); 221 222 if (!this.worldInfo.isInitialized()) 223 { 224 this.initialize(par3WorldSettings); 225 this.worldInfo.setServerInitialized(true); 226 } 227 228 this.calculateInitialSkylight(); 229 this.calculateInitialWeather(); 230 MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(this)); 231 } 232 233 /** 234 * Creates the chunk provider for this world. Called in the constructor. Retrieves provider from worldProvider? 235 */ 236 protected abstract IChunkProvider createChunkProvider(); 237 238 protected void initialize(WorldSettings par1WorldSettings) 239 { 240 this.worldInfo.setServerInitialized(true); 241 } 242 243 @SideOnly(Side.CLIENT) 244 245 /** 246 * Sets a new spawn location by finding an uncovered block at a random (x,z) location in the chunk. 247 */ 248 public void setSpawnLocation() 249 { 250 this.setSpawnLocation(8, 64, 8); 251 } 252 253 /** 254 * Returns the block ID of the first block at this (x,z) location with air above it, searching from sea level 255 * upwards. 256 */ 257 public int getFirstUncoveredBlock(int par1, int par2) 258 { 259 int var3; 260 261 for (var3 = 63; !this.isAirBlock(par1, var3 + 1, par2); ++var3) 262 { 263 ; 264 } 265 266 return this.getBlockId(par1, var3, par2); 267 } 268 269 /** 270 * Returns the block ID at coords x,y,z 271 */ 272 public int getBlockId(int par1, int par2, int par3) 273 { 274 return par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000 ? (par2 < 0 ? 0 : (par2 >= 256 ? 0 : this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).getBlockID(par1 & 15, par2, par3 & 15))) : 0; 275 } 276 277 public int getBlockLightOpacity(int par1, int par2, int par3) 278 { 279 return par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000 ? (par2 < 0 ? 0 : (par2 >= 256 ? 0 : this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).getBlockLightOpacity(par1 & 15, par2, par3 & 15))) : 0; 280 } 281 282 /** 283 * Returns true if the block at the specified coordinates is empty 284 */ 285 public boolean isAirBlock(int par1, int par2, int par3) 286 { 287 int id = getBlockId(par1, par2, par3); 288 return id == 0 || Block.blocksList[id] == null || Block.blocksList[id].isAirBlock(this, par1, par2, par3); 289 } 290 291 /** 292 * Checks if a block at a given position should have a tile entity. 293 */ 294 public boolean blockHasTileEntity(int par1, int par2, int par3) 295 { 296 int var4 = this.getBlockId(par1, par2, par3); 297 int meta = this.getBlockMetadata(par1, par2, par3); 298 return Block.blocksList[var4] != null && Block.blocksList[var4].hasTileEntity(meta); 299 } 300 301 /** 302 * Returns whether a block exists at world coordinates x, y, z 303 */ 304 public boolean blockExists(int par1, int par2, int par3) 305 { 306 return par2 >= 0 && par2 < 256 ? this.chunkExists(par1 >> 4, par3 >> 4) : false; 307 } 308 309 /** 310 * Checks if any of the chunks within distance (argument 4) blocks of the given block exist 311 */ 312 public boolean doChunksNearChunkExist(int par1, int par2, int par3, int par4) 313 { 314 return this.checkChunksExist(par1 - par4, par2 - par4, par3 - par4, par1 + par4, par2 + par4, par3 + par4); 315 } 316 317 /** 318 * Checks between a min and max all the chunks inbetween actually exist. Args: minX, minY, minZ, maxX, maxY, maxZ 319 */ 320 public boolean checkChunksExist(int par1, int par2, int par3, int par4, int par5, int par6) 321 { 322 if (par5 >= 0 && par2 < 256) 323 { 324 par1 >>= 4; 325 par3 >>= 4; 326 par4 >>= 4; 327 par6 >>= 4; 328 329 for (int var7 = par1; var7 <= par4; ++var7) 330 { 331 for (int var8 = par3; var8 <= par6; ++var8) 332 { 333 if (!this.chunkExists(var7, var8)) 334 { 335 return false; 336 } 337 } 338 } 339 340 return true; 341 } 342 else 343 { 344 return false; 345 } 346 } 347 348 /** 349 * Returns whether a chunk exists at chunk coordinates x, y 350 */ 351 protected boolean chunkExists(int par1, int par2) 352 { 353 return this.chunkProvider.chunkExists(par1, par2); 354 } 355 356 /** 357 * Returns a chunk looked up by block coordinates. Args: x, z 358 */ 359 public Chunk getChunkFromBlockCoords(int par1, int par2) 360 { 361 return this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4); 362 } 363 364 /** 365 * Returns back a chunk looked up by chunk coordinates Args: x, y 366 */ 367 public Chunk getChunkFromChunkCoords(int par1, int par2) 368 { 369 return this.chunkProvider.provideChunk(par1, par2); 370 } 371 372 /** 373 * Sets the block ID and metadata of a block in global coordinates 374 */ 375 public boolean setBlockAndMetadata(int par1, int par2, int par3, int par4, int par5) 376 { 377 return this.setBlockAndMetadataWithUpdate(par1, par2, par3, par4, par5, true); 378 } 379 380 /** 381 * Sets the block ID and metadata of a block, optionally marking it as needing update. Args: X,Y,Z, blockID, 382 * metadata, needsUpdate 383 */ 384 public boolean setBlockAndMetadataWithUpdate(int par1, int par2, int par3, int par4, int par5, boolean par6) 385 { 386 if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) 387 { 388 if (par2 < 0) 389 { 390 return false; 391 } 392 else if (par2 >= 256) 393 { 394 return false; 395 } 396 else 397 { 398 Chunk var7 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 399 boolean var8 = var7.setBlockIDWithMetadata(par1 & 15, par2, par3 & 15, par4, par5); 400 this.theProfiler.startSection("checkLight"); 401 this.updateAllLightTypes(par1, par2, par3); 402 this.theProfiler.endSection(); 403 404 if (par6 && var8 && (this.isRemote || var7.deferRender)) 405 { 406 this.markBlockNeedsUpdate(par1, par2, par3); 407 } 408 409 return var8; 410 } 411 } 412 else 413 { 414 return false; 415 } 416 } 417 418 /** 419 * Sets the block to the specified blockID at the block coordinates Args x, y, z, blockID 420 */ 421 public boolean setBlock(int par1, int par2, int par3, int par4) 422 { 423 if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) 424 { 425 if (par2 < 0) 426 { 427 return false; 428 } 429 else if (par2 >= 256) 430 { 431 return false; 432 } 433 else 434 { 435 Chunk var5 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 436 boolean var6 = var5.setBlockID(par1 & 15, par2, par3 & 15, par4); 437 this.theProfiler.startSection("checkLight"); 438 this.updateAllLightTypes(par1, par2, par3); 439 this.theProfiler.endSection(); 440 441 if (var6 && (this.isRemote || var5.deferRender)) 442 { 443 this.markBlockNeedsUpdate(par1, par2, par3); 444 } 445 446 return var6; 447 } 448 } 449 else 450 { 451 return false; 452 } 453 } 454 455 /** 456 * Returns the block's material. 457 */ 458 public Material getBlockMaterial(int par1, int par2, int par3) 459 { 460 int var4 = this.getBlockId(par1, par2, par3); 461 return var4 == 0 ? Material.air : Block.blocksList[var4].blockMaterial; 462 } 463 464 /** 465 * Returns the block metadata at coords x,y,z 466 */ 467 public int getBlockMetadata(int par1, int par2, int par3) 468 { 469 if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) 470 { 471 if (par2 < 0) 472 { 473 return 0; 474 } 475 else if (par2 >= 256) 476 { 477 return 0; 478 } 479 else 480 { 481 Chunk var4 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 482 par1 &= 15; 483 par3 &= 15; 484 return var4.getBlockMetadata(par1, par2, par3); 485 } 486 } 487 else 488 { 489 return 0; 490 } 491 } 492 493 /** 494 * Sets the blocks metadata and if set will then notify blocks that this block changed. Args: x, y, z, metadata 495 */ 496 public void setBlockMetadataWithNotify(int par1, int par2, int par3, int par4) 497 { 498 if (this.setBlockMetadata(par1, par2, par3, par4)) 499 { 500 this.notifyBlockChange(par1, par2, par3, this.getBlockId(par1, par2, par3)); 501 } 502 } 503 504 /** 505 * Set the metadata of a block in global coordinates 506 */ 507 public boolean setBlockMetadata(int par1, int par2, int par3, int par4) 508 { 509 if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) 510 { 511 if (par2 < 0) 512 { 513 return false; 514 } 515 else if (par2 >= 256) 516 { 517 return false; 518 } 519 else 520 { 521 Chunk var5 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 522 int var6 = par1 & 15; 523 int var7 = par3 & 15; 524 boolean var8 = var5.setBlockMetadata(var6, par2, var7, par4); 525 526 if (var8 && (this.isRemote || var5.deferRender && Block.requiresSelfNotify[var5.getBlockID(var6, par2, var7) & 4095])) 527 { 528 this.markBlockNeedsUpdate(par1, par2, par3); 529 } 530 531 return var8; 532 } 533 } 534 else 535 { 536 return false; 537 } 538 } 539 540 /** 541 * Sets a block and notifies relevant systems with the block change Args: x, y, z, blockID 542 */ 543 public boolean setBlockWithNotify(int par1, int par2, int par3, int par4) 544 { 545 if (this.setBlock(par1, par2, par3, par4)) 546 { 547 this.notifyBlockChange(par1, par2, par3, par4); 548 return true; 549 } 550 else 551 { 552 return false; 553 } 554 } 555 556 /** 557 * Sets the block ID and metadata, then notifies neighboring blocks of the change Params: x, y, z, BlockID, Metadata 558 */ 559 public boolean setBlockAndMetadataWithNotify(int par1, int par2, int par3, int par4, int par5) 560 { 561 if (this.setBlockAndMetadata(par1, par2, par3, par4, par5)) 562 { 563 this.notifyBlockChange(par1, par2, par3, par4); 564 return true; 565 } 566 else 567 { 568 return false; 569 } 570 } 571 572 /** 573 * Marks the block as needing an update with the renderer. Args: x, y, z 574 */ 575 public void markBlockNeedsUpdate(int par1, int par2, int par3) 576 { 577 Iterator var4 = this.worldAccesses.iterator(); 578 579 while (var4.hasNext()) 580 { 581 IWorldAccess var5 = (IWorldAccess)var4.next(); 582 var5.markBlockNeedsUpdate(par1, par2, par3); 583 } 584 } 585 586 /** 587 * The block type change and need to notify other systems Args: x, y, z, blockID 588 */ 589 public void notifyBlockChange(int par1, int par2, int par3, int par4) 590 { 591 this.notifyBlocksOfNeighborChange(par1, par2, par3, par4); 592 } 593 594 /** 595 * marks a vertical line of blocks as dirty 596 */ 597 public void markBlocksDirtyVertical(int par1, int par2, int par3, int par4) 598 { 599 int var5; 600 601 if (par3 > par4) 602 { 603 var5 = par4; 604 par4 = par3; 605 par3 = var5; 606 } 607 608 if (!this.provider.hasNoSky) 609 { 610 for (var5 = par3; var5 <= par4; ++var5) 611 { 612 this.updateLightByType(EnumSkyBlock.Sky, par1, var5, par2); 613 } 614 } 615 616 this.markBlocksDirty(par1, par3, par2, par1, par4, par2); 617 } 618 619 /** 620 * calls the 'MarkBlockAsNeedsUpdate' in all block accesses in this world 621 */ 622 public void markBlockAsNeedsUpdate(int par1, int par2, int par3) 623 { 624 Iterator var4 = this.worldAccesses.iterator(); 625 626 while (var4.hasNext()) 627 { 628 IWorldAccess var5 = (IWorldAccess)var4.next(); 629 var5.markBlockRangeNeedsUpdate(par1, par2, par3, par1, par2, par3); 630 } 631 } 632 633 public void markBlocksDirty(int par1, int par2, int par3, int par4, int par5, int par6) 634 { 635 Iterator var7 = this.worldAccesses.iterator(); 636 637 while (var7.hasNext()) 638 { 639 IWorldAccess var8 = (IWorldAccess)var7.next(); 640 var8.markBlockRangeNeedsUpdate(par1, par2, par3, par4, par5, par6); 641 } 642 } 643 644 /** 645 * Notifies neighboring blocks that this specified block changed Args: x, y, z, blockID 646 */ 647 public void notifyBlocksOfNeighborChange(int par1, int par2, int par3, int par4) 648 { 649 this.notifyBlockOfNeighborChange(par1 - 1, par2, par3, par4); 650 this.notifyBlockOfNeighborChange(par1 + 1, par2, par3, par4); 651 this.notifyBlockOfNeighborChange(par1, par2 - 1, par3, par4); 652 this.notifyBlockOfNeighborChange(par1, par2 + 1, par3, par4); 653 this.notifyBlockOfNeighborChange(par1, par2, par3 - 1, par4); 654 this.notifyBlockOfNeighborChange(par1, par2, par3 + 1, par4); 655 } 656 657 /** 658 * Notifies a block that one of its neighbor change to the specified type Args: x, y, z, blockID 659 */ 660 private void notifyBlockOfNeighborChange(int par1, int par2, int par3, int par4) 661 { 662 if (!this.editingBlocks && !this.isRemote) 663 { 664 Block var5 = Block.blocksList[this.getBlockId(par1, par2, par3)]; 665 666 if (var5 != null) 667 { 668 var5.onNeighborBlockChange(this, par1, par2, par3, par4); 669 } 670 } 671 } 672 673 /** 674 * Checks if the specified block is able to see the sky 675 */ 676 public boolean canBlockSeeTheSky(int par1, int par2, int par3) 677 { 678 return this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).canBlockSeeTheSky(par1 & 15, par2, par3 & 15); 679 } 680 681 /** 682 * Does the same as getBlockLightValue_do but without checking if its not a normal block 683 */ 684 public int getFullBlockLightValue(int par1, int par2, int par3) 685 { 686 if (par2 < 0) 687 { 688 return 0; 689 } 690 else 691 { 692 if (par2 >= 256) 693 { 694 par2 = 255; 695 } 696 697 return this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).getBlockLightValue(par1 & 15, par2, par3 & 15, 0); 698 } 699 } 700 701 /** 702 * Gets the light value of a block location 703 */ 704 public int getBlockLightValue(int par1, int par2, int par3) 705 { 706 return this.getBlockLightValue_do(par1, par2, par3, true); 707 } 708 709 /** 710 * Gets the light value of a block location. This is the actual function that gets the value and has a bool flag 711 * that indicates if its a half step block to get the maximum light value of a direct neighboring block (left, 712 * right, forward, back, and up) 713 */ 714 public int getBlockLightValue_do(int par1, int par2, int par3, boolean par4) 715 { 716 if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) 717 { 718 if (par4) 719 { 720 int var5 = this.getBlockId(par1, par2, par3); 721 722 if (var5 == Block.stoneSingleSlab.blockID || var5 == Block.woodSingleSlab.blockID || var5 == Block.tilledField.blockID || var5 == Block.stairCompactCobblestone.blockID || var5 == Block.stairCompactPlanks.blockID) 723 { 724 int var6 = this.getBlockLightValue_do(par1, par2 + 1, par3, false); 725 int var7 = this.getBlockLightValue_do(par1 + 1, par2, par3, false); 726 int var8 = this.getBlockLightValue_do(par1 - 1, par2, par3, false); 727 int var9 = this.getBlockLightValue_do(par1, par2, par3 + 1, false); 728 int var10 = this.getBlockLightValue_do(par1, par2, par3 - 1, false); 729 730 if (var7 > var6) 731 { 732 var6 = var7; 733 } 734 735 if (var8 > var6) 736 { 737 var6 = var8; 738 } 739 740 if (var9 > var6) 741 { 742 var6 = var9; 743 } 744 745 if (var10 > var6) 746 { 747 var6 = var10; 748 } 749 750 return var6; 751 } 752 } 753 754 if (par2 < 0) 755 { 756 return 0; 757 } 758 else 759 { 760 if (par2 >= 256) 761 { 762 par2 = 255; 763 } 764 765 Chunk var11 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 766 par1 &= 15; 767 par3 &= 15; 768 return var11.getBlockLightValue(par1, par2, par3, this.skylightSubtracted); 769 } 770 } 771 else 772 { 773 return 15; 774 } 775 } 776 777 /** 778 * Returns the y coordinate with a block in it at this x, z coordinate 779 */ 780 public int getHeightValue(int par1, int par2) 781 { 782 if (par1 >= -30000000 && par2 >= -30000000 && par1 < 30000000 && par2 < 30000000) 783 { 784 if (!this.chunkExists(par1 >> 4, par2 >> 4)) 785 { 786 return 0; 787 } 788 else 789 { 790 Chunk var3 = this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4); 791 return var3.getHeightValue(par1 & 15, par2 & 15); 792 } 793 } 794 else 795 { 796 return 0; 797 } 798 } 799 800 @SideOnly(Side.CLIENT) 801 802 /** 803 * Brightness for SkyBlock.Sky is clear white and (through color computing it is assumed) DEPENDENT ON DAYTIME. 804 * Brightness for SkyBlock.Block is yellowish and independent. 805 */ 806 public int getSkyBlockTypeBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) 807 { 808 if (this.provider.hasNoSky && par1EnumSkyBlock == EnumSkyBlock.Sky) 809 { 810 return 0; 811 } 812 else 813 { 814 if (par3 < 0) 815 { 816 par3 = 0; 817 } 818 819 if (par3 >= 256) 820 { 821 return par1EnumSkyBlock.defaultLightValue; 822 } 823 else if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000) 824 { 825 int var5 = par2 >> 4; 826 int var6 = par4 >> 4; 827 828 if (!this.chunkExists(var5, var6)) 829 { 830 return par1EnumSkyBlock.defaultLightValue; 831 } 832 else if (Block.useNeighborBrightness[this.getBlockId(par2, par3, par4)]) 833 { 834 int var12 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3 + 1, par4); 835 int var8 = this.getSavedLightValue(par1EnumSkyBlock, par2 + 1, par3, par4); 836 int var9 = this.getSavedLightValue(par1EnumSkyBlock, par2 - 1, par3, par4); 837 int var10 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3, par4 + 1); 838 int var11 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3, par4 - 1); 839 840 if (var8 > var12) 841 { 842 var12 = var8; 843 } 844 845 if (var9 > var12) 846 { 847 var12 = var9; 848 } 849 850 if (var10 > var12) 851 { 852 var12 = var10; 853 } 854 855 if (var11 > var12) 856 { 857 var12 = var11; 858 } 859 860 return var12; 861 } 862 else 863 { 864 Chunk var7 = this.getChunkFromChunkCoords(var5, var6); 865 return var7.getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15); 866 } 867 } 868 else 869 { 870 return par1EnumSkyBlock.defaultLightValue; 871 } 872 } 873 } 874 875 /** 876 * Returns saved light value without taking into account the time of day. Either looks in the sky light map or 877 * block light map based on the enumSkyBlock arg. 878 */ 879 public int getSavedLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) 880 { 881 if (par3 < 0) 882 { 883 par3 = 0; 884 } 885 886 if (par3 >= 256) 887 { 888 par3 = 255; 889 } 890 891 if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000) 892 { 893 int var5 = par2 >> 4; 894 int var6 = par4 >> 4; 895 896 if (!this.chunkExists(var5, var6)) 897 { 898 return par1EnumSkyBlock.defaultLightValue; 899 } 900 else 901 { 902 Chunk var7 = this.getChunkFromChunkCoords(var5, var6); 903 return var7.getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15); 904 } 905 } 906 else 907 { 908 return par1EnumSkyBlock.defaultLightValue; 909 } 910 } 911 912 /** 913 * Sets the light value either into the sky map or block map depending on if enumSkyBlock is set to sky or block. 914 * Args: enumSkyBlock, x, y, z, lightValue 915 */ 916 public void setLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4, int par5) 917 { 918 if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000) 919 { 920 if (par3 >= 0) 921 { 922 if (par3 < 256) 923 { 924 if (this.chunkExists(par2 >> 4, par4 >> 4)) 925 { 926 Chunk var6 = this.getChunkFromChunkCoords(par2 >> 4, par4 >> 4); 927 var6.setLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15, par5); 928 Iterator var7 = this.worldAccesses.iterator(); 929 930 while (var7.hasNext()) 931 { 932 IWorldAccess var8 = (IWorldAccess)var7.next(); 933 var8.markBlockNeedsUpdate2(par2, par3, par4); 934 } 935 } 936 } 937 } 938 } 939 } 940 941 public void func_72902_n(int par1, int par2, int par3) 942 { 943 Iterator var4 = this.worldAccesses.iterator(); 944 945 while (var4.hasNext()) 946 { 947 IWorldAccess var5 = (IWorldAccess)var4.next(); 948 var5.markBlockNeedsUpdate2(par1, par2, par3); 949 } 950 } 951 952 @SideOnly(Side.CLIENT) 953 954 /** 955 * Any Light rendered on a 1.8 Block goes through here 956 */ 957 public int getLightBrightnessForSkyBlocks(int par1, int par2, int par3, int par4) 958 { 959 int var5 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Sky, par1, par2, par3); 960 int var6 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Block, par1, par2, par3); 961 962 if (var6 < par4) 963 { 964 var6 = par4; 965 } 966 967 return var5 << 20 | var6 << 4; 968 } 969 970 @SideOnly(Side.CLIENT) 971 public float getBrightness(int par1, int par2, int par3, int par4) 972 { 973 int var5 = this.getBlockLightValue(par1, par2, par3); 974 975 if (var5 < par4) 976 { 977 var5 = par4; 978 } 979 980 return this.provider.lightBrightnessTable[var5]; 981 } 982 983 /** 984 * Returns how bright the block is shown as which is the block's light value looked up in a lookup table (light 985 * values aren't linear for brightness). Args: x, y, z 986 */ 987 public float getLightBrightness(int par1, int par2, int par3) 988 { 989 return this.provider.lightBrightnessTable[this.getBlockLightValue(par1, par2, par3)]; 990 } 991 992 /** 993 * Checks whether its daytime by seeing if the light subtracted from the skylight is less than 4 994 */ 995 public boolean isDaytime() 996 { 997 return this.skylightSubtracted < 4; 998 } 999 1000 /** 1001 * ray traces all blocks, including non-collideable ones 1002 */ 1003 public MovingObjectPosition rayTraceBlocks(Vec3 par1Vec3, Vec3 par2Vec3) 1004 { 1005 return this.rayTraceBlocks_do_do(par1Vec3, par2Vec3, false, false); 1006 } 1007 1008 public MovingObjectPosition rayTraceBlocks_do(Vec3 par1Vec3, Vec3 par2Vec3, boolean par3) 1009 { 1010 return this.rayTraceBlocks_do_do(par1Vec3, par2Vec3, par3, false); 1011 } 1012 1013 public MovingObjectPosition rayTraceBlocks_do_do(Vec3 par1Vec3, Vec3 par2Vec3, boolean par3, boolean par4) 1014 { 1015 if (!Double.isNaN(par1Vec3.xCoord) && !Double.isNaN(par1Vec3.yCoord) && !Double.isNaN(par1Vec3.zCoord)) 1016 { 1017 if (!Double.isNaN(par2Vec3.xCoord) && !Double.isNaN(par2Vec3.yCoord) && !Double.isNaN(par2Vec3.zCoord)) 1018 { 1019 int var5 = MathHelper.floor_double(par2Vec3.xCoord); 1020 int var6 = MathHelper.floor_double(par2Vec3.yCoord); 1021 int var7 = MathHelper.floor_double(par2Vec3.zCoord); 1022 int var8 = MathHelper.floor_double(par1Vec3.xCoord); 1023 int var9 = MathHelper.floor_double(par1Vec3.yCoord); 1024 int var10 = MathHelper.floor_double(par1Vec3.zCoord); 1025 int var11 = this.getBlockId(var8, var9, var10); 1026 int var12 = this.getBlockMetadata(var8, var9, var10); 1027 Block var13 = Block.blocksList[var11]; 1028 1029 if (var13 != null && (!par4 || var13 == null || var13.getCollisionBoundingBoxFromPool(this, var8, var9, var10) != null) && var11 > 0 && var13.canCollideCheck(var12, par3)) 1030 { 1031 MovingObjectPosition var14 = var13.collisionRayTrace(this, var8, var9, var10, par1Vec3, par2Vec3); 1032 1033 if (var14 != null) 1034 { 1035 return var14; 1036 } 1037 } 1038 1039 var11 = 200; 1040 1041 while (var11-- >= 0) 1042 { 1043 if (Double.isNaN(par1Vec3.xCoord) || Double.isNaN(par1Vec3.yCoord) || Double.isNaN(par1Vec3.zCoord)) 1044 { 1045 return null; 1046 } 1047 1048 if (var8 == var5 && var9 == var6 && var10 == var7) 1049 { 1050 return null; 1051 } 1052 1053 boolean var39 = true; 1054 boolean var40 = true; 1055 boolean var41 = true; 1056 double var15 = 999.0D; 1057 double var17 = 999.0D; 1058 double var19 = 999.0D; 1059 1060 if (var5 > var8) 1061 { 1062 var15 = (double)var8 + 1.0D; 1063 } 1064 else if (var5 < var8) 1065 { 1066 var15 = (double)var8 + 0.0D; 1067 } 1068 else 1069 { 1070 var39 = false; 1071 } 1072 1073 if (var6 > var9) 1074 { 1075 var17 = (double)var9 + 1.0D; 1076 } 1077 else if (var6 < var9) 1078 { 1079 var17 = (double)var9 + 0.0D; 1080 } 1081 else 1082 { 1083 var40 = false; 1084 } 1085 1086 if (var7 > var10) 1087 { 1088 var19 = (double)var10 + 1.0D; 1089 } 1090 else if (var7 < var10) 1091 { 1092 var19 = (double)var10 + 0.0D; 1093 } 1094 else 1095 { 1096 var41 = false; 1097 } 1098 1099 double var21 = 999.0D; 1100 double var23 = 999.0D; 1101 double var25 = 999.0D; 1102 double var27 = par2Vec3.xCoord - par1Vec3.xCoord; 1103 double var29 = par2Vec3.yCoord - par1Vec3.yCoord; 1104 double var31 = par2Vec3.zCoord - par1Vec3.zCoord; 1105 1106 if (var39) 1107 { 1108 var21 = (var15 - par1Vec3.xCoord) / var27; 1109 } 1110 1111 if (var40) 1112 { 1113 var23 = (var17 - par1Vec3.yCoord) / var29; 1114 } 1115 1116 if (var41) 1117 { 1118 var25 = (var19 - par1Vec3.zCoord) / var31; 1119 } 1120 1121 boolean var33 = false; 1122 byte var42; 1123 1124 if (var21 < var23 && var21 < var25) 1125 { 1126 if (var5 > var8) 1127 { 1128 var42 = 4; 1129 } 1130 else 1131 { 1132 var42 = 5; 1133 } 1134 1135 par1Vec3.xCoord = var15; 1136 par1Vec3.yCoord += var29 * var21; 1137 par1Vec3.zCoord += var31 * var21; 1138 } 1139 else if (var23 < var25) 1140 { 1141 if (var6 > var9) 1142 { 1143 var42 = 0; 1144 } 1145 else 1146 { 1147 var42 = 1; 1148 } 1149 1150 par1Vec3.xCoord += var27 * var23; 1151 par1Vec3.yCoord = var17; 1152 par1Vec3.zCoord += var31 * var23; 1153 } 1154 else 1155 { 1156 if (var7 > var10) 1157 { 1158 var42 = 2; 1159 } 1160 else 1161 { 1162 var42 = 3; 1163 } 1164 1165 par1Vec3.xCoord += var27 * var25; 1166 par1Vec3.yCoord += var29 * var25; 1167 par1Vec3.zCoord = var19; 1168 } 1169 1170 Vec3 var34 = Vec3.getVec3Pool().getVecFromPool(par1Vec3.xCoord, par1Vec3.yCoord, par1Vec3.zCoord); 1171 var8 = (int)(var34.xCoord = (double)MathHelper.floor_double(par1Vec3.xCoord)); 1172 1173 if (var42 == 5) 1174 { 1175 --var8; 1176 ++var34.xCoord; 1177 } 1178 1179 var9 = (int)(var34.yCoord = (double)MathHelper.floor_double(par1Vec3.yCoord)); 1180 1181 if (var42 == 1) 1182 { 1183 --var9; 1184 ++var34.yCoord; 1185 } 1186 1187 var10 = (int)(var34.zCoord = (double)MathHelper.floor_double(par1Vec3.zCoord)); 1188 1189 if (var42 == 3) 1190 { 1191 --var10; 1192 ++var34.zCoord; 1193 } 1194 1195 int var35 = this.getBlockId(var8, var9, var10); 1196 int var36 = this.getBlockMetadata(var8, var9, var10); 1197 Block var37 = Block.blocksList[var35]; 1198 1199 if ((!par4 || var37 == null || var37.getCollisionBoundingBoxFromPool(this, var8, var9, var10) != null) && var35 > 0 && var37.canCollideCheck(var36, par3)) 1200 { 1201 MovingObjectPosition var38 = var37.collisionRayTrace(this, var8, var9, var10, par1Vec3, par2Vec3); 1202 1203 if (var38 != null) 1204 { 1205 return var38; 1206 } 1207 } 1208 } 1209 1210 return null; 1211 } 1212 else 1213 { 1214 return null; 1215 } 1216 } 1217 else 1218 { 1219 return null; 1220 } 1221 } 1222 1223 /** 1224 * Plays a sound at the entity's position. Args: entity, sound, volume (relative to 1.0), and frequency (or pitch, 1225 * also relative to 1.0). 1226 */ 1227 public void playSoundAtEntity(Entity par1Entity, String par2Str, float par3, float par4) 1228 { 1229 PlaySoundAtEntityEvent event = new PlaySoundAtEntityEvent(par1Entity, par2Str, par3, par4); 1230 if (MinecraftForge.EVENT_BUS.post(event)) 1231 { 1232 return; 1233 } 1234 par2Str = event.name; 1235 if (par1Entity != null && par2Str != null) 1236 { 1237 Iterator var5 = this.worldAccesses.iterator(); 1238 1239 while (var5.hasNext()) 1240 { 1241 IWorldAccess var6 = (IWorldAccess)var5.next(); 1242 var6.playSound(par2Str, par1Entity.posX, par1Entity.posY - (double)par1Entity.yOffset, par1Entity.posZ, par3, par4); 1243 } 1244 } 1245 } 1246 1247 /** 1248 * Play a sound effect. Many many parameters for this function. Not sure what they do, but a classic call is : 1249 * (double)i + 0.5D, (double)j + 0.5D, (double)k + 0.5D, 'random.door_open', 1.0F, world.rand.nextFloat() * 0.1F + 1250 * 0.9F with i,j,k position of the block. 1251 */ 1252 public void playSoundEffect(double par1, double par3, double par5, String par7Str, float par8, float par9) 1253 { 1254 if (par7Str != null) 1255 { 1256 Iterator var10 = this.worldAccesses.iterator(); 1257 1258 while (var10.hasNext()) 1259 { 1260 IWorldAccess var11 = (IWorldAccess)var10.next(); 1261 var11.playSound(par7Str, par1, par3, par5, par8, par9); 1262 } 1263 } 1264 } 1265 1266 /** 1267 * Plays a record at the specified coordinates of the specified name. Args: recordName, x, y, z 1268 */ 1269 public void playRecord(String par1Str, int par2, int par3, int par4) 1270 { 1271 Iterator var5 = this.worldAccesses.iterator(); 1272 1273 while (var5.hasNext()) 1274 { 1275 IWorldAccess var6 = (IWorldAccess)var5.next(); 1276 var6.playRecord(par1Str, par2, par3, par4); 1277 } 1278 } 1279 1280 /** 1281 * Spawns a particle. Args particleName, x, y, z, velX, velY, velZ 1282 */ 1283 public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12) 1284 { 1285 Iterator var14 = this.worldAccesses.iterator(); 1286 1287 while (var14.hasNext()) 1288 { 1289 IWorldAccess var15 = (IWorldAccess)var14.next(); 1290 var15.spawnParticle(par1Str, par2, par4, par6, par8, par10, par12); 1291 } 1292 } 1293 1294 @SideOnly(Side.CLIENT) 1295 1296 /** 1297 * par8 is loudness, all pars passed to minecraftInstance.sndManager.playSound 1298 */ 1299 public void playSound(double par1, double par3, double par5, String par7Str, float par8, float par9) {} 1300 1301 /** 1302 * adds a lightning bolt to the list of lightning bolts in this world. 1303 */ 1304 public boolean addWeatherEffect(Entity par1Entity) 1305 { 1306 this.weatherEffects.add(par1Entity); 1307 return true; 1308 } 1309 1310 /** 1311 * Called to place all entities as part of a world 1312 */ 1313 public boolean spawnEntityInWorld(Entity par1Entity) 1314 { 1315 int var2 = MathHelper.floor_double(par1Entity.posX / 16.0D); 1316 int var3 = MathHelper.floor_double(par1Entity.posZ / 16.0D); 1317 boolean var4 = false; 1318 1319 if (par1Entity instanceof EntityPlayer) 1320 { 1321 var4 = true; 1322 } 1323 1324 if (!var4 && !this.chunkExists(var2, var3)) 1325 { 1326 return false; 1327 } 1328 else 1329 { 1330 if (par1Entity instanceof EntityPlayer) 1331 { 1332 EntityPlayer var5 = (EntityPlayer)par1Entity; 1333 this.playerEntities.add(var5); 1334 this.updateAllPlayersSleepingFlag(); 1335 } 1336 1337 this.getChunkFromChunkCoords(var2, var3).addEntity(par1Entity); 1338 this.loadedEntityList.add(par1Entity); 1339 this.obtainEntitySkin(par1Entity); 1340 return true; 1341 } 1342 } 1343 1344 /** 1345 * Start the skin for this entity downloading, if necessary, and increment its reference counter 1346 */ 1347 protected void obtainEntitySkin(Entity par1Entity) 1348 { 1349 Iterator var2 = this.worldAccesses.iterator(); 1350 1351 while (var2.hasNext()) 1352 { 1353 IWorldAccess var3 = (IWorldAccess)var2.next(); 1354 var3.obtainEntitySkin(par1Entity); 1355 } 1356 } 1357 1358 /** 1359 * Decrement the reference counter for this entity's skin image data 1360 */ 1361 protected void releaseEntitySkin(Entity par1Entity) 1362 { 1363 Iterator var2 = this.worldAccesses.iterator(); 1364 1365 while (var2.hasNext()) 1366 { 1367 IWorldAccess var3 = (IWorldAccess)var2.next(); 1368 var3.releaseEntitySkin(par1Entity); 1369 } 1370 } 1371 1372 /** 1373 * Dismounts the entity (and anything riding the entity), sets the dead flag, and removes the player entity from the 1374 * player entity list. Called by the playerLoggedOut function. 1375 */ 1376 public void setEntityDead(Entity par1Entity) 1377 { 1378 if (par1Entity.riddenByEntity != null) 1379 { 1380 par1Entity.riddenByEntity.mountEntity((Entity)null); 1381 } 1382 1383 if (par1Entity.ridingEntity != null) 1384 { 1385 par1Entity.mountEntity((Entity)null); 1386 } 1387 1388 par1Entity.setDead(); 1389 1390 if (par1Entity instanceof EntityPlayer) 1391 { 1392 this.playerEntities.remove(par1Entity); 1393 this.updateAllPlayersSleepingFlag(); 1394 } 1395 } 1396 1397 public void removeEntity(Entity par1Entity) 1398 { 1399 par1Entity.setDead(); 1400 1401 if (par1Entity instanceof EntityPlayer) 1402 { 1403 this.playerEntities.remove(par1Entity); 1404 this.updateAllPlayersSleepingFlag(); 1405 } 1406 1407 int var2 = par1Entity.chunkCoordX; 1408 int var3 = par1Entity.chunkCoordZ; 1409 1410 if (par1Entity.addedToChunk && this.chunkExists(var2, var3)) 1411 { 1412 this.getChunkFromChunkCoords(var2, var3).removeEntity(par1Entity); 1413 } 1414 1415 this.loadedEntityList.remove(par1Entity); 1416 this.releaseEntitySkin(par1Entity); 1417 } 1418 1419 /** 1420 * Adds a IWorldAccess to the list of worldAccesses 1421 */ 1422 public void addWorldAccess(IWorldAccess par1IWorldAccess) 1423 { 1424 this.worldAccesses.add(par1IWorldAccess); 1425 } 1426 1427 /** 1428 * Returns a list of bounding boxes that collide with aabb excluding the passed in entity's collision. Args: entity, 1429 * aabb 1430 */ 1431 public List getCollidingBoundingBoxes(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB) 1432 { 1433 this.collidingBoundingBoxes.clear(); 1434 int var3 = MathHelper.floor_double(par2AxisAlignedBB.minX); 1435 int var4 = MathHelper.floor_double(par2AxisAlignedBB.maxX + 1.0D); 1436 int var5 = MathHelper.floor_double(par2AxisAlignedBB.minY); 1437 int var6 = MathHelper.floor_double(par2AxisAlignedBB.maxY + 1.0D); 1438 int var7 = MathHelper.floor_double(par2AxisAlignedBB.minZ); 1439 int var8 = MathHelper.floor_double(par2AxisAlignedBB.maxZ + 1.0D); 1440 1441 for (int var9 = var3; var9 < var4; ++var9) 1442 { 1443 for (int var10 = var7; var10 < var8; ++var10) 1444 { 1445 if (this.blockExists(var9, 64, var10)) 1446 { 1447 for (int var11 = var5 - 1; var11 < var6; ++var11) 1448 { 1449 Block var12 = Block.blocksList[this.getBlockId(var9, var11, var10)]; 1450 1451 if (var12 != null) 1452 { 1453 var12.addCollidingBlockToList(this, var9, var11, var10, par2AxisAlignedBB, this.collidingBoundingBoxes, par1Entity); 1454 } 1455 } 1456 } 1457 } 1458 } 1459 1460 double var15 = 0.25D; 1461 List var17 = this.getEntitiesWithinAABBExcludingEntity(par1Entity, par2AxisAlignedBB.expand(var15, var15, var15)); 1462 Iterator var16 = var17.iterator(); 1463 1464 while (var16.hasNext()) 1465 { 1466 Entity var13 = (Entity)var16.next(); 1467 AxisAlignedBB var14 = var13.getBoundingBox(); 1468 1469 if (var14 != null && var14.intersectsWith(par2AxisAlignedBB)) 1470 { 1471 this.collidingBoundingBoxes.add(var14); 1472 } 1473 1474 var14 = par1Entity.getCollisionBox(var13); 1475 1476 if (var14 != null && var14.intersectsWith(par2AxisAlignedBB)) 1477 { 1478 this.collidingBoundingBoxes.add(var14); 1479 } 1480 } 1481 1482 return this.collidingBoundingBoxes; 1483 } 1484 1485 /** 1486 * calculates and returns a list of colliding bounding boxes within a given AABB 1487 */ 1488 public List getAllCollidingBoundingBoxes(AxisAlignedBB par1AxisAlignedBB) 1489 { 1490 this.collidingBoundingBoxes.clear(); 1491 int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX); 1492 int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 1493 int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY); 1494 int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 1495 int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 1496 int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 1497 1498 for (int var8 = var2; var8 < var3; ++var8) 1499 { 1500 for (int var9 = var6; var9 < var7; ++var9) 1501 { 1502 if (this.blockExists(var8, 64, var9)) 1503 { 1504 for (int var10 = var4 - 1; var10 < var5; ++var10) 1505 { 1506 Block var11 = Block.blocksList[this.getBlockId(var8, var10, var9)]; 1507 1508 if (var11 != null) 1509 { 1510 var11.addCollidingBlockToList(this, var8, var10, var9, par1AxisAlignedBB, this.collidingBoundingBoxes, (Entity)null); 1511 } 1512 } 1513 } 1514 } 1515 } 1516 1517 return this.collidingBoundingBoxes; 1518 } 1519 1520 /** 1521 * Returns the amount of skylight subtracted for the current time 1522 */ 1523 public int calculateSkylightSubtracted(float par1) 1524 { 1525 float var2 = this.getCelestialAngle(par1); 1526 float var3 = 1.0F - (MathHelper.cos(var2 * (float)Math.PI * 2.0F) * 2.0F + 0.5F); 1527 1528 if (var3 < 0.0F) 1529 { 1530 var3 = 0.0F; 1531 } 1532 1533 if (var3 > 1.0F) 1534 { 1535 var3 = 1.0F; 1536 } 1537 1538 var3 = 1.0F - var3; 1539 var3 = (float)((double)var3 * (1.0D - (double)(this.getRainStrength(par1) * 5.0F) / 16.0D)); 1540 var3 = (float)((double)var3 * (1.0D - (double)(this.getWeightedThunderStrength(par1) * 5.0F) / 16.0D)); 1541 var3 = 1.0F - var3; 1542 return (int)(var3 * 11.0F); 1543 } 1544 1545 @SideOnly(Side.CLIENT) 1546 1547 /** 1548 * Removes a worldAccess from the worldAccesses object 1549 */ 1550 public void removeWorldAccess(IWorldAccess par1IWorldAccess) 1551 { 1552 this.worldAccesses.remove(par1IWorldAccess); 1553 } 1554 1555 @SideOnly(Side.CLIENT) 1556 public float func_72971_b(float par1) 1557 { 1558 float var2 = this.getCelestialAngle(par1); 1559 float var3 = 1.0F - (MathHelper.cos(var2 * (float)Math.PI * 2.0F) * 2.0F + 0.2F); 1560 1561 if (var3 < 0.0F) 1562 { 1563 var3 = 0.0F; 1564 } 1565 1566 if (var3 > 1.0F) 1567 { 1568 var3 = 1.0F; 1569 } 1570 1571 var3 = 1.0F - var3; 1572 var3 = (float)((double)var3 * (1.0D - (double)(this.getRainStrength(par1) * 5.0F) / 16.0D)); 1573 var3 = (float)((double)var3 * (1.0D - (double)(this.getWeightedThunderStrength(par1) * 5.0F) / 16.0D)); 1574 return var3 * 0.8F + 0.2F; 1575 } 1576 1577 @SideOnly(Side.CLIENT) 1578 1579 /** 1580 * Calculates the color for the skybox 1581 */ 1582 public Vec3 getSkyColor(Entity par1Entity, float par2) 1583 { 1584 float var3 = this.getCelestialAngle(par2); 1585 float var4 = MathHelper.cos(var3 * (float)Math.PI * 2.0F) * 2.0F + 0.5F; 1586 1587 if (var4 < 0.0F) 1588 { 1589 var4 = 0.0F; 1590 } 1591 1592 if (var4 > 1.0F) 1593 { 1594 var4 = 1.0F; 1595 } 1596 1597 int var5 = MathHelper.floor_double(par1Entity.posX); 1598 int var6 = MathHelper.floor_double(par1Entity.posZ); 1599 BiomeGenBase var7 = this.getBiomeGenForCoords(var5, var6); 1600 float var8 = var7.getFloatTemperature(); 1601 int var9 = var7.getSkyColorByTemp(var8); 1602 float var10 = (float)(var9 >> 16 & 255) / 255.0F; 1603 float var11 = (float)(var9 >> 8 & 255) / 255.0F; 1604 float var12 = (float)(var9 & 255) / 255.0F; 1605 var10 *= var4; 1606 var11 *= var4; 1607 var12 *= var4; 1608 float var13 = this.getRainStrength(par2); 1609 float var14; 1610 float var15; 1611 1612 if (var13 > 0.0F) 1613 { 1614 var14 = (var10 * 0.3F + var11 * 0.59F + var12 * 0.11F) * 0.6F; 1615 var15 = 1.0F - var13 * 0.75F; 1616 var10 = var10 * var15 + var14 * (1.0F - var15); 1617 var11 = var11 * var15 + var14 * (1.0F - var15); 1618 var12 = var12 * var15 + var14 * (1.0F - var15); 1619 } 1620 1621 var14 = this.getWeightedThunderStrength(par2); 1622 1623 if (var14 > 0.0F) 1624 { 1625 var15 = (var10 * 0.3F + var11 * 0.59F + var12 * 0.11F) * 0.2F; 1626 float var16 = 1.0F - var14 * 0.75F; 1627 var10 = var10 * var16 + var15 * (1.0F - var16); 1628 var11 = var11 * var16 + var15 * (1.0F - var16); 1629 var12 = var12 * var16 + var15 * (1.0F - var16); 1630 } 1631 1632 if (this.lightningFlash > 0) 1633 { 1634 var15 = (float)this.lightningFlash - par2; 1635 1636 if (var15 > 1.0F) 1637 { 1638 var15 = 1.0F; 1639 } 1640 1641 var15 *= 0.45F; 1642 var10 = var10 * (1.0F - var15) + 0.8F * var15; 1643 var11 = var11 * (1.0F - var15) + 0.8F * var15; 1644 var12 = var12 * (1.0F - var15) + 1.0F * var15; 1645 } 1646 1647 return Vec3.getVec3Pool().getVecFromPool((double)var10, (double)var11, (double)var12); 1648 } 1649 1650 /** 1651 * calls calculateCelestialAngle 1652 */ 1653 public float getCelestialAngle(float par1) 1654 { 1655 return this.provider.calculateCelestialAngle(this.worldInfo.getWorldTime(), par1); 1656 } 1657 1658 @SideOnly(Side.CLIENT) 1659 public int getMoonPhase(float par1) 1660 { 1661 return this.provider.getMoonPhase(this.worldInfo.getWorldTime(), par1); 1662 } 1663 1664 @SideOnly(Side.CLIENT) 1665 1666 /** 1667 * Return getCelestialAngle()*2*PI 1668 */ 1669 public float getCelestialAngleRadians(float par1) 1670 { 1671 float var2 = this.getCelestialAngle(par1); 1672 return var2 * (float)Math.PI * 2.0F; 1673 } 1674 1675 @SideOnly(Side.CLIENT) 1676 public Vec3 drawClouds(float par1) 1677 { 1678 float var2 = this.getCelestialAngle(par1); 1679 float var3 = MathHelper.cos(var2 * (float)Math.PI * 2.0F) * 2.0F + 0.5F; 1680 1681 if (var3 < 0.0F) 1682 { 1683 var3 = 0.0F; 1684 } 1685 1686 if (var3 > 1.0F) 1687 { 1688 var3 = 1.0F; 1689 } 1690 1691 float var4 = (float)(this.cloudColour >> 16 & 255L) / 255.0F; 1692 float var5 = (float)(this.cloudColour >> 8 & 255L) / 255.0F; 1693 float var6 = (float)(this.cloudColour & 255L) / 255.0F; 1694 float var7 = this.getRainStrength(par1); 1695 float var8; 1696 float var9; 1697 1698 if (var7 > 0.0F) 1699 { 1700 var8 = (var4 * 0.3F + var5 * 0.59F + var6 * 0.11F) * 0.6F; 1701 var9 = 1.0F - var7 * 0.95F; 1702 var4 = var4 * var9 + var8 * (1.0F - var9); 1703 var5 = var5 * var9 + var8 * (1.0F - var9); 1704 var6 = var6 * var9 + var8 * (1.0F - var9); 1705 } 1706 1707 var4 *= var3 * 0.9F + 0.1F; 1708 var5 *= var3 * 0.9F + 0.1F; 1709 var6 *= var3 * 0.85F + 0.15F; 1710 var8 = this.getWeightedThunderStrength(par1); 1711 1712 if (var8 > 0.0F) 1713 { 1714 var9 = (var4 * 0.3F + var5 * 0.59F + var6 * 0.11F) * 0.2F; 1715 float var10 = 1.0F - var8 * 0.95F; 1716 var4 = var4 * var10 + var9 * (1.0F - var10); 1717 var5 = var5 * var10 + var9 * (1.0F - var10); 1718 var6 = var6 * var10 + var9 * (1.0F - var10); 1719 } 1720 1721 return Vec3.getVec3Pool().getVecFromPool((double)var4, (double)var5, (double)var6); 1722 } 1723 1724 @SideOnly(Side.CLIENT) 1725 1726 /** 1727 * Returns vector(ish) with R/G/B for fog 1728 */ 1729 public Vec3 getFogColor(float par1) 1730 { 1731 float var2 = this.getCelestialAngle(par1); 1732 return this.provider.getFogColor(var2, par1); 1733 } 1734 1735 /** 1736 * Gets the height to which rain/snow will fall. Calculates it if not already stored. 1737 */ 1738 public int getPrecipitationHeight(int par1, int par2) 1739 { 1740 return this.getChunkFromBlockCoords(par1, par2).getPrecipitationHeight(par1 & 15, par2 & 15); 1741 } 1742 1743 /** 1744 * Finds the highest block on the x, z coordinate that is solid and returns its y coord. Args x, z 1745 */ 1746 public int getTopSolidOrLiquidBlock(int par1, int par2) 1747 { 1748 Chunk var3 = this.getChunkFromBlockCoords(par1, par2); 1749 int var4 = var3.getTopFilledSegment() + 15; 1750 par1 &= 15; 1751 1752 for (par2 &= 15; var4 > 0; --var4) 1753 { 1754 int var5 = var3.getBlockID(par1, var4, par2); 1755 1756 if (var5 != 0 && Block.blocksList[var5].blockMaterial.blocksMovement() && Block.blocksList[var5].blockMaterial != Material.leaves) 1757 { 1758 return var4 + 1; 1759 } 1760 } 1761 1762 return -1; 1763 } 1764 1765 @SideOnly(Side.CLIENT) 1766 1767 /** 1768 * How bright are stars in the sky 1769 */ 1770 public float getStarBrightness(float par1) 1771 { 1772 float var2 = this.getCelestialAngle(par1); 1773 float var3 = 1.0F - (MathHelper.cos(var2 * (float)Math.PI * 2.0F) * 2.0F + 0.25F); 1774 1775 if (var3 < 0.0F) 1776 { 1777 var3 = 0.0F; 1778 } 1779 1780 if (var3 > 1.0F) 1781 { 1782 var3 = 1.0F; 1783 } 1784 1785 return var3 * var3 * 0.5F; 1786 } 1787 1788 /** 1789 * Schedules a tick to a block with a delay (Most commonly the tick rate) 1790 */ 1791 public void scheduleBlockUpdate(int par1, int par2, int par3, int par4, int par5) {} 1792 1793 /** 1794 * Schedules a block update from the saved information in a chunk. Called when the chunk is loaded. 1795 */ 1796 public void scheduleBlockUpdateFromLoad(int par1, int par2, int par3, int par4, int par5) {} 1797 1798 /** 1799 * Updates (and cleans up) entities and tile entities 1800 */ 1801 public void updateEntities() 1802 { 1803 this.theProfiler.startSection("entities"); 1804 this.theProfiler.startSection("global"); 1805 int var1; 1806 Entity var2; 1807 1808 for (var1 = 0; var1 < this.weatherEffects.size(); ++var1) 1809 { 1810 var2 = (Entity)this.weatherEffects.get(var1); 1811 var2.onUpdate(); 1812 1813 if (var2.isDead) 1814 { 1815 this.weatherEffects.remove(var1--); 1816 } 1817 } 1818 1819 this.theProfiler.endStartSection("remove"); 1820 this.loadedEntityList.removeAll(this.unloadedEntityList); 1821 Iterator var5 = this.unloadedEntityList.iterator(); 1822 int var3; 1823 int var4; 1824 1825 while (var5.hasNext()) 1826 { 1827 var2 = (Entity)var5.next(); 1828 var3 = var2.chunkCoordX; 1829 var4 = var2.chunkCoordZ; 1830 1831 if (var2.addedToChunk && this.chunkExists(var3, var4)) 1832 { 1833 this.getChunkFromChunkCoords(var3, var4).removeEntity(var2); 1834 } 1835 } 1836 1837 var5 = this.unloadedEntityList.iterator(); 1838 1839 while (var5.hasNext()) 1840 { 1841 var2 = (Entity)var5.next(); 1842 this.releaseEntitySkin(var2); 1843 } 1844 1845 this.unloadedEntityList.clear(); 1846 this.theProfiler.endStartSection("regular"); 1847 1848 for (var1 = 0; var1 < this.loadedEntityList.size(); ++var1) 1849 { 1850 var2 = (Entity)this.loadedEntityList.get(var1); 1851 1852 if (var2.ridingEntity != null) 1853 { 1854 if (!var2.ridingEntity.isDead && var2.ridingEntity.riddenByEntity == var2) 1855 { 1856 continue; 1857 } 1858 1859 var2.ridingEntity.riddenByEntity = null; 1860 var2.ridingEntity = null; 1861 } 1862 1863 this.theProfiler.startSection("tick"); 1864 1865 if (!var2.isDead) 1866 { 1867 this.updateEntity(var2); 1868 } 1869 1870 this.theProfiler.endSection(); 1871 this.theProfiler.startSection("remove"); 1872 1873 if (var2.isDead) 1874 { 1875 var3 = var2.chunkCoordX; 1876 var4 = var2.chunkCoordZ; 1877 1878 if (var2.addedToChunk && this.chunkExists(var3, var4)) 1879 { 1880 this.getChunkFromChunkCoords(var3, var4).removeEntity(var2); 1881 } 1882 1883 this.loadedEntityList.remove(var1--); 1884 this.releaseEntitySkin(var2); 1885 } 1886 1887 this.theProfiler.endSection(); 1888 } 1889 1890 this.theProfiler.endStartSection("tileEntities"); 1891 this.scanningTileEntities = true; 1892 var5 = this.loadedTileEntityList.iterator(); 1893 1894 while (var5.hasNext()) 1895 { 1896 TileEntity var6 = (TileEntity)var5.next(); 1897 1898 if (!var6.isInvalid() && var6.func_70309_m() && this.blockExists(var6.xCoord, var6.yCoord, var6.zCoord)) 1899 { 1900 var6.updateEntity(); 1901 } 1902 1903 if (var6.isInvalid()) 1904 { 1905 var5.remove(); 1906 1907 if (this.chunkExists(var6.xCoord >> 4, var6.zCoord >> 4)) 1908 { 1909 Chunk var8 = this.getChunkFromChunkCoords(var6.xCoord >> 4, var6.zCoord >> 4); 1910 1911 if (var8 != null) 1912 { 1913 var8.cleanChunkBlockTileEntity(var6.xCoord & 15, var6.yCoord, var6.zCoord & 15); 1914 } 1915 } 1916 } 1917 } 1918 1919 this.scanningTileEntities = false; 1920 1921 if (!this.entityRemoval.isEmpty()) 1922 { 1923 for (Object tile : entityRemoval) 1924 { 1925 ((TileEntity)tile).onChunkUnload(); 1926 } 1927 this.loadedTileEntityList.removeAll(this.entityRemoval); 1928 this.entityRemoval.clear(); 1929 } 1930 1931 this.theProfiler.endStartSection("pendingTileEntities"); 1932 1933 if (!this.addedTileEntityList.isEmpty()) 1934 { 1935 Iterator var7 = this.addedTileEntityList.iterator(); 1936 1937 while (var7.hasNext()) 1938 { 1939 TileEntity var9 = (TileEntity)var7.next(); 1940 1941 if (!var9.isInvalid()) 1942 { 1943 if (!this.loadedTileEntityList.contains(var9)) 1944 { 1945 this.loadedTileEntityList.add(var9); 1946 } 1947 } 1948 else 1949 { 1950 if (this.chunkExists(var9.xCoord >> 4, var9.zCoord >> 4)) 1951 { 1952 Chunk var10 = this.getChunkFromChunkCoords(var9.xCoord >> 4, var9.zCoord >> 4); 1953 1954 if (var10 != null) 1955 { 1956 var10.setChunkBlockTileEntity(var9.xCoord & 15, var9.yCoord, var9.zCoord & 15, var9); 1957 } 1958 } 1959 } 1960 } 1961 1962 this.addedTileEntityList.clear(); 1963 } 1964 1965 this.theProfiler.endSection(); 1966 this.theProfiler.endSection(); 1967 } 1968 1969 public void addTileEntity(Collection par1Collection) 1970 { 1971 List dest = scanningTileEntities ? addedTileEntityList : loadedTileEntityList; 1972 for(Object entity : par1Collection) 1973 { 1974 if(((TileEntity)entity).canUpdate()) 1975 { 1976 dest.add(entity); 1977 } 1978 } 1979 } 1980 1981 /** 1982 * Will update the entity in the world if the chunk the entity is in is currently loaded. Args: entity 1983 */ 1984 public void updateEntity(Entity par1Entity) 1985 { 1986 this.updateEntityWithOptionalForce(par1Entity, true); 1987 } 1988 1989 /** 1990 * Will update the entity in the world if the chunk the entity is in is currently loaded or its forced to update. 1991 * Args: entity, forceUpdate 1992 */ 1993 public void updateEntityWithOptionalForce(Entity par1Entity, boolean par2) 1994 { 1995 int var3 = MathHelper.floor_double(par1Entity.posX); 1996 int var4 = MathHelper.floor_double(par1Entity.posZ); 1997 byte var5 = 32; 1998 boolean canUpdate = !par2 || this.checkChunksExist(var3 - var5, 0, var4 - var5, var3 + var5, 0, var4 + var5); 1999 if (!canUpdate) 2000 { 2001 EntityEvent.CanUpdate event = new EntityEvent.CanUpdate(par1Entity); 2002 MinecraftForge.EVENT_BUS.post(event); 2003 canUpdate = event.canUpdate; 2004 } 2005 if (canUpdate) 2006 { 2007 par1Entity.lastTickPosX = par1Entity.posX; 2008 par1Entity.lastTickPosY = par1Entity.posY; 2009 par1Entity.lastTickPosZ = par1Entity.posZ; 2010 par1Entity.prevRotationYaw = par1Entity.rotationYaw; 2011 par1Entity.prevRotationPitch = par1Entity.rotationPitch; 2012 2013 if (par2 && par1Entity.addedToChunk) 2014 { 2015 if (par1Entity.ridingEntity != null) 2016 { 2017 par1Entity.updateRidden(); 2018 } 2019 else 2020 { 2021 par1Entity.onUpdate(); 2022 } 2023 } 2024 2025 this.theProfiler.startSection("chunkCheck"); 2026 2027 if (Double.isNaN(par1Entity.posX) || Double.isInfinite(par1Entity.posX)) 2028 { 2029 par1Entity.posX = par1Entity.lastTickPosX; 2030 } 2031 2032 if (Double.isNaN(par1Entity.posY) || Double.isInfinite(par1Entity.posY)) 2033 { 2034 par1Entity.posY = par1Entity.lastTickPosY; 2035 } 2036 2037 if (Double.isNaN(par1Entity.posZ) || Double.isInfinite(par1Entity.posZ)) 2038 { 2039 par1Entity.posZ = par1Entity.lastTickPosZ; 2040 } 2041 2042 if (Double.isNaN((double)par1Entity.rotationPitch) || Double.isInfinite((double)par1Entity.rotationPitch)) 2043 { 2044 par1Entity.rotationPitch = par1Entity.prevRotationPitch; 2045 } 2046 2047 if (Double.isNaN((double)par1Entity.rotationYaw) || Double.isInfinite((double)par1Entity.rotationYaw)) 2048 { 2049 par1Entity.rotationYaw = par1Entity.prevRotationYaw; 2050 } 2051 2052 int var6 = MathHelper.floor_double(par1Entity.posX / 16.0D); 2053 int var7 = MathHelper.floor_double(par1Entity.posY / 16.0D); 2054 int var8 = MathHelper.floor_double(par1Entity.posZ / 16.0D); 2055 2056 if (!par1Entity.addedToChunk || par1Entity.chunkCoordX != var6 || par1Entity.chunkCoordY != var7 || par1Entity.chunkCoordZ != var8) 2057 { 2058 if (par1Entity.addedToChunk && this.chunkExists(par1Entity.chunkCoordX, par1Entity.chunkCoordZ)) 2059 { 2060 this.getChunkFromChunkCoords(par1Entity.chunkCoordX, par1Entity.chunkCoordZ).removeEntityAtIndex(par1Entity, par1Entity.chunkCoordY); 2061 } 2062 2063 if (this.chunkExists(var6, var8)) 2064 { 2065 par1Entity.addedToChunk = true; 2066 this.getChunkFromChunkCoords(var6, var8).addEntity(par1Entity); 2067 } 2068 else 2069 { 2070 par1Entity.addedToChunk = false; 2071 } 2072 } 2073 2074 this.theProfiler.endSection(); 2075 2076 if (par2 && par1Entity.addedToChunk && par1Entity.riddenByEntity != null) 2077 { 2078 if (!par1Entity.riddenByEntity.isDead && par1Entity.riddenByEntity.ridingEntity == par1Entity) 2079 { 2080 this.updateEntity(par1Entity.riddenByEntity); 2081 } 2082 else 2083 { 2084 par1Entity.riddenByEntity.ridingEntity = null; 2085 par1Entity.riddenByEntity = null; 2086 } 2087 } 2088 } 2089 } 2090 2091 /** 2092 * Returns true if there are no solid, live entities in the specified AxisAlignedBB 2093 */ 2094 public boolean checkIfAABBIsClear(AxisAlignedBB par1AxisAlignedBB) 2095 { 2096 return this.checkIfAABBIsClearExcludingEntity(par1AxisAlignedBB, (Entity)null); 2097 } 2098 2099 /** 2100 * Returns true if there are no solid, live entities in the specified AxisAlignedBB, excluding the given entity 2101 */ 2102 public boolean checkIfAABBIsClearExcludingEntity(AxisAlignedBB par1AxisAlignedBB, Entity par2Entity) 2103 { 2104 List var3 = this.getEntitiesWithinAABBExcludingEntity((Entity)null, par1AxisAlignedBB); 2105 Iterator var4 = var3.iterator(); 2106 Entity var5; 2107 2108 do 2109 { 2110 if (!var4.hasNext()) 2111 { 2112 return true; 2113 } 2114 2115 var5 = (Entity)var4.next(); 2116 } 2117 while (var5.isDead || !var5.preventEntitySpawning || var5 == par2Entity); 2118 2119 return false; 2120 } 2121 2122 /** 2123 * Returns true if there are any blocks in the region constrained by an AxisAlignedBB 2124 */ 2125 public boolean isAABBNonEmpty(AxisAlignedBB par1AxisAlignedBB) 2126 { 2127 int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX); 2128 int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 2129 int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY); 2130 int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 2131 int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 2132 int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 2133 2134 if (par1AxisAlignedBB.minX < 0.0D) 2135 { 2136 --var2; 2137 } 2138 2139 if (par1AxisAlignedBB.minY < 0.0D) 2140 { 2141 --var4; 2142 } 2143 2144 if (par1AxisAlignedBB.minZ < 0.0D) 2145 { 2146 --var6; 2147 } 2148 2149 for (int var8 = var2; var8 < var3; ++var8) 2150 { 2151 for (int var9 = var4; var9 < var5; ++var9) 2152 { 2153 for (int var10 = var6; var10 < var7; ++var10) 2154 { 2155 Block var11 = Block.blocksList[this.getBlockId(var8, var9, var10)]; 2156 2157 if (var11 != null) 2158 { 2159 return true; 2160 } 2161 } 2162 } 2163 } 2164 2165 return false; 2166 } 2167 2168 /** 2169 * Returns if any of the blocks within the aabb are liquids. Args: aabb 2170 */ 2171 public boolean isAnyLiquid(AxisAlignedBB par1AxisAlignedBB) 2172 { 2173 int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX); 2174 int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 2175 int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY); 2176 int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 2177 int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 2178 int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 2179 2180 if (par1AxisAlignedBB.minX < 0.0D) 2181 { 2182 --var2; 2183 } 2184 2185 if (par1AxisAlignedBB.minY < 0.0D) 2186 { 2187 --var4; 2188 } 2189 2190 if (par1AxisAlignedBB.minZ < 0.0D) 2191 { 2192 --var6; 2193 } 2194 2195 for (int var8 = var2; var8 < var3; ++var8) 2196 { 2197 for (int var9 = var4; var9 < var5; ++var9) 2198 { 2199 for (int var10 = var6; var10 < var7; ++var10) 2200 { 2201 Block var11 = Block.blocksList[this.getBlockId(var8, var9, var10)]; 2202 2203 if (var11 != null && var11.blockMaterial.isLiquid()) 2204 { 2205 return true; 2206 } 2207 } 2208 } 2209 } 2210 2211 return false; 2212 } 2213 2214 /** 2215 * Returns whether or not the given bounding box is on fire or not 2216 */ 2217 public boolean isBoundingBoxBurning(AxisAlignedBB par1AxisAlignedBB) 2218 { 2219 int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX); 2220 int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 2221 int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY); 2222 int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 2223 int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 2224 int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 2225 2226 if (this.checkChunksExist(var2, var4, var6, var3, var5, var7)) 2227 { 2228 for (int var8 = var2; var8 < var3; ++var8) 2229 { 2230 for (int var9 = var4; var9 < var5; ++var9) 2231 { 2232 for (int var10 = var6; var10 < var7; ++var10) 2233 { 2234 int var11 = this.getBlockId(var8, var9, var10); 2235 2236 if (var11 == Block.fire.blockID || var11 == Block.lavaMoving.blockID || var11 == Block.lavaStill.blockID) 2237 { 2238 return true; 2239 } 2240 else 2241 { 2242 Block block = Block.blocksList[var11]; 2243 if (block != null && block.isBlockBurning(this, var8, var9, var10)) 2244 { 2245 return true; 2246 } 2247 } 2248 } 2249 } 2250 } 2251 } 2252 2253 return false; 2254 } 2255 2256 /** 2257 * handles the acceleration of an object whilst in water. Not sure if it is used elsewhere. 2258 */ 2259 public boolean handleMaterialAcceleration(AxisAlignedBB par1AxisAlignedBB, Material par2Material, Entity par3Entity) 2260 { 2261 int var4 = MathHelper.floor_double(par1AxisAlignedBB.minX); 2262 int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 2263 int var6 = MathHelper.floor_double(par1AxisAlignedBB.minY); 2264 int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 2265 int var8 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 2266 int var9 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 2267 2268 if (!this.checkChunksExist(var4, var6, var8, var5, var7, var9)) 2269 { 2270 return false; 2271 } 2272 else 2273 { 2274 boolean var10 = false; 2275 Vec3 var11 = Vec3.getVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D); 2276 2277 for (int var12 = var4; var12 < var5; ++var12) 2278 { 2279 for (int var13 = var6; var13 < var7; ++var13) 2280 { 2281 for (int var14 = var8; var14 < var9; ++var14) 2282 { 2283 Block var15 = Block.blocksList[this.getBlockId(var12, var13, var14)]; 2284 2285 if (var15 != null && var15.blockMaterial == par2Material) 2286 { 2287 double var16 = (double)((float)(var13 + 1) - BlockFluid.getFluidHeightPercent(this.getBlockMetadata(var12, var13, var14))); 2288 2289 if ((double)var7 >= var16) 2290 { 2291 var10 = true; 2292 var15.velocityToAddToEntity(this, var12, var13, var14, par3Entity, var11); 2293 } 2294 } 2295 } 2296 } 2297 } 2298 2299 if (var11.lengthVector() > 0.0D) 2300 { 2301 var11 = var11.normalize(); 2302 double var18 = 0.014D; 2303 par3Entity.motionX += var11.xCoord * var18; 2304 par3Entity.motionY += var11.yCoord * var18; 2305 par3Entity.motionZ += var11.zCoord * var18; 2306 } 2307 2308 return var10; 2309 } 2310 } 2311 2312 /** 2313 * Returns true if the given bounding box contains the given material 2314 */ 2315 public boolean isMaterialInBB(AxisAlignedBB par1AxisAlignedBB, Material par2Material) 2316 { 2317 int var3 = MathHelper.floor_double(par1AxisAlignedBB.minX); 2318 int var4 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 2319 int var5 = MathHelper.floor_double(par1AxisAlignedBB.minY); 2320 int var6 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 2321 int var7 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 2322 int var8 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 2323 2324 for (int var9 = var3; var9 < var4; ++var9) 2325 { 2326 for (int var10 = var5; var10 < var6; ++var10) 2327 { 2328 for (int var11 = var7; var11 < var8; ++var11) 2329 { 2330 Block var12 = Block.blocksList[this.getBlockId(var9, var10, var11)]; 2331 2332 if (var12 != null && var12.blockMaterial == par2Material) 2333 { 2334 return true; 2335 } 2336 } 2337 } 2338 } 2339 2340 return false; 2341 } 2342 2343 /** 2344 * checks if the given AABB is in the material given. Used while swimming. 2345 */ 2346 public boolean isAABBInMaterial(AxisAlignedBB par1AxisAlignedBB, Material par2Material) 2347 { 2348 int var3 = MathHelper.floor_double(par1AxisAlignedBB.minX); 2349 int var4 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D); 2350 int var5 = MathHelper.floor_double(par1AxisAlignedBB.minY); 2351 int var6 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D); 2352 int var7 = MathHelper.floor_double(par1AxisAlignedBB.minZ); 2353 int var8 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D); 2354 2355 for (int var9 = var3; var9 < var4; ++var9) 2356 { 2357 for (int var10 = var5; var10 < var6; ++var10) 2358 { 2359 for (int var11 = var7; var11 < var8; ++var11) 2360 { 2361 Block var12 = Block.blocksList[this.getBlockId(var9, var10, var11)]; 2362 2363 if (var12 != null && var12.blockMaterial == par2Material) 2364 { 2365 int var13 = this.getBlockMetadata(var9, var10, var11); 2366 double var14 = (double)(var10 + 1); 2367 2368 if (var13 < 8) 2369 { 2370 var14 = (double)(var10 + 1) - (double)var13 / 8.0D; 2371 } 2372 2373 if (var14 >= par1AxisAlignedBB.minY) 2374 { 2375 return true; 2376 } 2377 } 2378 } 2379 } 2380 } 2381 2382 return false; 2383 } 2384 2385 /** 2386 * Creates an explosion. Args: entity, x, y, z, strength 2387 */ 2388 public Explosion createExplosion(Entity par1Entity, double par2, double par4, double par6, float par8) 2389 { 2390 return this.newExplosion(par1Entity, par2, par4, par6, par8, false); 2391 } 2392 2393 /** 2394 * returns a new explosion. Does initiation (at time of writing Explosion is not finished) 2395 */ 2396 public Explosion newExplosion(Entity par1Entity, double par2, double par4, double par6, float par8, boolean par9) 2397 { 2398 Explosion var10 = new Explosion(this, par1Entity, par2, par4, par6, par8); 2399 var10.isFlaming = par9; 2400 var10.doExplosionA(); 2401 var10.doExplosionB(true); 2402 return var10; 2403 } 2404 2405 /** 2406 * Gets the percentage of real blocks within within a bounding box, along a specified vector. 2407 */ 2408 public float getBlockDensity(Vec3 par1Vec3, AxisAlignedBB par2AxisAlignedBB) 2409 { 2410 double var3 = 1.0D / ((par2AxisAlignedBB.maxX - par2AxisAlignedBB.minX) * 2.0D + 1.0D); 2411 double var5 = 1.0D / ((par2AxisAlignedBB.maxY - par2AxisAlignedBB.minY) * 2.0D + 1.0D); 2412 double var7 = 1.0D / ((par2AxisAlignedBB.maxZ - par2AxisAlignedBB.minZ) * 2.0D + 1.0D); 2413 int var9 = 0; 2414 int var10 = 0; 2415 2416 for (float var11 = 0.0F; var11 <= 1.0F; var11 = (float)((double)var11 + var3)) 2417 { 2418 for (float var12 = 0.0F; var12 <= 1.0F; var12 = (float)((double)var12 + var5)) 2419 { 2420 for (float var13 = 0.0F; var13 <= 1.0F; var13 = (float)((double)var13 + var7)) 2421 { 2422 double var14 = par2AxisAlignedBB.minX + (par2AxisAlignedBB.maxX - par2AxisAlignedBB.minX) * (double)var11; 2423 double var16 = par2AxisAlignedBB.minY + (par2AxisAlignedBB.maxY - par2AxisAlignedBB.minY) * (double)var12; 2424 double var18 = par2AxisAlignedBB.minZ + (par2AxisAlignedBB.maxZ - par2AxisAlignedBB.minZ) * (double)var13; 2425 2426 if (this.rayTraceBlocks(Vec3.getVec3Pool().getVecFromPool(var14, var16, var18), par1Vec3) == null) 2427 { 2428 ++var9; 2429 } 2430 2431 ++var10; 2432 } 2433 } 2434 } 2435 2436 return (float)var9 / (float)var10; 2437 } 2438 2439 /** 2440 * If the block in the given direction of the given coordinate is fire, extinguish it. Args: Player, X,Y,Z, 2441 * blockDirection 2442 */ 2443 public boolean extinguishFire(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5) 2444 { 2445 if (par5 == 0) 2446 { 2447 --par3; 2448 } 2449 2450 if (par5 == 1) 2451 { 2452 ++par3; 2453 } 2454 2455 if (par5 == 2) 2456 { 2457 --par4; 2458 } 2459 2460 if (par5 == 3) 2461 { 2462 ++par4; 2463 } 2464 2465 if (par5 == 4) 2466 { 2467 --par2; 2468 } 2469 2470 if (par5 == 5) 2471 { 2472 ++par2; 2473 } 2474 2475 if (this.getBlockId(par2, par3, par4) == Block.fire.blockID) 2476 { 2477 this.playAuxSFXAtEntity(par1EntityPlayer, 1004, par2, par3, par4, 0); 2478 this.setBlockWithNotify(par2, par3, par4, 0); 2479 return true; 2480 } 2481 else 2482 { 2483 return false; 2484 } 2485 } 2486 2487 @SideOnly(Side.CLIENT) 2488 2489 /** 2490 * This string is 'All: (number of loaded entities)' Viewable by press ing F3 2491 */ 2492 public String getDebugLoadedEntities() 2493 { 2494 return "All: " + this.loadedEntityList.size(); 2495 } 2496 2497 @SideOnly(Side.CLIENT) 2498 2499 /** 2500 * Returns the name of the current chunk provider, by calling chunkprovider.makeString() 2501 */ 2502 public String getProviderName() 2503 { 2504 return this.chunkProvider.makeString(); 2505 } 2506 2507 /** 2508 * Returns the TileEntity associated with a given block in X,Y,Z coordinates, or null if no TileEntity exists 2509 */ 2510 public TileEntity getBlockTileEntity(int par1, int par2, int par3) 2511 { 2512 if (par2 >= 256) 2513 { 2514 return null; 2515 } 2516 else 2517 { 2518 Chunk var4 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 2519 2520 if (var4 == null) 2521 { 2522 return null; 2523 } 2524 else 2525 { 2526 TileEntity var5 = var4.getChunkBlockTileEntity(par1 & 15, par2, par3 & 15); 2527 2528 if (var5 == null) 2529 { 2530 Iterator var6 = this.addedTileEntityList.iterator(); 2531 2532 while (var6.hasNext()) 2533 { 2534 TileEntity var7 = (TileEntity)var6.next(); 2535 2536 if (!var7.isInvalid() && var7.xCoord == par1 && var7.yCoord == par2 && var7.zCoord == par3) 2537 { 2538 var5 = var7; 2539 break; 2540 } 2541 } 2542 } 2543 2544 return var5; 2545 } 2546 } 2547 } 2548 2549 /** 2550 * Sets the TileEntity for a given block in X, Y, Z coordinates 2551 */ 2552 public void setBlockTileEntity(int par1, int par2, int par3, TileEntity par4TileEntity) 2553 { 2554 if (par4TileEntity == null || par4TileEntity.isInvalid()) 2555 { 2556 return; 2557 } 2558 2559 if (par4TileEntity.canUpdate()) 2560 { 2561 List dest = scanningTileEntities ? addedTileEntityList : loadedTileEntityList; 2562 dest.add(par4TileEntity); 2563 } 2564 2565 Chunk chunk = getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 2566 if (chunk != null) 2567 { 2568 chunk.setChunkBlockTileEntity(par1 & 15, par2, par3 & 15, par4TileEntity); 2569 } 2570 } 2571 2572 /** 2573 * Removes the TileEntity for a given block in X,Y,Z coordinates 2574 */ 2575 public void removeBlockTileEntity(int par1, int par2, int par3) 2576 { 2577 Chunk chunk = getChunkFromChunkCoords(par1 >> 4, par3 >> 4); 2578 if (chunk != null) 2579 { 2580 chunk.removeChunkBlockTileEntity(par1 & 15, par2, par3 & 15); 2581 } 2582 } 2583 2584 /** 2585 * adds tile entity to despawn list (renamed from markEntityForDespawn) 2586 */ 2587 public void markTileEntityForDespawn(TileEntity par1TileEntity) 2588 { 2589 this.entityRemoval.add(par1TileEntity); 2590 } 2591 2592 /** 2593 * Returns true if the block at the specified coordinates is an opaque cube. Args: x, y, z 2594 */ 2595 public boolean isBlockOpaqueCube(int par1, int par2, int par3) 2596 { 2597 Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)]; 2598 return var4 == null ? false : var4.isOpaqueCube(); 2599 } 2600 2601 /** 2602 * Indicate if a material is a normal solid opaque cube. 2603 */ 2604 public boolean isBlockNormalCube(int par1, int par2, int par3) 2605 { 2606 Block block = Block.blocksList[getBlockId(par1, par2, par3)]; 2607 return block != null && block.isBlockNormalCube(this, par1, par2, par3); 2608 } 2609 2610 /** 2611 * Returns true if the block at the given coordinate has a solid (buildable) top surface. 2612 */ 2613 public boolean doesBlockHaveSolidTopSurface(int par1, int par2, int par3) 2614 { 2615 return isBlockSolidOnSide(par1, par2, par3, ForgeDirection.UP); 2616 } 2617 2618 /** 2619 * Checks if the block is a solid, normal cube. If the chunk does not exist, or is not loaded, it returns the 2620 * boolean parameter. 2621 */ 2622 public boolean isBlockNormalCubeDefault(int par1, int par2, int par3, boolean par4) 2623 { 2624 if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) 2625 { 2626 Chunk var5 = this.chunkProvider.provideChunk(par1 >> 4, par3 >> 4); 2627 2628 if (var5 != null && !var5.isEmpty()) 2629 { 2630 Block var6 = Block.blocksList[this.getBlockId(par1, par2, par3)]; 2631 return var6 == null ? false : isBlockNormalCube(par1, par2, par3); 2632 } 2633 else 2634 { 2635 return par4; 2636 } 2637 } 2638 else 2639 { 2640 return par4; 2641 } 2642 } 2643 2644 /** 2645 * Called on construction of the World class to setup the initial skylight values 2646 */ 2647 public void calculateInitialSkylight() 2648 { 2649 int var1 = this.calculateSkylightSubtracted(1.0F); 2650 2651 if (var1 != this.skylightSubtracted) 2652 { 2653 this.skylightSubtracted = var1; 2654 } 2655 } 2656 2657 /** 2658 * Set which types of mobs are allowed to spawn (peaceful vs hostile). 2659 */ 2660 public void setAllowedSpawnTypes(boolean par1, boolean par2) 2661 { 2662 this.spawnHostileMobs = par1; 2663 this.spawnPeacefulMobs = par2; 2664 } 2665 2666 /** 2667 * Runs a single tick for the world 2668 */ 2669 public void tick() 2670 { 2671 this.updateWeather(); 2672 } 2673 2674 /** 2675 * Called from World constructor to set rainingStrength and thunderingStrength 2676 */ 2677 private void calculateInitialWeather() 2678 { 2679 if (this.worldInfo.isRaining()) 2680 { 2681 this.rainingStrength = 1.0F; 2682 2683 if (this.worldInfo.isThundering()) 2684 { 2685 this.thunderingStrength = 1.0F; 2686 } 2687 } 2688 } 2689 2690 /** 2691 * Updates all weather states. 2692 */ 2693 protected void updateWeather() 2694 { 2695 if (!this.provider.hasNoSky) 2696 { 2697 if (this.lastLightningBolt > 0) 2698 { 2699 --this.lastLightningBolt; 2700 } 2701 2702 int var1 = this.worldInfo.getThunderTime(); 2703 2704 if (var1 <= 0) 2705 { 2706 if (this.worldInfo.isThundering()) 2707 { 2708 this.worldInfo.setThunderTime(this.rand.nextInt(12000) + 3600); 2709 } 2710 else 2711 { 2712 this.worldInfo.setThunderTime(this.rand.nextInt(168000) + 12000); 2713 } 2714 } 2715 else 2716 { 2717 --var1; 2718 this.worldInfo.setThunderTime(var1); 2719 2720 if (var1 <= 0) 2721 { 2722 this.worldInfo.setThundering(!this.worldInfo.isThundering()); 2723 } 2724 } 2725 2726 int var2 = this.worldInfo.getRainTime(); 2727 2728 if (var2 <= 0) 2729 { 2730 if (this.worldInfo.isRaining()) 2731 { 2732 this.worldInfo.setRainTime(this.rand.nextInt(12000) + 12000); 2733 } 2734 else 2735 { 2736 this.worldInfo.setRainTime(this.rand.nextInt(168000) + 12000); 2737 } 2738 } 2739 else 2740 { 2741 --var2; 2742 this.worldInfo.setRainTime(var2); 2743 2744 if (var2 <= 0) 2745 { 2746 this.worldInfo.setRaining(!this.worldInfo.isRaining()); 2747 } 2748 } 2749 2750 this.prevRainingStrength = this.rainingStrength; 2751 2752 if (this.worldInfo.isRaining()) 2753 { 2754 this.rainingStrength = (float)((double)this.rainingStrength + 0.01D); 2755 } 2756 else 2757 { 2758 this.rainingStrength = (float)((double)this.rainingStrength - 0.01D); 2759 } 2760 2761 if (this.rainingStrength < 0.0F) 2762 { 2763 this.rainingStrength = 0.0F; 2764 } 2765 2766 if (this.rainingStrength > 1.0F) 2767 { 2768 this.rainingStrength = 1.0F; 2769 } 2770 2771 this.prevThunderingStrength = this.thunderingStrength; 2772 2773 if (this.worldInfo.isThundering()) 2774 { 2775 this.thunderingStrength = (float)((double)this.thunderingStrength + 0.01D); 2776 } 2777 else 2778 { 2779 this.thunderingStrength = (float)((double)this.thunderingStrength - 0.01D); 2780 } 2781 2782 if (this.thunderingStrength < 0.0F) 2783 { 2784 this.thunderingStrength = 0.0F; 2785 } 2786 2787 if (this.thunderingStrength > 1.0F) 2788 { 2789 this.thunderingStrength = 1.0F; 2790 } 2791 } 2792 } 2793 2794 public void toggleRain() 2795 { 2796 this.worldInfo.setRainTime(1); 2797 } 2798 2799 protected void setActivePlayerChunksAndCheckLight() 2800 { 2801 this.activeChunkSet.clear(); 2802 this.theProfiler.startSection("buildList"); 2803 int var1; 2804 EntityPlayer var2; 2805 int var3; 2806 int var4; 2807 2808 for (var1 = 0; var1 < this.playerEntities.size(); ++var1) 2809 { 2810 var2 = (EntityPlayer)this.playerEntities.get(var1); 2811 var3 = MathHelper.floor_double(var2.posX / 16.0D); 2812 var4 = MathHelper.floor_double(var2.posZ / 16.0D); 2813 byte var5 = 7; 2814 2815 for (int var6 = -var5; var6 <= var5; ++var6) 2816 { 2817 for (int var7 = -var5; var7 <= var5; ++var7) 2818 { 2819 this.activeChunkSet.add(new ChunkCoordIntPair(var6 + var3, var7 + var4)); 2820 } 2821 } 2822 } 2823 2824 this.theProfiler.endSection(); 2825 2826 if (this.ambientTickCountdown > 0) 2827 { 2828 --this.ambientTickCountdown; 2829 } 2830 2831 this.theProfiler.startSection("playerCheckLight"); 2832 2833 if (!this.playerEntities.isEmpty()) 2834 { 2835 var1 = this.rand.nextInt(this.playerEntities.size()); 2836 var2 = (EntityPlayer)this.playerEntities.get(var1); 2837 var3 = MathHelper.floor_double(var2.posX) + this.rand.nextInt(11) - 5; 2838 var4 = MathHelper.floor_double(var2.posY) + this.rand.nextInt(11) - 5; 2839 int var8 = MathHelper.floor_double(var2.posZ) + this.rand.nextInt(11) - 5; 2840 this.updateAllLightTypes(var3, var4, var8); 2841 } 2842 2843 this.theProfiler.endSection(); 2844 } 2845 2846 protected void moodSoundAndLightCheck(int par1, int par2, Chunk par3Chunk) 2847 { 2848 this.theProfiler.endStartSection("moodSound"); 2849 2850 if (this.ambientTickCountdown == 0) 2851 { 2852 this.updateLCG = this.updateLCG * 3 + 1013904223; 2853 int var4 = this.updateLCG >> 2; 2854 int var5 = var4 & 15; 2855 int var6 = var4 >> 8 & 15; 2856 int var7 = var4 >> 16 & 127; 2857 int var8 = par3Chunk.getBlockID(var5, var7, var6); 2858 var5 += par1; 2859 var6 += par2; 2860 2861 if (var8 == 0 && this.getFullBlockLightValue(var5, var7, var6) <= this.rand.nextInt(8) && this.getSavedLightValue(EnumSkyBlock.Sky, var5, var7, var6) <= 0) 2862 { 2863 EntityPlayer var9 = this.getClosestPlayer((double)var5 + 0.5D, (double)var7 + 0.5D, (double)var6 + 0.5D, 8.0D); 2864 2865 if (var9 != null && var9.getDistanceSq((double)var5 + 0.5D, (double)var7 + 0.5D, (double)var6 + 0.5D) > 4.0D) 2866 { 2867 this.playSoundEffect((double)var5 + 0.5D, (double)var7 + 0.5D, (double)var6 + 0.5D, "ambient.cave.cave", 0.7F, 0.8F + this.rand.nextFloat() * 0.2F); 2868 this.ambientTickCountdown = this.rand.nextInt(12000) + 6000; 2869 } 2870 } 2871 } 2872 2873 this.theProfiler.endStartSection("checkLight"); 2874 par3Chunk.enqueueRelightChecks(); 2875 } 2876 2877 /** 2878 * plays random cave ambient sounds and runs updateTick on random blocks within each chunk in the vacinity of a 2879 * player 2880 */ 2881 protected void tickBlocksAndAmbiance() 2882 { 2883 this.setActivePlayerChunksAndCheckLight(); 2884 } 2885 2886 /** 2887 * checks to see if a given block is both water and is cold enough to freeze 2888 */ 2889 public boolean isBlockFreezable(int par1, int par2, int par3) 2890 { 2891 return this.canBlockFreeze(par1, par2, par3, false); 2892 } 2893 2894 /** 2895 * checks to see if a given block is both water and has at least one immediately adjacent non-water block 2896 */ 2897 public boolean isBlockFreezableNaturally(int par1, int par2, int par3) 2898 { 2899 return this.canBlockFreeze(par1, par2, par3, true); 2900 } 2901 2902 /** 2903 * checks to see if a given block is both water, and cold enough to freeze - if the par4 boolean is set, this will 2904 * only return true if there is a non-water block immediately adjacent to the specified block 2905 */ 2906 public boolean canBlockFreeze(int par1, int par2, int par3, boolean par4) 2907 { 2908 BiomeGenBase var5 = this.getBiomeGenForCoords(par1, par3); 2909 float var6 = var5.getFloatTemperature(); 2910 2911 if (var6 > 0.15F) 2912 { 2913 return false; 2914 } 2915 else 2916 { 2917 if (par2 >= 0 && par2 < 256 && this.getSavedLightValue(EnumSkyBlock.Block, par1, par2, par3) < 10) 2918 { 2919 int var7 = this.getBlockId(par1, par2, par3); 2920 2921 if ((var7 == Block.waterStill.blockID || var7 == Block.waterMoving.blockID) && this.getBlockMetadata(par1, par2, par3) == 0) 2922 { 2923 if (!par4) 2924 { 2925 return true; 2926 } 2927 2928 boolean var8 = true; 2929 2930 if (var8 && this.getBlockMaterial(par1 - 1, par2, par3) != Material.water) 2931 { 2932 var8 = false; 2933 } 2934 2935 if (var8 && this.getBlockMaterial(par1 + 1, par2, par3) != Material.water) 2936 { 2937 var8 = false; 2938 } 2939 2940 if (var8 && this.getBlockMaterial(par1, par2, par3 - 1) != Material.water) 2941 { 2942 var8 = false; 2943 } 2944 2945 if (var8 && this.getBlockMaterial(par1, par2, par3 + 1) != Material.water) 2946 { 2947 var8 = false; 2948 } 2949 2950 if (!var8) 2951 { 2952 return true; 2953 } 2954 } 2955 } 2956 2957 return false; 2958 } 2959 } 2960 2961 /** 2962 * Tests whether or not snow can be placed at a given location 2963 */ 2964 public boolean canSnowAt(int par1, int par2, int par3) 2965 { 2966 BiomeGenBase var4 = this.getBiomeGenForCoords(par1, par3); 2967 float var5 = var4.getFloatTemperature(); 2968 2969 if (var5 > 0.15F) 2970 { 2971 return false; 2972 } 2973 else 2974 { 2975 if (par2 >= 0 && par2 < 256 && this.getSavedLightValue(EnumSkyBlock.Block, par1, par2, par3) < 10) 2976 { 2977 int var6 = this.getBlockId(par1, par2 - 1, par3); 2978 int var7 = this.getBlockId(par1, par2, par3); 2979 2980 if (var7 == 0 && Block.snow.canPlaceBlockAt(this, par1, par2, par3) && var6 != 0 && var6 != Block.ice.blockID && Block.blocksList[var6].blockMaterial.blocksMovement()) 2981 { 2982 return true; 2983 } 2984 } 2985 2986 return false; 2987 } 2988 } 2989 2990 public void updateAllLightTypes(int par1, int par2, int par3) 2991 { 2992 if (!this.provider.hasNoSky) 2993 { 2994 this.updateLightByType(EnumSkyBlock.Sky, par1, par2, par3); 2995 } 2996 2997 this.updateLightByType(EnumSkyBlock.Block, par1, par2, par3); 2998 } 2999 3000 private int computeSkyLightValue(int par1, int par2, int par3, int par4, int par5, int par6) 3001 { 3002 int var7 = 0; 3003 3004 if (this.canBlockSeeTheSky(par2, par3, par4)) 3005 { 3006 var7 = 15; 3007 } 3008 else 3009 { 3010 if (par6 == 0) 3011 { 3012 par6 = 1; 3013 } 3014 3015 int var8 = this.getSavedLightValue(EnumSkyBlock.Sky, par2 - 1, par3, par4) - par6; 3016 int var9 = this.getSavedLightValue(EnumSkyBlock.Sky, par2 + 1, par3, par4) - par6; 3017 int var10 = this.getSavedLightValue(EnumSkyBlock.Sky, par2, par3 - 1, par4) - par6; 3018 int var11 = this.getSavedLightValue(EnumSkyBlock.Sky, par2, par3 + 1, par4) - par6; 3019 int var12 = this.getSavedLightValue(EnumSkyBlock.Sky, par2, par3, par4 - 1) - par6; 3020 int var13 = this.getSavedLightValue(EnumSkyBlock.Sky, par2, par3, par4 + 1) - par6; 3021 3022 if (var8 > var7) 3023 { 3024 var7 = var8; 3025 } 3026 3027 if (var9 > var7) 3028 { 3029 var7 = var9; 3030 } 3031 3032 if (var10 > var7) 3033 { 3034 var7 = var10; 3035 } 3036 3037 if (var11 > var7) 3038 { 3039 var7 = var11; 3040 } 3041 3042 if (var12 > var7) 3043 { 3044 var7 = var12; 3045 } 3046 3047 if (var13 > var7) 3048 { 3049 var7 = var13; 3050 } 3051 } 3052 3053 return var7; 3054 } 3055 3056 private int computeBlockLightValue(int par1, int par2, int par3, int par4, int par5, int par6) 3057 { 3058 int var7 = (par5 == 0 || Block.blocksList[par5] == null ? 0 : Block.blocksList[par5].getLightValue(this, par2, par3, par4)); 3059 int var8 = this.getSavedLightValue(EnumSkyBlock.Block, par2 - 1, par3, par4) - par6; 3060 int var9 = this.getSavedLightValue(EnumSkyBlock.Block, par2 + 1, par3, par4) - par6; 3061 int var10 = this.getSavedLightValue(EnumSkyBlock.Block, par2, par3 - 1, par4) - par6; 3062 int var11 = this.getSavedLightValue(EnumSkyBlock.Block, par2, par3 + 1, par4) - par6; 3063 int var12 = this.getSavedLightValue(EnumSkyBlock.Block, par2, par3, par4 - 1) - par6; 3064 int var13 = this.getSavedLightValue(EnumSkyBlock.Block, par2, par3, par4 + 1) - par6; 3065 3066 if (var8 > var7) 3067 { 3068 var7 = var8; 3069 } 3070 3071 if (var9 > var7) 3072 { 3073 var7 = var9; 3074 } 3075 3076 if (var10 > var7) 3077 { 3078 var7 = var10; 3079 } 3080 3081 if (var11 > var7) 3082 { 3083 var7 = var11; 3084 } 3085 3086 if (var12 > var7) 3087 { 3088 var7 = var12; 3089 } 3090 3091 if (var13 > var7) 3092 { 3093 var7 = var13; 3094 } 3095 3096 return var7; 3097 } 3098 3099 public void updateLightByType(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) 3100 { 3101 if (this.doChunksNearChunkExist(par2, par3, par4, 17)) 3102 { 3103 int var5 = 0; 3104 int var6 = 0; 3105 this.theProfiler.startSection("getBrightness"); 3106 int var7 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3, par4); 3107 boolean var8 = false; 3108 int var9 = this.getBlockId(par2, par3, par4); 3109 int var10 = this.getBlockLightOpacity(par2, par3, par4); 3110 3111 if (var10 == 0) 3112 { 3113 var10 = 1; 3114 } 3115 3116 boolean var11 = false; 3117 int var24; 3118 3119 if (par1EnumSkyBlock == EnumSkyBlock.Sky) 3120 { 3121 var24 = this.computeSkyLightValue(var7, par2, par3, par4, var9, var10); 3122 } 3123 else 3124 { 3125 var24 = this.computeBlockLightValue(var7, par2, par3, par4, var9, var10); 3126 } 3127 3128 int var12; 3129 int var13; 3130 int var14; 3131 int var15; 3132 int var17; 3133 int var16; 3134 int var19; 3135 int var18; 3136 3137 if (var24 > var7) 3138 { 3139 this.lightUpdateBlockList[var6++] = 133152; 3140 } 3141 else if (var24 < var7) 3142 { 3143 if (par1EnumSkyBlock != EnumSkyBlock.Block) 3144 { 3145 ; 3146 } 3147 3148 this.lightUpdateBlockList[var6++] = 133152 + (var7 << 18); 3149 3150 while (var5 < var6) 3151 { 3152 var9 = this.lightUpdateBlockList[var5++]; 3153 var10 = (var9 & 63) - 32 + par2; 3154 var24 = (var9 >> 6 & 63) - 32 + par3; 3155 var12 = (var9 >> 12 & 63) - 32 + par4; 3156 var13 = var9 >> 18 & 15; 3157 var14 = this.getSavedLightValue(par1EnumSkyBlock, var10, var24, var12); 3158 3159 if (var14 == var13) 3160 { 3161 this.setLightValue(par1EnumSkyBlock, var10, var24, var12, 0); 3162 3163 if (var13 > 0) 3164 { 3165 var15 = var10 - par2; 3166 var16 = var24 - par3; 3167 var17 = var12 - par4; 3168 3169 if (var15 < 0) 3170 { 3171 var15 = -var15; 3172 } 3173 3174 if (var16 < 0) 3175 { 3176 var16 = -var16; 3177 } 3178 3179 if (var17 < 0) 3180 { 3181 var17 = -var17; 3182 } 3183 3184 if (var15 + var16 + var17 < 17) 3185 { 3186 for (var18 = 0; var18 < 6; ++var18) 3187 { 3188 var19 = var18 % 2 * 2 - 1; 3189 int var20 = var10 + var18 / 2 % 3 / 2 * var19; 3190 int var21 = var24 + (var18 / 2 + 1) % 3 / 2 * var19; 3191 int var22 = var12 + (var18 / 2 + 2) % 3 / 2 * var19; 3192 var14 = this.getSavedLightValue(par1EnumSkyBlock, var20, var21, var22); 3193 int var23 = Block.lightOpacity[this.getBlockId(var20, var21, var22)]; 3194 3195 if (var23 == 0) 3196 { 3197 var23 = 1; 3198 } 3199 3200 if (var14 == var13 - var23 && var6 < this.lightUpdateBlockList.length) 3201 { 3202 this.lightUpdateBlockList[var6++] = var20 - par2 + 32 + (var21 - par3 + 32 << 6) + (var22 - par4 + 32 << 12) + (var13 - var23 << 18); 3203 } 3204 } 3205 } 3206 } 3207 } 3208 } 3209 3210 var5 = 0; 3211 } 3212 3213 this.theProfiler.endSection(); 3214 this.theProfiler.startSection("tcp < tcc"); 3215 3216 while (var5 < var6) 3217 { 3218 var9 = this.lightUpdateBlockList[var5++]; 3219 var10 = (var9 & 63) - 32 + par2; 3220 var24 = (var9 >> 6 & 63) - 32 + par3; 3221 var12 = (var9 >> 12 & 63) - 32 + par4; 3222 var13 = this.getSavedLightValue(par1EnumSkyBlock, var10, var24, var12); 3223 var14 = this.getBlockId(var10, var24, var12); 3224 var15 = Block.lightOpacity[var14]; 3225 3226 if (var15 == 0) 3227 { 3228 var15 = 1; 3229 } 3230 3231 boolean var25 = false; 3232 3233 if (par1EnumSkyBlock == EnumSkyBlock.Sky) 3234 { 3235 var16 = this.computeSkyLightValue(var13, var10, var24, var12, var14, var15); 3236 } 3237 else 3238 { 3239 var16 = this.computeBlockLightValue(var13, var10, var24, var12, var14, var15); 3240 } 3241 3242 if (var16 != var13) 3243 { 3244 this.setLightValue(par1EnumSkyBlock, var10, var24, var12, var16); 3245 3246 if (var16 > var13) 3247 { 3248 var17 = var10 - par2; 3249 var18 = var24 - par3; 3250 var19 = var12 - par4; 3251 3252 if (var17 < 0) 3253 { 3254 var17 = -var17; 3255 } 3256 3257 if (var18 < 0) 3258 { 3259 var18 = -var18; 3260 } 3261 3262 if (var19 < 0) 3263 { 3264 var19 = -var19; 3265 } 3266 3267 if (var17 + var18 + var19 < 17 && var6 < this.lightUpdateBlockList.length - 6) 3268 { 3269 if (this.getSavedLightValue(par1EnumSkyBlock, var10 - 1, var24, var12) < var16) 3270 { 3271 this.lightUpdateBlockList[var6++] = var10 - 1 - par2 + 32 + (var24 - par3 + 32 << 6) + (var12 - par4 + 32 << 12); 3272 } 3273 3274 if (this.getSavedLightValue(par1EnumSkyBlock, var10 + 1, var24, var12) < var16) 3275 { 3276 this.lightUpdateBlockList[var6++] = var10 + 1 - par2 + 32 + (var24 - par3 + 32 << 6) + (var12 - par4 + 32 << 12); 3277 } 3278 3279 if (this.getSavedLightValue(par1EnumSkyBlock, var10, var24 - 1, var12) < var16) 3280 { 3281 this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var24 - 1 - par3 + 32 << 6) + (var12 - par4 + 32 << 12); 3282 } 3283 3284 if (this.getSavedLightValue(par1EnumSkyBlock, var10, var24 + 1, var12) < var16) 3285 { 3286 this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var24 + 1 - par3 + 32 << 6) + (var12 - par4 + 32 << 12); 3287 } 3288 3289 if (this.getSavedLightValue(par1EnumSkyBlock, var10, var24, var12 - 1) < var16) 3290 { 3291 this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var24 - par3 + 32 << 6) + (var12 - 1 - par4 + 32 << 12); 3292 } 3293 3294 if (this.getSavedLightValue(par1EnumSkyBlock, var10, var24, var12 + 1) < var16) 3295 { 3296 this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var24 - par3 + 32 << 6) + (var12 + 1 - par4 + 32 << 12); 3297 } 3298 } 3299 } 3300 } 3301 } 3302 3303 this.theProfiler.endSection(); 3304 } 3305 } 3306 3307 /** 3308 * Runs through the list of updates to run and ticks them 3309 */ 3310 public boolean tickUpdates(boolean par1) 3311 { 3312 return false; 3313 } 3314 3315 public List getPendingBlockUpdates(Chunk par1Chunk, boolean par2) 3316 { 3317 return null; 3318 } 3319 3320 /** 3321 * Will get all entities within the specified AABB excluding the one passed into it. Args: entityToExclude, aabb 3322 */ 3323 public List getEntitiesWithinAABBExcludingEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB) 3324 { 3325 this.entitiesWithinAABBExcludingEntity.clear(); 3326 int var3 = MathHelper.floor_double((par2AxisAlignedBB.minX - MAX_ENTITY_RADIUS) / 16.0D); 3327 int var4 = MathHelper.floor_double((par2AxisAlignedBB.maxX + MAX_ENTITY_RADIUS) / 16.0D); 3328 int var5 = MathHelper.floor_double((par2AxisAlignedBB.minZ - MAX_ENTITY_RADIUS) / 16.0D); 3329 int var6 = MathHelper.floor_double((par2AxisAlignedBB.maxZ + MAX_ENTITY_RADIUS) / 16.0D); 3330 3331 for (int var7 = var3; var7 <= var4; ++var7) 3332 { 3333 for (int var8 = var5; var8 <= var6; ++var8) 3334 { 3335 if (this.chunkExists(var7, var8)) 3336 { 3337 this.getChunkFromChunkCoords(var7, var8).getEntitiesWithinAABBForEntity(par1Entity, par2AxisAlignedBB, this.entitiesWithinAABBExcludingEntity); 3338 } 3339 } 3340 } 3341 3342 return this.entitiesWithinAABBExcludingEntity; 3343 } 3344 3345 /** 3346 * Returns all entities of the specified class type which intersect with the AABB. Args: entityClass, aabb 3347 */ 3348 public List getEntitiesWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB) 3349 { 3350 int var3 = MathHelper.floor_double((par2AxisAlignedBB.minX - MAX_ENTITY_RADIUS) / 16.0D); 3351 int var4 = MathHelper.floor_double((par2AxisAlignedBB.maxX + MAX_ENTITY_RADIUS) / 16.0D); 3352 int var5 = MathHelper.floor_double((par2AxisAlignedBB.minZ - MAX_ENTITY_RADIUS) / 16.0D); 3353 int var6 = MathHelper.floor_double((par2AxisAlignedBB.maxZ + MAX_ENTITY_RADIUS) / 16.0D); 3354 ArrayList var7 = new ArrayList(); 3355 3356 for (int var8 = var3; var8 <= var4; ++var8) 3357 { 3358 for (int var9 = var5; var9 <= var6; ++var9) 3359 { 3360 if (this.chunkExists(var8, var9)) 3361 { 3362 this.getChunkFromChunkCoords(var8, var9).getEntitiesOfTypeWithinAAAB(par1Class, par2AxisAlignedBB, var7); 3363 } 3364 } 3365 } 3366 3367 return var7; 3368 } 3369 3370 public Entity findNearestEntityWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB, Entity par3Entity) 3371 { 3372 List var4 = this.getEntitiesWithinAABB(par1Class, par2AxisAlignedBB); 3373 Entity var5 = null; 3374 double var6 = Double.MAX_VALUE; 3375 Iterator var8 = var4.iterator(); 3376 3377 while (var8.hasNext()) 3378 { 3379 Entity var9 = (Entity)var8.next(); 3380 3381 if (var9 != par3Entity) 3382 { 3383 double var10 = par3Entity.getDistanceSqToEntity(var9); 3384 3385 if (var10 <= var6) 3386 { 3387 var5 = var9; 3388 var6 = var10; 3389 } 3390 } 3391 } 3392 3393 return var5; 3394 } 3395 3396 @SideOnly(Side.CLIENT) 3397 3398 /** 3399 * Accessor for world Loaded Entity List 3400 */ 3401 public List getLoadedEntityList() 3402 { 3403 return this.loadedEntityList; 3404 } 3405 3406 /** 3407 * marks the chunk that contains this tilentity as modified and then calls worldAccesses.doNothingWithTileEntity 3408 */ 3409 public void updateTileEntityChunkAndDoNothing(int par1, int par2, int par3, TileEntity par4TileEntity) 3410 { 3411 if (this.blockExists(par1, par2, par3)) 3412 { 3413 this.getChunkFromBlockCoords(par1, par3).setChunkModified(); 3414 } 3415 } 3416 3417 /** 3418 * Counts how many entities of an entity class exist in the world. Args: entityClass 3419 */ 3420 public int countEntities(Class par1Class) 3421 { 3422 int var2 = 0; 3423 3424 for (int var3 = 0; var3 < this.loadedEntityList.size(); ++var3) 3425 { 3426 Entity var4 = (Entity)this.loadedEntityList.get(var3); 3427 3428 if (par1Class.isAssignableFrom(var4.getClass())) 3429 { 3430 ++var2; 3431 } 3432 } 3433 3434 return var2; 3435 } 3436 3437 /** 3438 * adds entities to the loaded entities list, and loads thier skins. 3439 */ 3440 public void addLoadedEntities(List par1List) 3441 { 3442 this.loadedEntityList.addAll(par1List); 3443 3444 for (int var2 = 0; var2 < par1List.size(); ++var2) 3445 { 3446 this.obtainEntitySkin((Entity)par1List.get(var2)); 3447 } 3448 } 3449 3450 /** 3451 * Adds a list of entities to be unloaded on the next pass of World.updateEntities() 3452 */ 3453 public void unloadEntities(List par1List) 3454 { 3455 this.unloadedEntityList.addAll(par1List); 3456 } 3457 3458 /** 3459 * Returns true if the given Entity can be placed on the given side of the given block position. 3460 */ 3461 public boolean canPlaceEntityOnSide(int par1, int par2, int par3, int par4, boolean par5, int par6, Entity par7Entity) 3462 { 3463 int var8 = this.getBlockId(par2, par3, par4); 3464 Block var9 = Block.blocksList[var8]; 3465 Block var10 = Block.blocksList[par1]; 3466 AxisAlignedBB var11 = var10.getCollisionBoundingBoxFromPool(this, par2, par3, par4); 3467 3468 if (par5) 3469 { 3470 var11 = null; 3471 } 3472 3473 if (var11 != null && !this.checkIfAABBIsClearExcludingEntity(var11, par7Entity)) 3474 { 3475 return false; 3476 } 3477 else 3478 { 3479 if (var9 != null && (var9 == Block.waterMoving || var9 == Block.waterStill || var9 == Block.lavaMoving || var9 == Block.lavaStill || var9 == Block.fire || var9.blockMaterial.isGroundCover())) 3480 { 3481 var9 = null; 3482 } 3483 if (var9 != null && var9.isBlockReplaceable(this, par2, par3, par4)) 3484 { 3485 var9 = null; 3486 } 3487 return par1 > 0 && var9 == null && var10.canPlaceBlockOnSide(this, par2, par3, par4, par6); 3488 } 3489 } 3490 3491 public PathEntity getPathEntityToEntity(Entity par1Entity, Entity par2Entity, float par3, boolean par4, boolean par5, boolean par6, boolean par7) 3492 { 3493 this.theProfiler.startSection("pathfind"); 3494 int var8 = MathHelper.floor_double(par1Entity.posX); 3495 int var9 = MathHelper.floor_double(par1Entity.posY + 1.0D); 3496 int var10 = MathHelper.floor_double(par1Entity.posZ); 3497 int var11 = (int)(par3 + 16.0F); 3498 int var12 = var8 - var11; 3499 int var13 = var9 - var11; 3500 int var14 = var10 - var11; 3501 int var15 = var8 + var11; 3502 int var16 = var9 + var11; 3503 int var17 = var10 + var11; 3504 ChunkCache var18 = new ChunkCache(this, var12, var13, var14, var15, var16, var17); 3505 PathEntity var19 = (new PathFinder(var18, par4, par5, par6, par7)).createEntityPathTo(par1Entity, par2Entity, par3); 3506 this.theProfiler.endSection(); 3507 return var19; 3508 } 3509 3510 public PathEntity getEntityPathToXYZ(Entity par1Entity, int par2, int par3, int par4, float par5, boolean par6, boolean par7, boolean par8, boolean par9) 3511 { 3512 this.theProfiler.startSection("pathfind"); 3513 int var10 = MathHelper.floor_double(par1Entity.posX); 3514 int var11 = MathHelper.floor_double(par1Entity.posY); 3515 int var12 = MathHelper.floor_double(par1Entity.posZ); 3516 int var13 = (int)(par5 + 8.0F); 3517 int var14 = var10 - var13; 3518 int var15 = var11 - var13; 3519 int var16 = var12 - var13; 3520 int var17 = var10 + var13; 3521 int var18 = var11 + var13; 3522 int var19 = var12 + var13; 3523 ChunkCache var20 = new ChunkCache(this, var14, var15, var16, var17, var18, var19); 3524 PathEntity var21 = (new PathFinder(var20, par6, par7, par8, par9)).createEntityPathTo(par1Entity, par2, par3, par4, par5); 3525 this.theProfiler.endSection(); 3526 return var21; 3527 } 3528 3529 /** 3530 * Is this block powering in the specified direction Args: x, y, z, direction 3531 */ 3532 public boolean isBlockProvidingPowerTo(int par1, int par2, int par3, int par4) 3533 { 3534 int var5 = this.getBlockId(par1, par2, par3); 3535 return var5 == 0 ? false : Block.blocksList[var5].isIndirectlyPoweringTo(this, par1, par2, par3, par4); 3536 } 3537 3538 /** 3539 * Whether one of the neighboring blocks is putting power into this block. Args: x, y, z 3540 */ 3541 public boolean isBlockGettingPowered(int par1, int par2, int par3) 3542 { 3543 return this.isBlockProvidingPowerTo(par1, par2 - 1, par3, 0) ? true : (this.isBlockProvidingPowerTo(par1, par2 + 1, par3, 1) ? true : (this.isBlockProvidingPowerTo(par1, par2, par3 - 1, 2) ? true : (this.isBlockProvidingPowerTo(par1, par2, par3 + 1, 3) ? true : (this.isBlockProvidingPowerTo(par1 - 1, par2, par3, 4) ? true : this.isBlockProvidingPowerTo(par1 + 1, par2, par3, 5))))); 3544 } 3545 3546 /** 3547 * Is a block next to you getting powered (if its an attachable block) or is it providing power directly to you. 3548 * Args: x, y, z, direction 3549 */ 3550 public boolean isBlockIndirectlyProvidingPowerTo(int par1, int par2, int par3, int par4) 3551 { 3552 if (this.isBlockNormalCube(par1, par2, par3)) 3553 { 3554 return this.isBlockGettingPowered(par1, par2, par3); 3555 } 3556 else 3557 { 3558 int var5 = this.getBlockId(par1, par2, par3); 3559 return var5 == 0 ? false : Block.blocksList[var5].isPoweringTo(this, par1, par2, par3, par4); 3560 } 3561 } 3562 3563 /** 3564 * Used to see if one of the blocks next to you or your block is getting power from a neighboring block. Used by 3565 * items like TNT or Doors so they don't have redstone going straight into them. Args: x, y, z 3566 */ 3567 public boolean isBlockIndirectlyGettingPowered(int par1, int par2, int par3) 3568 { 3569 return this.isBlockIndirectlyProvidingPowerTo(par1, par2 - 1, par3, 0) ? true : (this.isBlockIndirectlyProvidingPowerTo(par1, par2 + 1, par3, 1) ? true : (this.isBlockIndirectlyProvidingPowerTo(par1, par2, par3 - 1, 2) ? true : (this.isBlockIndirectlyProvidingPowerTo(par1, par2, par3 + 1, 3) ? true : (this.isBlockIndirectlyProvidingPowerTo(par1 - 1, par2, par3, 4) ? true : this.isBlockIndirectlyProvidingPowerTo(par1 + 1, par2, par3, 5))))); 3570 } 3571 3572 /** 3573 * Gets the closest player to the entity within the specified distance (if distance is less than 0 then ignored). 3574 * Args: entity, dist 3575 */ 3576 public EntityPlayer getClosestPlayerToEntity(Entity par1Entity, double par2) 3577 { 3578 return this.getClosestPlayer(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par2); 3579 } 3580 3581 /** 3582 * Gets the closest player to the point within the specified distance (distance can be set to less than 0 to not 3583 * limit the distance). Args: x, y, z, dist 3584 */ 3585 public EntityPlayer getClosestPlayer(double par1, double par3, double par5, double par7) 3586 { 3587 double var9 = -1.0D; 3588 EntityPlayer var11 = null; 3589 3590 for (int var12 = 0; var12 < this.playerEntities.size(); ++var12) 3591 { 3592 EntityPlayer var13 = (EntityPlayer)this.playerEntities.get(var12); 3593 double var14 = var13.getDistanceSq(par1, par3, par5); 3594 3595 if ((par7 < 0.0D || var14 < par7 * par7) && (var9 == -1.0D || var14 < var9)) 3596 { 3597 var9 = var14; 3598 var11 = var13; 3599 } 3600 } 3601 3602 return var11; 3603 } 3604 3605 /** 3606 * Returns the closest vulnerable player to this entity within the given radius, or null if none is found 3607 */ 3608 public EntityPlayer getClosestVulnerablePlayerToEntity(Entity par1Entity, double par2) 3609 { 3610 return this.getClosestVulnerablePlayer(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par2); 3611 } 3612 3613 /** 3614 * Returns the closest vulnerable player within the given radius, or null if none is found. 3615 */ 3616 public EntityPlayer getClosestVulnerablePlayer(double par1, double par3, double par5, double par7) 3617 { 3618 double var9 = -1.0D; 3619 EntityPlayer var11 = null; 3620 3621 for (int var12 = 0; var12 < this.playerEntities.size(); ++var12) 3622 { 3623 EntityPlayer var13 = (EntityPlayer)this.playerEntities.get(var12); 3624 3625 if (!var13.capabilities.disableDamage) 3626 { 3627 double var14 = var13.getDistanceSq(par1, par3, par5); 3628 3629 if ((par7 < 0.0D || var14 < par7 * par7) && (var9 == -1.0D || var14 < var9)) 3630 { 3631 var9 = var14; 3632 var11 = var13; 3633 } 3634 } 3635 } 3636 3637 return var11; 3638 } 3639 3640 /** 3641 * Find a player by name in this world. 3642 */ 3643 public EntityPlayer getPlayerEntityByName(String par1Str) 3644 { 3645 for (int var2 = 0; var2 < this.playerEntities.size(); ++var2) 3646 { 3647 if (par1Str.equals(((EntityPlayer)this.playerEntities.get(var2)).username)) 3648 { 3649 return (EntityPlayer)this.playerEntities.get(var2); 3650 } 3651 } 3652 3653 return null; 3654 } 3655 3656 @SideOnly(Side.CLIENT) 3657 3658 /** 3659 * If on MP, sends a quitting packet. 3660 */ 3661 public void sendQuittingDisconnectingPacket() {} 3662 3663 /** 3664 * Checks whether the session lock file was modified by another process 3665 */ 3666 public void checkSessionLock() throws MinecraftException 3667 { 3668 this.saveHandler.checkSessionLock(); 3669 } 3670 3671 /** 3672 * Sets the world time. 3673 */ 3674 public void setWorldTime(long par1) 3675 { 3676 this.worldInfo.setWorldTime(par1); 3677 } 3678 3679 /** 3680 * Retrieve the world seed from level.dat 3681 */ 3682 public long getSeed() 3683 { 3684 return this.worldInfo.getSeed(); 3685 } 3686 3687 public long getWorldTime() 3688 { 3689 return this.worldInfo.getWorldTime(); 3690 } 3691 3692 /** 3693 * Returns the coordinates of the spawn point 3694 */ 3695 public ChunkCoordinates getSpawnPoint() 3696 { 3697 return new ChunkCoordinates(this.worldInfo.getSpawnX(), this.worldInfo.getSpawnY(), this.worldInfo.getSpawnZ()); 3698 } 3699 3700 @SideOnly(Side.CLIENT) 3701 public void setSpawnLocation(int par1, int par2, int par3) 3702 { 3703 this.worldInfo.setSpawnPosition(par1, par2, par3); 3704 } 3705 3706 @SideOnly(Side.CLIENT) 3707 3708 /** 3709 * spwans an entity and loads surrounding chunks 3710 */ 3711 public void joinEntityInSurroundings(Entity par1Entity) 3712 { 3713 int var2 = MathHelper.floor_double(par1Entity.posX / 16.0D); 3714 int var3 = MathHelper.floor_double(par1Entity.posZ / 16.0D); 3715 byte var4 = 2; 3716 3717 for (int var5 = var2 - var4; var5 <= var2 + var4; ++var5) 3718 { 3719 for (int var6 = var3 - var4; var6 <= var3 + var4; ++var6) 3720 { 3721 this.getChunkFromChunkCoords(var5, var6); 3722 } 3723 } 3724 3725 if (!this.loadedEntityList.contains(par1Entity)) 3726 { 3727 this.loadedEntityList.add(par1Entity); 3728 } 3729 } 3730 3731 /** 3732 * Called when checking if a certain block can be mined or not. The 'spawn safe zone' check is located here. 3733 */ 3734 public boolean canMineBlock(EntityPlayer par1EntityPlayer, int par2, int par3, int par4) 3735 { 3736 return true; 3737 } 3738 3739 /** 3740 * sends a Packet 38 (Entity Status) to all tracked players of that entity 3741 */ 3742 public void setEntityState(Entity par1Entity, byte par2) {} 3743 3744 /** 3745 * gets the IChunkProvider this world uses. 3746 */ 3747 public IChunkProvider getChunkProvider() 3748 { 3749 return this.chunkProvider; 3750 } 3751 3752 /** 3753 * Adds a block event with the given Args to the blockEventCache. During the next tick(), the block specified will 3754 * have its onBlockEvent handler called with the given parameters. Args: X,Y,Z, BlockID, EventID, EventParameter 3755 */ 3756 public void addBlockEvent(int par1, int par2, int par3, int par4, int par5, int par6) 3757 { 3758 if (par4 > 0) 3759 { 3760 Block.blocksList[par4].onBlockEventReceived(this, par1, par2, par3, par5, par6); 3761 } 3762 } 3763 3764 /** 3765 * Returns this world's current save handler 3766 */ 3767 public ISaveHandler getSaveHandler() 3768 { 3769 return this.saveHandler; 3770 } 3771 3772 /** 3773 * Gets the World's WorldInfo instance 3774 */ 3775 public WorldInfo getWorldInfo() 3776 { 3777 return this.worldInfo; 3778 } 3779 3780 /** 3781 * Updates the flag that indicates whether or not all players in the world are sleeping. 3782 */ 3783 public void updateAllPlayersSleepingFlag() {} 3784 3785 public float getWeightedThunderStrength(float par1) 3786 { 3787 return (this.prevThunderingStrength + (this.thunderingStrength - this.prevThunderingStrength) * par1) * this.getRainStrength(par1); 3788 } 3789 3790 /** 3791 * Not sure about this actually. Reverting this one myself. 3792 */ 3793 public float getRainStrength(float par1) 3794 { 3795 return this.prevRainingStrength + (this.rainingStrength - this.prevRainingStrength) * par1; 3796 } 3797 3798 @SideOnly(Side.CLIENT) 3799 public void setRainStrength(float par1) 3800 { 3801 this.prevRainingStrength = par1; 3802 this.rainingStrength = par1; 3803 } 3804 3805 /** 3806 * Returns true if the current thunder strength (weighted with the rain strength) is greater than 0.9 3807 */ 3808 public boolean isThundering() 3809 { 3810 return (double)this.getWeightedThunderStrength(1.0F) > 0.9D; 3811 } 3812 3813 /** 3814 * Returns true if the current rain strength is greater than 0.2 3815 */ 3816 public boolean isRaining() 3817 { 3818 return (double)this.getRainStrength(1.0F) > 0.2D; 3819 } 3820 3821 public boolean canLightningStrikeAt(int par1, int par2, int par3) 3822 { 3823 if (!this.isRaining()) 3824 { 3825 return false; 3826 } 3827 else if (!this.canBlockSeeTheSky(par1, par2, par3)) 3828 { 3829 return false; 3830 } 3831 else if (this.getPrecipitationHeight(par1, par3) > par2) 3832 { 3833 return false; 3834 } 3835 else 3836 { 3837 BiomeGenBase var4 = this.getBiomeGenForCoords(par1, par3); 3838 return var4.getEnableSnow() ? false : var4.canSpawnLightningBolt(); 3839 } 3840 } 3841 3842 /** 3843 * Checks to see if the biome rainfall values for a given x,y,z coordinate set are extremely high 3844 */ 3845 public boolean isBlockHighHumidity(int par1, int par2, int par3) 3846 { 3847 BiomeGenBase var4 = this.getBiomeGenForCoords(par1, par3); 3848 return var4.isHighHumidity(); 3849 } 3850 3851 /** 3852 * Assigns the given String id to the given MapDataBase using the MapStorage, removing any existing ones of the same 3853 * id. 3854 */ 3855 public void setItemData(String par1Str, WorldSavedData par2WorldSavedData) 3856 { 3857 this.mapStorage.setData(par1Str, par2WorldSavedData); 3858 } 3859 3860 /** 3861 * Loads an existing MapDataBase corresponding to the given String id from disk using the MapStorage, instantiating 3862 * the given Class, or returns null if none such file exists. args: Class to instantiate, String dataid 3863 */ 3864 public WorldSavedData loadItemData(Class par1Class, String par2Str) 3865 { 3866 return this.mapStorage.loadData(par1Class, par2Str); 3867 } 3868 3869 /** 3870 * Returns an unique new data id from the MapStorage for the given prefix and saves the idCounts map to the 3871 * 'idcounts' file. 3872 */ 3873 public int getUniqueDataId(String par1Str) 3874 { 3875 return this.mapStorage.getUniqueDataId(par1Str); 3876 } 3877 3878 /** 3879 * See description for playAuxSFX. 3880 */ 3881 public void playAuxSFX(int par1, int par2, int par3, int par4, int par5) 3882 { 3883 this.playAuxSFXAtEntity((EntityPlayer)null, par1, par2, par3, par4, par5); 3884 } 3885 3886 /** 3887 * See description for playAuxSFX. 3888 */ 3889 public void playAuxSFXAtEntity(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5, int par6) 3890 { 3891 for (int var7 = 0; var7 < this.worldAccesses.size(); ++var7) 3892 { 3893 ((IWorldAccess)this.worldAccesses.get(var7)).playAuxSFX(par1EntityPlayer, par2, par3, par4, par5, par6); 3894 } 3895 } 3896 3897 /** 3898 * Returns current world height. 3899 */ 3900 public int getHeight() 3901 { 3902 return 256; 3903 } 3904 3905 /** 3906 * Returns current world height. 3907 */ 3908 public int getActualHeight() 3909 { 3910 return this.provider.hasNoSky ? 128 : 256; 3911 } 3912 3913 /** 3914 * puts the World Random seed to a specific state dependant on the inputs 3915 */ 3916 public Random setRandomSeed(int par1, int par2, int par3) 3917 { 3918 long var4 = (long)par1 * 341873128712L + (long)par2 * 132897987541L + this.getWorldInfo().getSeed() + (long)par3; 3919 this.rand.setSeed(var4); 3920 return this.rand; 3921 } 3922 3923 /** 3924 * Updates lighting. Returns true if there are more lighting updates to update 3925 */ 3926 public boolean updatingLighting() 3927 { 3928 return false; 3929 } 3930 3931 /** 3932 * Returns the location of the closest structure of the specified type. If not found returns null. 3933 */ 3934 public ChunkPosition findClosestStructure(String par1Str, int par2, int par3, int par4) 3935 { 3936 return this.getChunkProvider().findClosestStructure(this, par1Str, par2, par3, par4); 3937 } 3938 3939 @SideOnly(Side.CLIENT) 3940 3941 /** 3942 * set by !chunk.getAreLevelsEmpty 3943 */ 3944 public boolean extendedLevelsInChunkCache() 3945 { 3946 return false; 3947 } 3948 3949 @SideOnly(Side.CLIENT) 3950 3951 /** 3952 * Returns horizon height for use in rendering the sky. 3953 */ 3954 public double getHorizon() 3955 { 3956 return this.worldInfo.getTerrainType().getHorizon(this); 3957 } 3958 3959 /** 3960 * Adds some basic stats of the world to the given crash report. 3961 */ 3962 public CrashReport addWorldInfoToCrashReport(CrashReport par1CrashReport) 3963 { 3964 par1CrashReport.addCrashSectionCallable("World " + this.worldInfo.getWorldName() + " Entities", new CallableLvl1(this)); 3965 par1CrashReport.addCrashSectionCallable("World " + this.worldInfo.getWorldName() + " Players", new CallableLvl2(this)); 3966 par1CrashReport.addCrashSectionCallable("World " + this.worldInfo.getWorldName() + " Chunk Stats", new CallableLvl3(this)); 3967 return par1CrashReport; 3968 } 3969 3970 /** 3971 * Starts (or continues) destroying a block with given ID at the given coordinates for the given partially destroyed 3972 * value 3973 */ 3974 public void destroyBlockInWorldPartially(int par1, int par2, int par3, int par4, int par5) 3975 { 3976 Iterator var6 = this.worldAccesses.iterator(); 3977 3978 while (var6.hasNext()) 3979 { 3980 IWorldAccess var7 = (IWorldAccess)var6.next(); 3981 var7.destroyBlockPartially(par1, par2, par3, par4, par5); 3982 } 3983 } 3984 3985 /** 3986 * Adds a single TileEntity to the world. 3987 * @param entity The TileEntity to be added. 3988 */ 3989 public void addTileEntity(TileEntity entity) 3990 { 3991 List dest = scanningTileEntities ? addedTileEntityList : loadedTileEntityList; 3992 if(entity.canUpdate()) 3993 { 3994 dest.add(entity); 3995 } 3996 } 3997 3998 /** 3999 * Determine if the given block is considered solid on the 4000 * specified side. Used by placement logic. 4001 * 4002 * @param X Block X Position 4003 * @param Y Block Y Position 4004 * @param Z Block Z Position 4005 * @param side The Side in question 4006 * @return True if the side is solid 4007 */ 4008 public boolean isBlockSolidOnSide(int X, int Y, int Z, ForgeDirection side) 4009 { 4010 return isBlockSolidOnSide(X, Y, Z, side, false); 4011 } 4012 4013 /** 4014 * Determine if the given block is considered solid on the 4015 * specified side. Used by placement logic. 4016 * 4017 * @param X Block X Position 4018 * @param Y Block Y Position 4019 * @param Z Block Z Position 4020 * @param side The Side in question 4021 * @param _default The defult to return if the block doesn't exist. 4022 * @return True if the side is solid 4023 */ 4024 public boolean isBlockSolidOnSide(int X, int Y, int Z, ForgeDirection side, boolean _default) 4025 { 4026 if (X < -30000000 || Z < -30000000 || X >= 30000000 || Z >= 30000000) 4027 { 4028 return _default; 4029 } 4030 4031 Chunk var5 = this.chunkProvider.provideChunk(X >> 4, Z >> 4); 4032 if (var5 == null || var5.isEmpty()) 4033 { 4034 return _default; 4035 } 4036 4037 Block block = Block.blocksList[getBlockId(X, Y, Z)]; 4038 if(block == null) 4039 { 4040 return false; 4041 } 4042 4043 return block.isBlockSolidOnSide(this, X, Y, Z, side); 4044 } 4045 }