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