    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    }