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