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