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