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