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