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