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