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