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