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