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