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