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