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