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