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