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