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