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