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