Advertisement
trhod17

Untitled

Jan 18th, 2019
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 148.50 KB | None | 0 0
  1. package net.minecraft.world;
  2.  
  3. import com.google.common.base.Function;
  4. import com.google.common.base.MoreObjects;
  5. import com.google.common.base.Predicate;
  6. import com.google.common.collect.Lists;
  7. import java.util.Calendar;
  8. import java.util.Collection;
  9. import java.util.Iterator;
  10. import java.util.List;
  11. import java.util.Random;
  12. import java.util.UUID;
  13. import java.util.function.Supplier;
  14.  
  15. import javax.annotation.Nullable;
  16. import net.minecraft.advancements.AdvancementManager;
  17. import net.minecraft.advancements.FunctionManager;
  18. import net.minecraft.block.Block;
  19. import net.minecraft.block.BlockLiquid;
  20. import net.minecraft.block.BlockObserver;
  21. import net.minecraft.block.material.Material;
  22. import net.minecraft.block.state.IBlockState;
  23. import net.minecraft.crash.CrashReport;
  24. import net.minecraft.crash.CrashReportCategory;
  25. import net.minecraft.crash.ICrashReportDetail;
  26. import net.minecraft.entity.Entity;
  27. import net.minecraft.entity.EntityLiving;
  28. import net.minecraft.entity.player.EntityPlayer;
  29. import net.minecraft.entity.player.EntityPlayerMP;
  30. import net.minecraft.init.Biomes;
  31. import net.minecraft.init.Blocks;
  32. import net.minecraft.nbt.NBTTagCompound;
  33. import net.minecraft.network.Packet;
  34. import net.minecraft.pathfinding.PathWorldListener;
  35. import net.minecraft.profiler.Profiler;
  36. import net.minecraft.scoreboard.Scoreboard;
  37. import net.minecraft.server.MinecraftServer;
  38. import net.minecraft.tileentity.TileEntity;
  39. import net.minecraft.util.EntitySelectors;
  40. import net.minecraft.util.EnumFacing;
  41. import net.minecraft.util.EnumParticleTypes;
  42. import net.minecraft.util.ITickable;
  43. import net.minecraft.util.IntHashMap;
  44. import net.minecraft.util.ReportedException;
  45. import net.minecraft.util.SoundCategory;
  46. import net.minecraft.util.SoundEvent;
  47. import net.minecraft.util.math.AxisAlignedBB;
  48. import net.minecraft.util.math.BlockPos;
  49. import net.minecraft.util.math.MathHelper;
  50. import net.minecraft.util.math.RayTraceResult;
  51. import net.minecraft.util.math.Vec3d;
  52. import net.minecraft.village.VillageCollection;
  53. import net.minecraft.world.biome.Biome;
  54. import net.minecraft.world.biome.BiomeProvider;
  55. import net.minecraft.world.border.WorldBorder;
  56. import net.minecraft.world.chunk.Chunk;
  57. import net.minecraft.world.chunk.IChunkProvider;
  58. import net.minecraft.world.gen.structure.StructureBoundingBox;
  59. import net.minecraft.world.storage.ISaveHandler;
  60. import net.minecraft.world.storage.MapStorage;
  61. import net.minecraft.world.storage.WorldInfo;
  62. import net.minecraft.world.storage.WorldSavedData;
  63. import net.minecraft.world.storage.loot.LootTableManager;
  64. import net.minecraftforge.fml.relauncher.Side;
  65. import net.minecraftforge.fml.relauncher.SideOnly;
  66.  
  67. public abstract class World implements IBlockAccess, net.minecraftforge.common.capabilities.ICapabilityProvider
  68. {
  69.     /**
  70.      * Used in the getEntitiesWithinAABB functions to expand the search area for entities.
  71.      * Modders should change this variable to a higher value if it is less then the radius
  72.      * of one of there entities.
  73.      */
  74.     public static double MAX_ENTITY_RADIUS = 2.0D;
  75.  
  76.     private int seaLevel = 63;
  77.     /** boolean; if true updates scheduled by scheduleBlockUpdate happen immediately */
  78.     protected boolean scheduledUpdatesAreImmediate;
  79.     /** A list of all Entities in all currently-loaded chunks */
  80.     public final List<Entity> loadedEntityList = Lists.<Entity>newArrayList();
  81.     protected final List<Entity> unloadedEntityList = Lists.<Entity>newArrayList();
  82.     /** A list of the loaded tile entities in the world */
  83.     public final List<TileEntity> loadedTileEntityList = Lists.<TileEntity>newArrayList();
  84.     public final List<TileEntity> tickableTileEntities = Lists.<TileEntity>newArrayList();
  85.     private final List<TileEntity> addedTileEntityList = Lists.<TileEntity>newArrayList();
  86.     private final List<TileEntity> tileEntitiesToBeRemoved = Lists.<TileEntity>newArrayList();
  87.     /** Array list of players in the world. */
  88.     public final List<EntityPlayer> playerEntities = Lists.<EntityPlayer>newArrayList();
  89.     /** a list of all the lightning entities */
  90.     public final List<Entity> weatherEffects = Lists.<Entity>newArrayList();
  91.     protected final IntHashMap<Entity> entitiesById = new IntHashMap<Entity>();
  92.     private final long cloudColour = 16777215L;
  93.     /** How much light is subtracted from full daylight */
  94.     private int skylightSubtracted;
  95.     /**
  96.      * Contains the current Linear Congruential Generator seed for block updates. Used with an A value of 3 and a C
  97.      * value of 0x3c6ef35f, producing a highly planar series of values ill-suited for choosing random blocks in a
  98.      * 16x128x16 field.
  99.      */
  100.     protected int updateLCG = (new Random()).nextInt();
  101.     /** magic number used to generate fast random numbers for 3d distribution within a chunk */
  102.     protected final int DIST_HASH_MAGIC = 1013904223;
  103.     public float prevRainingStrength;
  104.     public float rainingStrength;
  105.     public float prevThunderingStrength;
  106.     public float thunderingStrength;
  107.     /**
  108.      * Set to 2 whenever a lightning bolt is generated in SSP. Decrements if > 0 in updateWeather(). Value appears to be
  109.      * unused.
  110.      */
  111.     private int lastLightningBolt;
  112.     /** RNG for World. */
  113.     public final Random rand = new Random();
  114.     /** The WorldProvider instance that World uses. */
  115.     public final WorldProvider provider;
  116.     protected PathWorldListener pathListener = new PathWorldListener();
  117.     protected List<IWorldEventListener> eventListeners;
  118.     /** Handles chunk operations and caching */
  119.     protected IChunkProvider chunkProvider;
  120.     protected final ISaveHandler saveHandler;
  121.     /** holds information about a world (size on disk, time, spawn point, seed, ...) */
  122.     protected WorldInfo worldInfo;
  123.     /**
  124.      * if set, this flag forces a request to load a chunk to load the chunk rather than defaulting to the world's
  125.      * chunkprovider's dummy if possible
  126.      */
  127.     protected boolean findingSpawnPoint;
  128.     protected MapStorage mapStorage;
  129.     public VillageCollection villageCollection;
  130.     protected LootTableManager lootTable;
  131.     protected AdvancementManager advancementManager;
  132.     protected FunctionManager functionManager;
  133.     public final Profiler profiler;
  134.     private final Calendar calendar;
  135.     protected Scoreboard worldScoreboard;
  136.     /**
  137.      * True if the world is a 'slave' client; changes will not be saved or propagated from this world. For example,
  138.      * server worlds have this set to false, client worlds have this set to true.
  139.      */
  140.     public final boolean isRemote;
  141.     /** indicates if enemies are spawned or not */
  142.     protected boolean spawnHostileMobs;
  143.     /** A flag indicating whether we should spawn peaceful mobs. */
  144.     protected boolean spawnPeacefulMobs;
  145.     private boolean processingLoadedTiles;
  146.     private final WorldBorder worldBorder;
  147.     /**
  148.      * is a temporary list of blocks and light values used when updating light levels. Holds up to 32x32x32 blocks (the
  149.      * maximum influence of a light source.) Every element is a packed bit value: 0000000000LLLLzzzzzzyyyyyyxxxxxx. The
  150.      * 4-bit L is a light level used when darkening blocks. 6-bit numbers x, y and z represent the block's offset from
  151.      * the original block, plus 32 (i.e. value of 31 would mean a -1 offset
  152.      */
  153.     int[] lightUpdateBlockList;
  154.  
  155.     public boolean restoringBlockSnapshots = false;
  156.     public boolean captureBlockSnapshots = false;
  157.     public java.util.ArrayList<net.minecraftforge.common.util.BlockSnapshot> capturedBlockSnapshots = new java.util.ArrayList<net.minecraftforge.common.util.BlockSnapshot>();
  158.     private net.minecraftforge.common.capabilities.CapabilityDispatcher capabilities;
  159.     private net.minecraftforge.common.util.WorldCapabilityData capabilityData;
  160.  
  161.     protected World(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client)
  162.     {
  163.         this.eventListeners = Lists.newArrayList(this.pathListener);
  164.         this.calendar = Calendar.getInstance();
  165.         this.worldScoreboard = new Scoreboard();
  166.         this.spawnHostileMobs = true;
  167.         this.spawnPeacefulMobs = true;
  168.         this.lightUpdateBlockList = new int[32768];
  169.         this.saveHandler = saveHandlerIn;
  170.         this.profiler = profilerIn;
  171.         this.worldInfo = info;
  172.         this.provider = providerIn;
  173.         this.isRemote = client;
  174.         this.worldBorder = providerIn.createWorldBorder();
  175.         perWorldStorage = new MapStorage((ISaveHandler)null);
  176.     }
  177.  
  178.     public World init()
  179.     {
  180.         return this;
  181.     }
  182.  
  183.     public Biome getBiome(final BlockPos pos)
  184.     {
  185.         return this.provider.getBiomeForCoords(pos);
  186.     }
  187.  
  188.     public Biome getBiomeForCoordsBody(final BlockPos pos)
  189.     {
  190.         if (this.isBlockLoaded(pos))
  191.         {
  192.             Chunk chunk = this.getChunkFromBlockCoords(pos);
  193.  
  194.             try
  195.             {
  196.                 return chunk.getBiome(pos, this.provider.getBiomeProvider());
  197.             }
  198.             catch (Throwable throwable)
  199.             {
  200.                 CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Getting biome");
  201.                 CrashReportCategory crashreportcategory = crashreport.makeCategory("Coordinates of biome request");
  202.                 crashreportcategory.addDetail("Location", new ICrashReportDetail<String>()
  203.                 {
  204.                     public String call() throws Exception
  205.                     {
  206.                         return CrashReportCategory.getCoordinateInfo(pos);
  207.                     }
  208.                 });
  209.                 throw new ReportedException(crashreport);
  210.             }
  211.         }
  212.         else
  213.         {
  214.             return this.provider.getBiomeProvider().getBiome(pos, Biomes.PLAINS);
  215.         }
  216.     }
  217.  
  218.     public BiomeProvider getBiomeProvider()
  219.     {
  220.         return this.provider.getBiomeProvider();
  221.     }
  222.  
  223.     /**
  224.      * Creates the chunk provider for this world. Called in the constructor. Retrieves provider from worldProvider?
  225.      */
  226.     protected abstract IChunkProvider createChunkProvider();
  227.  
  228.     public void initialize(WorldSettings settings)
  229.     {
  230.         this.worldInfo.setServerInitialized(true);
  231.     }
  232.  
  233.     @Nullable
  234.     public MinecraftServer getMinecraftServer()
  235.     {
  236.         return null;
  237.     }
  238.  
  239.     /**
  240.      * Sets a new spawn location by finding an uncovered block at a random (x,z) location in the chunk.
  241.      */
  242.     @SideOnly(Side.CLIENT)
  243.     public void setInitialSpawnLocation()
  244.     {
  245.         this.setSpawnPoint(new BlockPos(8, 64, 8));
  246.     }
  247.  
  248.     public IBlockState getGroundAboveSeaLevel(BlockPos pos)
  249.     {
  250.         BlockPos blockpos;
  251.  
  252.         for (blockpos = new BlockPos(pos.getX(), this.getSeaLevel(), pos.getZ()); !this.isAirBlock(blockpos.up()); blockpos = blockpos.up())
  253.         {
  254.             ;
  255.         }
  256.  
  257.         return this.getBlockState(blockpos);
  258.     }
  259.  
  260.     /**
  261.      * Check if the given BlockPos has valid coordinates
  262.      */
  263.     public boolean isValid(BlockPos pos)
  264.     {
  265.         return !this.isOutsideBuildHeight(pos) && pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000;
  266.     }
  267.  
  268.     public boolean isOutsideBuildHeight(BlockPos pos)
  269.     {
  270.         return pos.getY() < 0 || pos.getY() >= 256;
  271.     }
  272.  
  273.     /**
  274.      * Checks to see if an air block exists at the provided location. Note that this only checks to see if the blocks
  275.      * material is set to air, meaning it is possible for non-vanilla blocks to still pass this check.
  276.      */
  277.     public boolean isAirBlock(BlockPos pos)
  278.     {
  279.         return this.getBlockState(pos).getBlock().isAir(this.getBlockState(pos), this, pos);
  280.     }
  281.  
  282.     public boolean isBlockLoaded(BlockPos pos)
  283.     {
  284.         return this.isBlockLoaded(pos, true);
  285.     }
  286.  
  287.     public boolean isBlockLoaded(BlockPos pos, boolean allowEmpty)
  288.     {
  289.         return this.isChunkLoaded(pos.getX() >> 4, pos.getZ() >> 4, allowEmpty);
  290.     }
  291.  
  292.     public boolean isAreaLoaded(BlockPos center, int radius)
  293.     {
  294.         return this.isAreaLoaded(center, radius, true);
  295.     }
  296.  
  297.     public boolean isAreaLoaded(BlockPos center, int radius, boolean allowEmpty)
  298.     {
  299.         return this.isAreaLoaded(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius, allowEmpty);
  300.     }
  301.  
  302.     public boolean isAreaLoaded(BlockPos from, BlockPos to)
  303.     {
  304.         return this.isAreaLoaded(from, to, true);
  305.     }
  306.  
  307.     public boolean isAreaLoaded(BlockPos from, BlockPos to, boolean allowEmpty)
  308.     {
  309.         return this.isAreaLoaded(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ(), allowEmpty);
  310.     }
  311.  
  312.     public boolean isAreaLoaded(StructureBoundingBox box)
  313.     {
  314.         return this.isAreaLoaded(box, true);
  315.     }
  316.  
  317.     public boolean isAreaLoaded(StructureBoundingBox box, boolean allowEmpty)
  318.     {
  319.         return this.isAreaLoaded(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, allowEmpty);
  320.     }
  321.  
  322.     private boolean isAreaLoaded(int xStart, int yStart, int zStart, int xEnd, int yEnd, int zEnd, boolean allowEmpty)
  323.     {
  324.         if (yEnd >= 0 && yStart < 256)
  325.         {
  326.             xStart = xStart >> 4;
  327.             zStart = zStart >> 4;
  328.             xEnd = xEnd >> 4;
  329.             zEnd = zEnd >> 4;
  330.  
  331.             for (int i = xStart; i <= xEnd; ++i)
  332.             {
  333.                 for (int j = zStart; j <= zEnd; ++j)
  334.                 {
  335.                     if (!this.isChunkLoaded(i, j, allowEmpty))
  336.                     {
  337.                         return false;
  338.                     }
  339.                 }
  340.             }
  341.  
  342.             return true;
  343.         }
  344.         else
  345.         {
  346.             return false;
  347.         }
  348.     }
  349.  
  350.     protected abstract boolean isChunkLoaded(int x, int z, boolean allowEmpty);
  351.  
  352.     public Chunk getChunkFromBlockCoords(BlockPos pos)
  353.     {
  354.         return this.getChunkFromChunkCoords(pos.getX() >> 4, pos.getZ() >> 4);
  355.     }
  356.  
  357.     /**
  358.      * Gets the chunk at the specified location.
  359.      */
  360.     public Chunk getChunkFromChunkCoords(int chunkX, int chunkZ)
  361.     {
  362.         return this.chunkProvider.provideChunk(chunkX, chunkZ);
  363.     }
  364.  
  365.     public boolean isChunkGeneratedAt(int x, int z)
  366.     {
  367.         return this.isChunkLoaded(x, z, false) ? true : this.chunkProvider.isChunkGeneratedAt(x, z);
  368.     }
  369.  
  370.     /**
  371.      * Flag 1 will cause a block update. Flag 2 will send the change to clients. Flag 4 will prevent the block from
  372.      * being re-rendered, if this is a client world. Flag 8 will force any re-renders to run on the main thread instead
  373.      * of the worker pool, if this is a client world and flag 4 is clear. Flag 16 will prevent observers from seeing
  374.      * this change. Flags can be OR-ed
  375.      */
  376.     public boolean setBlockState(BlockPos pos, IBlockState newState, int flags)
  377.     {
  378.         if (this.isOutsideBuildHeight(pos))
  379.         {
  380.             return false;
  381.         }
  382.         else if (!this.isRemote && this.worldInfo.getTerrainType() == WorldType.DEBUG_ALL_BLOCK_STATES)
  383.         {
  384.             return false;
  385.         }
  386.         else
  387.         {
  388.             Chunk chunk = this.getChunkFromBlockCoords(pos);
  389.  
  390.             pos = pos.toImmutable(); // Forge - prevent mutable BlockPos leaks
  391.             net.minecraftforge.common.util.BlockSnapshot blockSnapshot = null;
  392.             if (this.captureBlockSnapshots && !this.isRemote)
  393.             {
  394.                 blockSnapshot = net.minecraftforge.common.util.BlockSnapshot.getBlockSnapshot(this, pos, flags);
  395.                 this.capturedBlockSnapshots.add(blockSnapshot);
  396.             }
  397.             IBlockState oldState = getBlockState(pos);
  398.             int oldLight = oldState.getLightValue(this, pos);
  399.             int oldOpacity = oldState.getLightOpacity(this, pos);
  400.  
  401.             IBlockState iblockstate = chunk.setBlockState(pos, newState);
  402.  
  403.             if (iblockstate == null)
  404.             {
  405.                 if (blockSnapshot != null) this.capturedBlockSnapshots.remove(blockSnapshot);
  406.                 return false;
  407.             }
  408.             else
  409.             {
  410.                 if (newState.getLightOpacity(this, pos) != oldOpacity || newState.getLightValue(this, pos) != oldLight)
  411.                 {
  412.                     this.profiler.startSection("checkLight");
  413.                     this.checkLight(pos);
  414.                     this.profiler.endSection();
  415.                 }
  416.  
  417.                 if (blockSnapshot == null) // Don't notify clients or update physics while capturing blockstates
  418.                 {
  419.                     this.markAndNotifyBlock(pos, chunk, iblockstate, newState, flags);
  420.                 }
  421.                 return true;
  422.             }
  423.         }
  424.     }
  425.  
  426.     // Split off from original setBlockState(BlockPos, IBlockState, int) method in order to directly send client and physic updates
  427.     public void markAndNotifyBlock(BlockPos pos, @Nullable Chunk chunk, IBlockState iblockstate, IBlockState newState, int flags)
  428.     {
  429.         Block block = newState.getBlock();
  430.         {
  431.             {
  432.                 if ((flags & 2) != 0 && (!this.isRemote || (flags & 4) == 0) && (chunk == null || chunk.isPopulated()))
  433.                 {
  434.                     this.notifyBlockUpdate(pos, iblockstate, newState, flags);
  435.                 }
  436.  
  437.                 if (!this.isRemote && (flags & 1) != 0)
  438.                 {
  439.                     this.notifyNeighborsRespectDebug(pos, iblockstate.getBlock(), true);
  440.  
  441.                     if (newState.hasComparatorInputOverride())
  442.                     {
  443.                         this.updateComparatorOutputLevel(pos, block);
  444.                     }
  445.                 }
  446.                 else if (!this.isRemote && (flags & 16) == 0)
  447.                 {
  448.                     this.updateObservingBlocksAt(pos, block);
  449.                 }
  450.             }
  451.         }
  452.     }
  453.  
  454.     public boolean setBlockToAir(BlockPos pos)
  455.     {
  456.         return this.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
  457.     }
  458.  
  459.     /**
  460.      * Sets a block to air, but also plays the sound and particles and can spawn drops
  461.      */
  462.     public boolean destroyBlock(BlockPos pos, boolean dropBlock)
  463.     {
  464.         IBlockState iblockstate = this.getBlockState(pos);
  465.         Block block = iblockstate.getBlock();
  466.  
  467.         if (block.isAir(iblockstate, this, pos))
  468.         {
  469.             return false;
  470.         }
  471.         else
  472.         {
  473.             this.playEvent(2001, pos, Block.getStateId(iblockstate));
  474.  
  475.             if (dropBlock)
  476.             {
  477.                 block.dropBlockAsItem(this, pos, iblockstate, 0);
  478.             }
  479.  
  480.             return this.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
  481.         }
  482.     }
  483.  
  484.     /**
  485.      * Convenience method to update the block on both the client and server
  486.      */
  487.     public boolean setBlockState(BlockPos pos, IBlockState state)
  488.     {
  489.         return this.setBlockState(pos, state, 3);
  490.     }
  491.  
  492.     /**
  493.      * Flags are as in setBlockState
  494.      */
  495.     public void notifyBlockUpdate(BlockPos pos, IBlockState oldState, IBlockState newState, int flags)
  496.     {
  497.         for (int i = 0; i < this.eventListeners.size(); ++i)
  498.         {
  499.             ((IWorldEventListener)this.eventListeners.get(i)).notifyBlockUpdate(this, pos, oldState, newState, flags);
  500.         }
  501.     }
  502.  
  503.     public void notifyNeighborsRespectDebug(BlockPos pos, Block blockType, boolean p_175722_3_)
  504.     {
  505.         if (this.worldInfo.getTerrainType() != WorldType.DEBUG_ALL_BLOCK_STATES)
  506.         {
  507.             this.notifyNeighborsOfStateChange(pos, blockType, p_175722_3_);
  508.         }
  509.     }
  510.  
  511.     /**
  512.      * Marks a vertical column of blocks dirty, scheduling a render update.
  513.      *  
  514.      * Automatically swaps y1 and y2 if they are backwards.
  515.      */
  516.     public void markBlocksDirtyVertical(int x, int z, int y1, int y2)
  517.     {
  518.         if (y1 > y2)
  519.         {
  520.             int i = y2;
  521.             y2 = y1;
  522.             y1 = i;
  523.         }
  524.  
  525.         if (this.provider.hasSkyLight())
  526.         {
  527.             for (int j = y1; j <= y2; ++j)
  528.             {
  529.                 this.checkLightFor(EnumSkyBlock.SKY, new BlockPos(x, j, z));
  530.             }
  531.         }
  532.  
  533.         this.markBlockRangeForRenderUpdate(x, y1, z, x, y2, z);
  534.     }
  535.  
  536.     public void markBlockRangeForRenderUpdate(BlockPos rangeMin, BlockPos rangeMax)
  537.     {
  538.         this.markBlockRangeForRenderUpdate(rangeMin.getX(), rangeMin.getY(), rangeMin.getZ(), rangeMax.getX(), rangeMax.getY(), rangeMax.getZ());
  539.     }
  540.  
  541.     /**
  542.      * Notifies all listening IWorldEventListeners of an update within the given bounds.
  543.      */
  544.     public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2)
  545.     {
  546.         for (int i = 0; i < this.eventListeners.size(); ++i)
  547.         {
  548.             ((IWorldEventListener)this.eventListeners.get(i)).markBlockRangeForRenderUpdate(x1, y1, z1, x2, y2, z2);
  549.         }
  550.     }
  551.  
  552.     public void updateObservingBlocksAt(BlockPos pos, Block blockType)
  553.     {
  554.         this.observedNeighborChanged(pos.west(), blockType, pos);
  555.         this.observedNeighborChanged(pos.east(), blockType, pos);
  556.         this.observedNeighborChanged(pos.down(), blockType, pos);
  557.         this.observedNeighborChanged(pos.up(), blockType, pos);
  558.         this.observedNeighborChanged(pos.north(), blockType, pos);
  559.         this.observedNeighborChanged(pos.south(), blockType, pos);
  560.     }
  561.  
  562.     public void notifyNeighborsOfStateChange(BlockPos pos, Block blockType, boolean updateObservers)
  563.     {
  564.         if(net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(this, pos, this.getBlockState(pos), java.util.EnumSet.allOf(EnumFacing.class), updateObservers).isCanceled())
  565.             return;
  566.  
  567.         this.neighborChanged(pos.west(), blockType, pos);
  568.         this.neighborChanged(pos.east(), blockType, pos);
  569.         this.neighborChanged(pos.down(), blockType, pos);
  570.         this.neighborChanged(pos.up(), blockType, pos);
  571.         this.neighborChanged(pos.north(), blockType, pos);
  572.         this.neighborChanged(pos.south(), blockType, pos);
  573.  
  574.         if (updateObservers)
  575.         {
  576.             this.updateObservingBlocksAt(pos, blockType);
  577.         }
  578.     }
  579.  
  580.     public void notifyNeighborsOfStateExcept(BlockPos pos, Block blockType, EnumFacing skipSide)
  581.     {
  582.         java.util.EnumSet<EnumFacing> directions = java.util.EnumSet.allOf(EnumFacing.class);
  583.         directions.remove(skipSide);
  584.         if(net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(this, pos, this.getBlockState(pos), directions, false).isCanceled())
  585.             return;
  586.  
  587.         if (skipSide != EnumFacing.WEST)
  588.         {
  589.             this.neighborChanged(pos.west(), blockType, pos);
  590.         }
  591.  
  592.         if (skipSide != EnumFacing.EAST)
  593.         {
  594.             this.neighborChanged(pos.east(), blockType, pos);
  595.         }
  596.  
  597.         if (skipSide != EnumFacing.DOWN)
  598.         {
  599.             this.neighborChanged(pos.down(), blockType, pos);
  600.         }
  601.  
  602.         if (skipSide != EnumFacing.UP)
  603.         {
  604.             this.neighborChanged(pos.up(), blockType, pos);
  605.         }
  606.  
  607.         if (skipSide != EnumFacing.NORTH)
  608.         {
  609.             this.neighborChanged(pos.north(), blockType, pos);
  610.         }
  611.  
  612.         if (skipSide != EnumFacing.SOUTH)
  613.         {
  614.             this.neighborChanged(pos.south(), blockType, pos);
  615.         }
  616.     }
  617.  
  618.     public void neighborChanged(BlockPos pos, final Block blockIn, BlockPos fromPos)
  619.     {
  620.         if (!this.isRemote)
  621.         {
  622.             IBlockState iblockstate = this.getBlockState(pos);
  623.  
  624.             try
  625.             {
  626.                 iblockstate.neighborChanged(this, pos, blockIn, fromPos);
  627.             }
  628.             catch (Throwable throwable)
  629.             {
  630.                 CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception while updating neighbours");
  631.                 CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being updated");
  632.                 crashreportcategory.addDetail("Source block type", new ICrashReportDetail<String>()
  633.                 {
  634.                     public String call() throws Exception
  635.                     {
  636.                         try
  637.                         {
  638.                             return String.format("ID #%d (%s // %s // %s)", Block.getIdFromBlock(blockIn), blockIn.getUnlocalizedName(), blockIn.getClass().getName(), blockIn.getRegistryName());
  639.                         }
  640.                         catch (Throwable var2)
  641.                         {
  642.                             return "ID #" + Block.getIdFromBlock(blockIn);
  643.                         }
  644.                     }
  645.                 });
  646.                 CrashReportCategory.addBlockInfo(crashreportcategory, pos, iblockstate);
  647.                 throw new ReportedException(crashreport);
  648.             }
  649.         }
  650.     }
  651.  
  652.     public void observedNeighborChanged(BlockPos pos, final Block p_190529_2_, BlockPos p_190529_3_)
  653.     {
  654.         if (!this.isRemote)
  655.         {
  656.             IBlockState iblockstate = this.getBlockState(pos);
  657.  
  658.             if (true)
  659.             {
  660.                 try
  661.                 {
  662.                     iblockstate.getBlock().observedNeighborChange(iblockstate, this, pos, p_190529_2_, p_190529_3_);
  663.                 }
  664.                 catch (Throwable throwable)
  665.                 {
  666.                     CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception while updating neighbours");
  667.                     CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being updated");
  668.                     crashreportcategory.addDetail("Source block type", new ICrashReportDetail<String>()
  669.                     {
  670.                         public String call() throws Exception
  671.                         {
  672.                             try
  673.                             {
  674.                                 return String.format("ID #%d (%s // %s // %s)", Block.getIdFromBlock(p_190529_2_), p_190529_2_.getUnlocalizedName(), p_190529_2_.getClass().getName(), p_190529_2_.getRegistryName());
  675.                             }
  676.                             catch (Throwable var2)
  677.                             {
  678.                                 return "ID #" + Block.getIdFromBlock(p_190529_2_);
  679.                             }
  680.                         }
  681.                     });
  682.                     CrashReportCategory.addBlockInfo(crashreportcategory, pos, iblockstate);
  683.                     throw new ReportedException(crashreport);
  684.                 }
  685.             }
  686.         }
  687.     }
  688.  
  689.     public boolean isBlockTickPending(BlockPos pos, Block blockType)
  690.     {
  691.         return false;
  692.     }
  693.  
  694.     public boolean canSeeSky(BlockPos pos)
  695.     {
  696.         return this.getChunkFromBlockCoords(pos).canSeeSky(pos);
  697.     }
  698.  
  699.     public boolean canBlockSeeSky(BlockPos pos)
  700.     {
  701.         if (pos.getY() >= this.getSeaLevel())
  702.         {
  703.             return this.canSeeSky(pos);
  704.         }
  705.         else
  706.         {
  707.             BlockPos blockpos = new BlockPos(pos.getX(), this.getSeaLevel(), pos.getZ());
  708.  
  709.             if (!this.canSeeSky(blockpos))
  710.             {
  711.                 return false;
  712.             }
  713.             else
  714.             {
  715.                 for (BlockPos blockpos1 = blockpos.down(); blockpos1.getY() > pos.getY(); blockpos1 = blockpos1.down())
  716.                 {
  717.                     IBlockState iblockstate = this.getBlockState(blockpos1);
  718.  
  719.                     if (iblockstate.getBlock().getLightOpacity(iblockstate, this, blockpos) > 0 && !iblockstate.getMaterial().isLiquid())
  720.                     {
  721.                         return false;
  722.                     }
  723.                 }
  724.  
  725.                 return true;
  726.             }
  727.         }
  728.     }
  729.  
  730.     public int getLight(BlockPos pos)
  731.     {
  732.         if (pos.getY() < 0)
  733.         {
  734.             return 0;
  735.         }
  736.         else
  737.         {
  738.             if (pos.getY() >= 256)
  739.             {
  740.                 pos = new BlockPos(pos.getX(), 255, pos.getZ());
  741.             }
  742.  
  743.             return this.getChunkFromBlockCoords(pos).getLightSubtracted(pos, 0);
  744.         }
  745.     }
  746.  
  747.     public int getLightFromNeighbors(BlockPos pos)
  748.     {
  749.         return this.getLight(pos, true);
  750.     }
  751.  
  752.     public int getLight(BlockPos pos, boolean checkNeighbors)
  753.     {
  754.         if (pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000)
  755.         {
  756.             if (checkNeighbors && this.getBlockState(pos).useNeighborBrightness())
  757.             {
  758.                 int i1 = this.getLight(pos.up(), false);
  759.                 int i = this.getLight(pos.east(), false);
  760.                 int j = this.getLight(pos.west(), false);
  761.                 int k = this.getLight(pos.south(), false);
  762.                 int l = this.getLight(pos.north(), false);
  763.  
  764.                 if (i > i1)
  765.                 {
  766.                     i1 = i;
  767.                 }
  768.  
  769.                 if (j > i1)
  770.                 {
  771.                     i1 = j;
  772.                 }
  773.  
  774.                 if (k > i1)
  775.                 {
  776.                     i1 = k;
  777.                 }
  778.  
  779.                 if (l > i1)
  780.                 {
  781.                     i1 = l;
  782.                 }
  783.  
  784.                 return i1;
  785.             }
  786.             else if (pos.getY() < 0)
  787.             {
  788.                 return 0;
  789.             }
  790.             else
  791.             {
  792.                 if (pos.getY() >= 256)
  793.                 {
  794.                     pos = new BlockPos(pos.getX(), 255, pos.getZ());
  795.                 }
  796.  
  797.                 Chunk chunk = this.getChunkFromBlockCoords(pos);
  798.                 return chunk.getLightSubtracted(pos, this.skylightSubtracted);
  799.             }
  800.         }
  801.         else
  802.         {
  803.             return 15;
  804.         }
  805.     }
  806.  
  807.     /**
  808.      * Returns the position at this x, z coordinate in the chunk with y set to the value from the height map.
  809.      */
  810.     public BlockPos getHeight(BlockPos pos)
  811.     {
  812.         return new BlockPos(pos.getX(), this.getHeight(pos.getX(), pos.getZ()), pos.getZ());
  813.     }
  814.  
  815.     /**
  816.      * Returns, from the height map, the height of the highest block at this x and z coordinate.
  817.      */
  818.     public int getHeight(int x, int z)
  819.     {
  820.         int i;
  821.  
  822.         if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000)
  823.         {
  824.             if (this.isChunkLoaded(x >> 4, z >> 4, true))
  825.             {
  826.                 i = this.getChunkFromChunkCoords(x >> 4, z >> 4).getHeightValue(x & 15, z & 15);
  827.             }
  828.             else
  829.             {
  830.                 i = 0;
  831.             }
  832.         }
  833.         else
  834.         {
  835.             i = this.getSeaLevel() + 1;
  836.         }
  837.  
  838.         return i;
  839.     }
  840.  
  841.     /**
  842.      * Gets the lowest height of the chunk where sunlight directly reaches
  843.      */
  844.     @Deprecated
  845.     public int getChunksLowestHorizon(int x, int z)
  846.     {
  847.         if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000)
  848.         {
  849.             if (!this.isChunkLoaded(x >> 4, z >> 4, true))
  850.             {
  851.                 return 0;
  852.             }
  853.             else
  854.             {
  855.                 Chunk chunk = this.getChunkFromChunkCoords(x >> 4, z >> 4);
  856.                 return chunk.getLowestHeight();
  857.             }
  858.         }
  859.         else
  860.         {
  861.             return this.getSeaLevel() + 1;
  862.         }
  863.     }
  864.  
  865.     @SideOnly(Side.CLIENT)
  866.     public int getLightFromNeighborsFor(EnumSkyBlock type, BlockPos pos)
  867.     {
  868.         if (!this.provider.hasSkyLight() && type == EnumSkyBlock.SKY)
  869.         {
  870.             return 0;
  871.         }
  872.         else
  873.         {
  874.             if (pos.getY() < 0)
  875.             {
  876.                 pos = new BlockPos(pos.getX(), 0, pos.getZ());
  877.             }
  878.  
  879.             if (!this.isValid(pos))
  880.             {
  881.                 return type.defaultLightValue;
  882.             }
  883.             else if (!this.isBlockLoaded(pos))
  884.             {
  885.                 return type.defaultLightValue;
  886.             }
  887.             else if (this.getBlockState(pos).useNeighborBrightness())
  888.             {
  889.                 int i1 = this.getLightFor(type, pos.up());
  890.                 int i = this.getLightFor(type, pos.east());
  891.                 int j = this.getLightFor(type, pos.west());
  892.                 int k = this.getLightFor(type, pos.south());
  893.                 int l = this.getLightFor(type, pos.north());
  894.  
  895.                 if (i > i1)
  896.                 {
  897.                     i1 = i;
  898.                 }
  899.  
  900.                 if (j > i1)
  901.                 {
  902.                     i1 = j;
  903.                 }
  904.  
  905.                 if (k > i1)
  906.                 {
  907.                     i1 = k;
  908.                 }
  909.  
  910.                 if (l > i1)
  911.                 {
  912.                     i1 = l;
  913.                 }
  914.  
  915.                 return i1;
  916.             }
  917.             else
  918.             {
  919.                 Chunk chunk = this.getChunkFromBlockCoords(pos);
  920.                 return chunk.getLightFor(type, pos);
  921.             }
  922.         }
  923.     }
  924.  
  925.     public int getLightFor(EnumSkyBlock type, BlockPos pos)
  926.     {
  927.         if (pos.getY() < 0)
  928.         {
  929.             pos = new BlockPos(pos.getX(), 0, pos.getZ());
  930.         }
  931.  
  932.         if (!this.isValid(pos))
  933.         {
  934.             return type.defaultLightValue;
  935.         }
  936.         else if (!this.isBlockLoaded(pos))
  937.         {
  938.             return type.defaultLightValue;
  939.         }
  940.         else
  941.         {
  942.             Chunk chunk = this.getChunkFromBlockCoords(pos);
  943.             return chunk.getLightFor(type, pos);
  944.         }
  945.     }
  946.  
  947.     public void setLightFor(EnumSkyBlock type, BlockPos pos, int lightValue)
  948.     {
  949.         if (this.isValid(pos))
  950.         {
  951.             if (this.isBlockLoaded(pos))
  952.             {
  953.                 Chunk chunk = this.getChunkFromBlockCoords(pos);
  954.                 chunk.setLightFor(type, pos, lightValue);
  955.                 this.notifyLightSet(pos);
  956.             }
  957.         }
  958.     }
  959.  
  960.     public void notifyLightSet(BlockPos pos)
  961.     {
  962.         for (int i = 0; i < this.eventListeners.size(); ++i)
  963.         {
  964.             ((IWorldEventListener)this.eventListeners.get(i)).notifyLightSet(pos);
  965.         }
  966.     }
  967.  
  968.     @SideOnly(Side.CLIENT)
  969.     public int getCombinedLight(BlockPos pos, int lightValue)
  970.     {
  971.         int i = this.getLightFromNeighborsFor(EnumSkyBlock.SKY, pos);
  972.         int j = this.getLightFromNeighborsFor(EnumSkyBlock.BLOCK, pos);
  973.  
  974.         if (j < lightValue)
  975.         {
  976.             j = lightValue;
  977.         }
  978.  
  979.         return i << 20 | j << 4;
  980.     }
  981.  
  982.     public float getLightBrightness(BlockPos pos)
  983.     {
  984.         return this.provider.getLightBrightnessTable()[this.getLightFromNeighbors(pos)];
  985.     }
  986.  
  987.     public IBlockState getBlockState(BlockPos pos)
  988.     {
  989.         if (this.isOutsideBuildHeight(pos))
  990.         {
  991.             return Blocks.AIR.getDefaultState();
  992.         }
  993.         else
  994.         {
  995.             Chunk chunk = this.getChunkFromBlockCoords(pos);
  996.             return chunk.getBlockState(pos);
  997.         }
  998.     }
  999.  
  1000.     /**
  1001.      * Checks whether its daytime by seeing if the light subtracted from the skylight is less than 4
  1002.      */
  1003.     public boolean isDaytime()
  1004.     {
  1005.         return this.provider.isDaytime();
  1006.     }
  1007.  
  1008.     /**
  1009.      * ray traces all blocks, including non-collideable ones
  1010.      */
  1011.     @Nullable
  1012.     public RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end)
  1013.     {
  1014.         return this.rayTraceBlocks(start, end, false, false, false);
  1015.     }
  1016.  
  1017.     @Nullable
  1018.     public RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end, boolean stopOnLiquid)
  1019.     {
  1020.         return this.rayTraceBlocks(start, end, stopOnLiquid, false, false);
  1021.     }
  1022.  
  1023.     /**
  1024.      * Performs a raycast against all blocks in the world. Args : Vec1, Vec2, stopOnLiquid,
  1025.      * ignoreBlockWithoutBoundingBox, returnLastUncollidableBlock
  1026.      */
  1027.     @Nullable
  1028.     public RayTraceResult rayTraceBlocks(Vec3d vec31, Vec3d vec32, boolean stopOnLiquid, boolean ignoreBlockWithoutBoundingBox, boolean returnLastUncollidableBlock)
  1029.     {
  1030.         if (!Double.isNaN(vec31.x) && !Double.isNaN(vec31.y) && !Double.isNaN(vec31.z))
  1031.         {
  1032.             if (!Double.isNaN(vec32.x) && !Double.isNaN(vec32.y) && !Double.isNaN(vec32.z))
  1033.             {
  1034.                 int i = MathHelper.floor(vec32.x);
  1035.                 int j = MathHelper.floor(vec32.y);
  1036.                 int k = MathHelper.floor(vec32.z);
  1037.                 int l = MathHelper.floor(vec31.x);
  1038.                 int i1 = MathHelper.floor(vec31.y);
  1039.                 int j1 = MathHelper.floor(vec31.z);
  1040.                 BlockPos blockpos = new BlockPos(l, i1, j1);
  1041.                 IBlockState iblockstate = this.getBlockState(blockpos);
  1042.                 Block block = iblockstate.getBlock();
  1043.  
  1044.                 if ((!ignoreBlockWithoutBoundingBox || iblockstate.getCollisionBoundingBox(this, blockpos) != Block.NULL_AABB) && block.canCollideCheck(iblockstate, stopOnLiquid))
  1045.                 {
  1046.                     RayTraceResult raytraceresult = iblockstate.collisionRayTrace(this, blockpos, vec31, vec32);
  1047.  
  1048.                     if (raytraceresult != null)
  1049.                     {
  1050.                         return raytraceresult;
  1051.                     }
  1052.                 }
  1053.  
  1054.                 RayTraceResult raytraceresult2 = null;
  1055.                 int k1 = 200;
  1056.  
  1057.                 while (k1-- >= 0)
  1058.                 {
  1059.                     if (Double.isNaN(vec31.x) || Double.isNaN(vec31.y) || Double.isNaN(vec31.z))
  1060.                     {
  1061.                         return null;
  1062.                     }
  1063.  
  1064.                     if (l == i && i1 == j && j1 == k)
  1065.                     {
  1066.                         return returnLastUncollidableBlock ? raytraceresult2 : null;
  1067.                     }
  1068.  
  1069.                     boolean flag2 = true;
  1070.                     boolean flag = true;
  1071.                     boolean flag1 = true;
  1072.                     double d0 = 999.0D;
  1073.                     double d1 = 999.0D;
  1074.                     double d2 = 999.0D;
  1075.  
  1076.                     if (i > l)
  1077.                     {
  1078.                         d0 = (double)l + 1.0D;
  1079.                     }
  1080.                     else if (i < l)
  1081.                     {
  1082.                         d0 = (double)l + 0.0D;
  1083.                     }
  1084.                     else
  1085.                     {
  1086.                         flag2 = false;
  1087.                     }
  1088.  
  1089.                     if (j > i1)
  1090.                     {
  1091.                         d1 = (double)i1 + 1.0D;
  1092.                     }
  1093.                     else if (j < i1)
  1094.                     {
  1095.                         d1 = (double)i1 + 0.0D;
  1096.                     }
  1097.                     else
  1098.                     {
  1099.                         flag = false;
  1100.                     }
  1101.  
  1102.                     if (k > j1)
  1103.                     {
  1104.                         d2 = (double)j1 + 1.0D;
  1105.                     }
  1106.                     else if (k < j1)
  1107.                     {
  1108.                         d2 = (double)j1 + 0.0D;
  1109.                     }
  1110.                     else
  1111.                     {
  1112.                         flag1 = false;
  1113.                     }
  1114.  
  1115.                     double d3 = 999.0D;
  1116.                     double d4 = 999.0D;
  1117.                     double d5 = 999.0D;
  1118.                     double d6 = vec32.x - vec31.x;
  1119.                     double d7 = vec32.y - vec31.y;
  1120.                     double d8 = vec32.z - vec31.z;
  1121.  
  1122.                     if (flag2)
  1123.                     {
  1124.                         d3 = (d0 - vec31.x) / d6;
  1125.                     }
  1126.  
  1127.                     if (flag)
  1128.                     {
  1129.                         d4 = (d1 - vec31.y) / d7;
  1130.                     }
  1131.  
  1132.                     if (flag1)
  1133.                     {
  1134.                         d5 = (d2 - vec31.z) / d8;
  1135.                     }
  1136.  
  1137.                     if (d3 == -0.0D)
  1138.                     {
  1139.                         d3 = -1.0E-4D;
  1140.                     }
  1141.  
  1142.                     if (d4 == -0.0D)
  1143.                     {
  1144.                         d4 = -1.0E-4D;
  1145.                     }
  1146.  
  1147.                     if (d5 == -0.0D)
  1148.                     {
  1149.                         d5 = -1.0E-4D;
  1150.                     }
  1151.  
  1152.                     EnumFacing enumfacing;
  1153.  
  1154.                     if (d3 < d4 && d3 < d5)
  1155.                     {
  1156.                         enumfacing = i > l ? EnumFacing.WEST : EnumFacing.EAST;
  1157.                         vec31 = new Vec3d(d0, vec31.y + d7 * d3, vec31.z + d8 * d3);
  1158.                     }
  1159.                     else if (d4 < d5)
  1160.                     {
  1161.                         enumfacing = j > i1 ? EnumFacing.DOWN : EnumFacing.UP;
  1162.                         vec31 = new Vec3d(vec31.x + d6 * d4, d1, vec31.z + d8 * d4);
  1163.                     }
  1164.                     else
  1165.                     {
  1166.                         enumfacing = k > j1 ? EnumFacing.NORTH : EnumFacing.SOUTH;
  1167.                         vec31 = new Vec3d(vec31.x + d6 * d5, vec31.y + d7 * d5, d2);
  1168.                     }
  1169.  
  1170.                     l = MathHelper.floor(vec31.x) - (enumfacing == EnumFacing.EAST ? 1 : 0);
  1171.                     i1 = MathHelper.floor(vec31.y) - (enumfacing == EnumFacing.UP ? 1 : 0);
  1172.                     j1 = MathHelper.floor(vec31.z) - (enumfacing == EnumFacing.SOUTH ? 1 : 0);
  1173.                     blockpos = new BlockPos(l, i1, j1);
  1174.                     IBlockState iblockstate1 = this.getBlockState(blockpos);
  1175.                     Block block1 = iblockstate1.getBlock();
  1176.  
  1177.                     if (!ignoreBlockWithoutBoundingBox || iblockstate1.getMaterial() == Material.PORTAL || iblockstate1.getCollisionBoundingBox(this, blockpos) != Block.NULL_AABB)
  1178.                     {
  1179.                         if (block1.canCollideCheck(iblockstate1, stopOnLiquid))
  1180.                         {
  1181.                             RayTraceResult raytraceresult1 = iblockstate1.collisionRayTrace(this, blockpos, vec31, vec32);
  1182.  
  1183.                             if (raytraceresult1 != null)
  1184.                             {
  1185.                                 return raytraceresult1;
  1186.                             }
  1187.                         }
  1188.                         else
  1189.                         {
  1190.                             raytraceresult2 = new RayTraceResult(RayTraceResult.Type.MISS, vec31, enumfacing, blockpos);
  1191.                         }
  1192.                     }
  1193.                 }
  1194.  
  1195.                 return returnLastUncollidableBlock ? raytraceresult2 : null;
  1196.             }
  1197.             else
  1198.             {
  1199.                 return null;
  1200.             }
  1201.         }
  1202.         else
  1203.         {
  1204.             return null;
  1205.         }
  1206.     }
  1207.  
  1208.     /**
  1209.      * Plays the specified sound for a player at the center of the given block position.
  1210.      */
  1211.     public void playSound(@Nullable EntityPlayer player, BlockPos pos, SoundEvent soundIn, SoundCategory category, float volume, float pitch)
  1212.     {
  1213.         this.playSound(player, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, soundIn, category, volume, pitch);
  1214.     }
  1215.  
  1216.     public void playSound(@Nullable EntityPlayer player, double x, double y, double z, SoundEvent soundIn, SoundCategory category, float volume, float pitch)
  1217.     {
  1218.         net.minecraftforge.event.entity.PlaySoundAtEntityEvent event = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAtEntity(player, soundIn, category, volume, pitch);
  1219.         if (event.isCanceled() || event.getSound() == null) return;
  1220.         soundIn = event.getSound();
  1221.         category = event.getCategory();
  1222.         volume = event.getVolume();
  1223.         pitch = event.getPitch();
  1224.  
  1225.         for (int i = 0; i < this.eventListeners.size(); ++i)
  1226.         {
  1227.             ((IWorldEventListener)this.eventListeners.get(i)).playSoundToAllNearExcept(player, soundIn, category, x, y, z, volume, pitch);
  1228.         }
  1229.     }
  1230.  
  1231.     public void playSound(double x, double y, double z, SoundEvent soundIn, SoundCategory category, float volume, float pitch, boolean distanceDelay)
  1232.     {
  1233.     }
  1234.  
  1235.     public void playRecord(BlockPos blockPositionIn, @Nullable SoundEvent soundEventIn)
  1236.     {
  1237.         for (int i = 0; i < this.eventListeners.size(); ++i)
  1238.         {
  1239.             ((IWorldEventListener)this.eventListeners.get(i)).playRecord(soundEventIn, blockPositionIn);
  1240.         }
  1241.     }
  1242.  
  1243.     public void spawnParticle(EnumParticleTypes particleType, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters)
  1244.     {
  1245.         this.spawnParticle(particleType.getParticleID(), particleType.getShouldIgnoreRange(), xCoord, yCoord, zCoord, xSpeed, ySpeed, zSpeed, parameters);
  1246.     }
  1247.  
  1248.     /**
  1249.      * Spawns particles that will always show regardless of the Video Settings -> Particles setting. Range restrictions
  1250.      * still apply.
  1251.      */
  1252.     public void spawnAlwaysVisibleParticle(int p_190523_1_, double p_190523_2_, double p_190523_4_, double p_190523_6_, double p_190523_8_, double p_190523_10_, double p_190523_12_, int... p_190523_14_)
  1253.     {
  1254.         for (int i = 0; i < this.eventListeners.size(); ++i)
  1255.         {
  1256.             ((IWorldEventListener)this.eventListeners.get(i)).spawnParticle(p_190523_1_, false, true, p_190523_2_, p_190523_4_, p_190523_6_, p_190523_8_, p_190523_10_, p_190523_12_, p_190523_14_);
  1257.         }
  1258.     }
  1259.  
  1260.     @SideOnly(Side.CLIENT)
  1261.     public void spawnParticle(EnumParticleTypes particleType, boolean ignoreRange, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters)
  1262.     {
  1263.         this.spawnParticle(particleType.getParticleID(), particleType.getShouldIgnoreRange() || ignoreRange, xCoord, yCoord, zCoord, xSpeed, ySpeed, zSpeed, parameters);
  1264.     }
  1265.  
  1266.     private void spawnParticle(int particleID, boolean ignoreRange, double xCood, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters)
  1267.     {
  1268.         for (int i = 0; i < this.eventListeners.size(); ++i)
  1269.         {
  1270.             ((IWorldEventListener)this.eventListeners.get(i)).spawnParticle(particleID, ignoreRange, xCood, yCoord, zCoord, xSpeed, ySpeed, zSpeed, parameters);
  1271.         }
  1272.     }
  1273.  
  1274.     /**
  1275.      * adds a lightning bolt to the list of lightning bolts in this world.
  1276.      */
  1277.     public boolean addWeatherEffect(Entity entityIn)
  1278.     {
  1279.         this.weatherEffects.add(entityIn);
  1280.         return true;
  1281.     }
  1282.  
  1283.     /**
  1284.      * Called when an entity is spawned in the world. This includes players.
  1285.      */
  1286.     public boolean spawnEntity(Entity entityIn)
  1287.     {
  1288.         // do not drop any items while restoring blocksnapshots. Prevents dupes
  1289.         if (!this.isRemote && (entityIn == null || (entityIn instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false;
  1290.  
  1291.         int i = MathHelper.floor(entityIn.posX / 16.0D);
  1292.         int j = MathHelper.floor(entityIn.posZ / 16.0D);
  1293.         boolean flag = entityIn.forceSpawn;
  1294.  
  1295.         if (entityIn instanceof EntityPlayer)
  1296.         {
  1297.             flag = true;
  1298.         }
  1299.  
  1300.         if (!flag && !this.isChunkLoaded(i, j, false))
  1301.         {
  1302.             return false;
  1303.         }
  1304.         else
  1305.         {
  1306.             if (entityIn instanceof EntityPlayer)
  1307.             {
  1308.                 EntityPlayer entityplayer = (EntityPlayer)entityIn;
  1309.                 this.playerEntities.add(entityplayer);
  1310.                 this.updateAllPlayersSleepingFlag();
  1311.             }
  1312.  
  1313.             if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entityIn, this)) && !flag) return false;
  1314.  
  1315.             this.getChunkFromChunkCoords(i, j).addEntity(entityIn);
  1316.             this.loadedEntityList.add(entityIn);
  1317.             this.onEntityAdded(entityIn);
  1318.             return true;
  1319.         }
  1320.     }
  1321.  
  1322.     public void onEntityAdded(Entity entityIn)
  1323.     {
  1324.         for (int i = 0; i < this.eventListeners.size(); ++i)
  1325.         {
  1326.             ((IWorldEventListener)this.eventListeners.get(i)).onEntityAdded(entityIn);
  1327.         }
  1328.         entityIn.onAddedToWorld();
  1329.     }
  1330.  
  1331.     public void onEntityRemoved(Entity entityIn)
  1332.     {
  1333.         for (int i = 0; i < this.eventListeners.size(); ++i)
  1334.         {
  1335.             ((IWorldEventListener)this.eventListeners.get(i)).onEntityRemoved(entityIn);
  1336.         }
  1337.         entityIn.onRemovedFromWorld();
  1338.     }
  1339.  
  1340.     /**
  1341.      * Schedule the entity for removal during the next tick. Marks the entity dead in anticipation.
  1342.      */
  1343.     public void removeEntity(Entity entityIn)
  1344.     {
  1345.         if (entityIn.isBeingRidden())
  1346.         {
  1347.             entityIn.removePassengers();
  1348.         }
  1349.  
  1350.         if (entityIn.isRiding())
  1351.         {
  1352.             entityIn.dismountRidingEntity();
  1353.         }
  1354.  
  1355.         entityIn.setDead();
  1356.  
  1357.         if (entityIn instanceof EntityPlayer)
  1358.         {
  1359.             this.playerEntities.remove(entityIn);
  1360.             this.updateAllPlayersSleepingFlag();
  1361.             this.onEntityRemoved(entityIn);
  1362.         }
  1363.     }
  1364.  
  1365.     /**
  1366.      * Do NOT use this method to remove normal entities- use normal removeEntity
  1367.      */
  1368.     public void removeEntityDangerously(Entity entityIn)
  1369.     {
  1370.         entityIn.setDropItemsWhenDead(false);
  1371.         entityIn.setDead();
  1372.  
  1373.         if (entityIn instanceof EntityPlayer)
  1374.         {
  1375.             this.playerEntities.remove(entityIn);
  1376.             this.updateAllPlayersSleepingFlag();
  1377.         }
  1378.  
  1379.         int i = entityIn.chunkCoordX;
  1380.         int j = entityIn.chunkCoordZ;
  1381.  
  1382.         if (entityIn.addedToChunk && this.isChunkLoaded(i, j, true))
  1383.         {
  1384.             this.getChunkFromChunkCoords(i, j).removeEntity(entityIn);
  1385.         }
  1386.  
  1387.         this.loadedEntityList.remove(entityIn);
  1388.         this.onEntityRemoved(entityIn);
  1389.     }
  1390.  
  1391.     /**
  1392.      * Add a world event listener
  1393.      */
  1394.     public void addEventListener(IWorldEventListener listener)
  1395.     {
  1396.         this.eventListeners.add(listener);
  1397.     }
  1398.  
  1399.     /**
  1400.      * Gets all <strong>block</strong> collision boxes in the given area. Also gets a world border collision box. Does
  1401.      * not get entity collision boxes.
  1402.      *  
  1403.      * @return true if any box intersects (i.e. resultList is not empty)
  1404.      *  
  1405.      * @param entityIn The entity to check with. Used for the world border and {@link
  1406.      * IBlockState#addCollisionBoxToList}. May be null, in which case the world border is skipped.
  1407.      * @param aabb The area to search
  1408.      * @param outList A list to store the intersecting AABBs.
  1409.      */
  1410.     private boolean getCollisionBoxes(@Nullable Entity entityIn, AxisAlignedBB aabb, boolean p_191504_3_, @Nullable List<AxisAlignedBB> outList)
  1411.     {
  1412.         int i = MathHelper.floor(aabb.minX) - 1;
  1413.         int j = MathHelper.ceil(aabb.maxX) + 1;
  1414.         int k = MathHelper.floor(aabb.minY) - 1;
  1415.         int l = MathHelper.ceil(aabb.maxY) + 1;
  1416.         int i1 = MathHelper.floor(aabb.minZ) - 1;
  1417.         int j1 = MathHelper.ceil(aabb.maxZ) + 1;
  1418.         WorldBorder worldborder = this.getWorldBorder();
  1419.         boolean flag = entityIn != null && entityIn.isOutsideBorder();
  1420.         boolean flag1 = entityIn != null && this.isInsideWorldBorder(entityIn);
  1421.         IBlockState iblockstate = Blocks.STONE.getDefaultState();
  1422.         BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  1423.  
  1424.         if (p_191504_3_ && !net.minecraftforge.event.ForgeEventFactory.gatherCollisionBoxes(this, entityIn, aabb, outList)) return true;
  1425.         try
  1426.         {
  1427.             for (int k1 = i; k1 < j; ++k1)
  1428.             {
  1429.                 for (int l1 = i1; l1 < j1; ++l1)
  1430.                 {
  1431.                     boolean flag2 = k1 == i || k1 == j - 1;
  1432.                     boolean flag3 = l1 == i1 || l1 == j1 - 1;
  1433.  
  1434.                     if ((!flag2 || !flag3) && this.isBlockLoaded(blockpos$pooledmutableblockpos.setPos(k1, 64, l1)))
  1435.                     {
  1436.                         for (int i2 = k; i2 < l; ++i2)
  1437.                         {
  1438.                             if (!flag2 && !flag3 || i2 != l - 1)
  1439.                             {
  1440.                                 if (p_191504_3_)
  1441.                                 {
  1442.                                     if (k1 < -30000000 || k1 >= 30000000 || l1 < -30000000 || l1 >= 30000000)
  1443.                                     {
  1444.                                         boolean lvt_21_2_ = true;
  1445.                                         return lvt_21_2_;
  1446.                                     }
  1447.                                 }
  1448.                                 else if (entityIn != null && flag == flag1)
  1449.                                 {
  1450.                                     entityIn.setOutsideBorder(!flag1);
  1451.                                 }
  1452.  
  1453.                                 blockpos$pooledmutableblockpos.setPos(k1, i2, l1);
  1454.                                 IBlockState iblockstate1;
  1455.  
  1456.                                 if (!p_191504_3_ && !worldborder.contains(blockpos$pooledmutableblockpos) && flag1)
  1457.                                 {
  1458.                                     iblockstate1 = iblockstate;
  1459.                                 }
  1460.                                 else
  1461.                                 {
  1462.                                     iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos);
  1463.                                 }
  1464.  
  1465.                                 iblockstate1.addCollisionBoxToList(this, blockpos$pooledmutableblockpos, aabb, outList, entityIn, false);
  1466.  
  1467.                                 if (p_191504_3_ && !net.minecraftforge.event.ForgeEventFactory.gatherCollisionBoxes(this, entityIn, aabb, outList))
  1468.                                 {
  1469.                                     boolean flag5 = true;
  1470.                                     return flag5;
  1471.                                 }
  1472.                             }
  1473.                         }
  1474.                     }
  1475.                 }
  1476.             }
  1477.         }
  1478.         finally
  1479.         {
  1480.             blockpos$pooledmutableblockpos.release();
  1481.         }
  1482.  
  1483.         return !outList.isEmpty();
  1484.     }
  1485.  
  1486.     /**
  1487.      * Gets a list of bounding boxes that intersect with the provided AABB.
  1488.      */
  1489.     public List<AxisAlignedBB> getCollisionBoxes(@Nullable Entity entityIn, AxisAlignedBB aabb)
  1490.     {
  1491.         List<AxisAlignedBB> list = Lists.<AxisAlignedBB>newArrayList();
  1492.         this.getCollisionBoxes(entityIn, aabb, false, list);
  1493.  
  1494.         if (entityIn != null)
  1495.         {
  1496.             List<Entity> list1 = this.getEntitiesWithinAABBExcludingEntity(entityIn, aabb.grow(0.25D));
  1497.  
  1498.             for (int i = 0; i < list1.size(); ++i)
  1499.             {
  1500.                 Entity entity = list1.get(i);
  1501.  
  1502.                 if (!entityIn.isRidingSameEntity(entity))
  1503.                 {
  1504.                     AxisAlignedBB axisalignedbb = entity.getCollisionBoundingBox();
  1505.  
  1506.                     if (axisalignedbb != null && axisalignedbb.intersects(aabb))
  1507.                     {
  1508.                         list.add(axisalignedbb);
  1509.                     }
  1510.  
  1511.                     axisalignedbb = entityIn.getCollisionBox(entity);
  1512.  
  1513.                     if (axisalignedbb != null && axisalignedbb.intersects(aabb))
  1514.                     {
  1515.                         list.add(axisalignedbb);
  1516.                     }
  1517.                 }
  1518.             }
  1519.         }
  1520.         net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.GetCollisionBoxesEvent(this, entityIn, aabb, list));
  1521.         return list;
  1522.     }
  1523.  
  1524.     /**
  1525.      * Remove a world event listener
  1526.      */
  1527.     public void removeEventListener(IWorldEventListener listener)
  1528.     {
  1529.         this.eventListeners.remove(listener);
  1530.     }
  1531.  
  1532.     public boolean isInsideWorldBorder(Entity p_191503_1_)
  1533.     {
  1534.         double d0 = this.worldBorder.minX();
  1535.         double d1 = this.worldBorder.minZ();
  1536.         double d2 = this.worldBorder.maxX();
  1537.         double d3 = this.worldBorder.maxZ();
  1538.  
  1539.         if (p_191503_1_.isOutsideBorder())
  1540.         {
  1541.             ++d0;
  1542.             ++d1;
  1543.             --d2;
  1544.             --d3;
  1545.         }
  1546.         else
  1547.         {
  1548.             --d0;
  1549.             --d1;
  1550.             ++d2;
  1551.             ++d3;
  1552.         }
  1553.  
  1554.         return p_191503_1_.posX > d0 && p_191503_1_.posX < d2 && p_191503_1_.posZ > d1 && p_191503_1_.posZ < d3;
  1555.     }
  1556.  
  1557.     /**
  1558.      * Returns true if the given bbox collides with any block.
  1559.      */
  1560.     public boolean collidesWithAnyBlock(AxisAlignedBB bbox)
  1561.     {
  1562.         return this.getCollisionBoxes((Entity)null, bbox, true, Lists.newArrayList());
  1563.     }
  1564.  
  1565.     /**
  1566.      * Returns the amount of skylight subtracted for the current time
  1567.      */
  1568.     public int calculateSkylightSubtracted(float partialTicks)
  1569.     {
  1570.         float f = provider.getSunBrightnessFactor(partialTicks);
  1571.         f = 1 - f;
  1572.         return (int)(f * 11);
  1573.     }
  1574.  
  1575.     /**
  1576.      * The current sun brightness factor for this dimension.
  1577.      * 0.0f means no light at all, and 1.0f means maximum sunlight.
  1578.      * Highly recommended for sunlight detection like solar panel.
  1579.      *
  1580.      * @return The current brightness factor
  1581.      * */
  1582.     public float getSunBrightnessFactor(float partialTicks)
  1583.     {
  1584.         float f = this.getCelestialAngle(partialTicks);
  1585.         float f1 = 1.0F - (MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F);
  1586.         f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
  1587.         f1 = 1.0F - f1;
  1588.         f1 = (float)((double)f1 * (1.0D - (double)(this.getRainStrength(partialTicks) * 5.0F) / 16.0D));
  1589.         f1 = (float)((double)f1 * (1.0D - (double)(this.getThunderStrength(partialTicks) * 5.0F) / 16.0D));
  1590.         return f1;
  1591.     }
  1592.  
  1593.     /**
  1594.      * Returns the sun brightness - checks time of day, rain and thunder
  1595.      */
  1596.     @SideOnly(Side.CLIENT)
  1597.     public float getSunBrightness(float partialTicks)
  1598.     {
  1599.         return this.provider.getSunBrightness(partialTicks);
  1600.     }
  1601.  
  1602.     @SideOnly(Side.CLIENT)
  1603.     public float getSunBrightnessBody(float partialTicks)
  1604.     {
  1605.         float f = this.getCelestialAngle(partialTicks);
  1606.         float f1 = 1.0F - (MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.2F);
  1607.         f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
  1608.         f1 = 1.0F - f1;
  1609.         f1 = (float)((double)f1 * (1.0D - (double)(this.getRainStrength(partialTicks) * 5.0F) / 16.0D));
  1610.         f1 = (float)((double)f1 * (1.0D - (double)(this.getThunderStrength(partialTicks) * 5.0F) / 16.0D));
  1611.         return f1 * 0.8F + 0.2F;
  1612.     }
  1613.  
  1614.     /**
  1615.      * Calculates the color for the skybox
  1616.      */
  1617.     @SideOnly(Side.CLIENT)
  1618.     public Vec3d getSkyColor(Entity entityIn, float partialTicks)
  1619.     {
  1620.         return this.provider.getSkyColor(entityIn, partialTicks);
  1621.     }
  1622.  
  1623.     @SideOnly(Side.CLIENT)
  1624.     public Vec3d getSkyColorBody(Entity entityIn, float partialTicks)
  1625.     {
  1626.         float f = this.getCelestialAngle(partialTicks);
  1627.         float f1 = MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F;
  1628.         f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
  1629.         int i = MathHelper.floor(entityIn.posX);
  1630.         int j = MathHelper.floor(entityIn.posY);
  1631.         int k = MathHelper.floor(entityIn.posZ);
  1632.         BlockPos blockpos = new BlockPos(i, j, k);
  1633.         int l = net.minecraftforge.client.ForgeHooksClient.getSkyBlendColour(this, blockpos);
  1634.         float f3 = (float)(l >> 16 & 255) / 255.0F;
  1635.         float f4 = (float)(l >> 8 & 255) / 255.0F;
  1636.         float f5 = (float)(l & 255) / 255.0F;
  1637.         f3 = f3 * f1;
  1638.         f4 = f4 * f1;
  1639.         f5 = f5 * f1;
  1640.         float f6 = this.getRainStrength(partialTicks);
  1641.  
  1642.         if (f6 > 0.0F)
  1643.         {
  1644.             float f7 = (f3 * 0.3F + f4 * 0.59F + f5 * 0.11F) * 0.6F;
  1645.             float f8 = 1.0F - f6 * 0.75F;
  1646.             f3 = f3 * f8 + f7 * (1.0F - f8);
  1647.             f4 = f4 * f8 + f7 * (1.0F - f8);
  1648.             f5 = f5 * f8 + f7 * (1.0F - f8);
  1649.         }
  1650.  
  1651.         float f10 = this.getThunderStrength(partialTicks);
  1652.  
  1653.         if (f10 > 0.0F)
  1654.         {
  1655.             float f11 = (f3 * 0.3F + f4 * 0.59F + f5 * 0.11F) * 0.2F;
  1656.             float f9 = 1.0F - f10 * 0.75F;
  1657.             f3 = f3 * f9 + f11 * (1.0F - f9);
  1658.             f4 = f4 * f9 + f11 * (1.0F - f9);
  1659.             f5 = f5 * f9 + f11 * (1.0F - f9);
  1660.         }
  1661.  
  1662.         if (this.lastLightningBolt > 0)
  1663.         {
  1664.             float f12 = (float)this.lastLightningBolt - partialTicks;
  1665.  
  1666.             if (f12 > 1.0F)
  1667.             {
  1668.                 f12 = 1.0F;
  1669.             }
  1670.  
  1671.             f12 = f12 * 0.45F;
  1672.             f3 = f3 * (1.0F - f12) + 0.8F * f12;
  1673.             f4 = f4 * (1.0F - f12) + 0.8F * f12;
  1674.             f5 = f5 * (1.0F - f12) + 1.0F * f12;
  1675.         }
  1676.  
  1677.         return new Vec3d((double)f3, (double)f4, (double)f5);
  1678.     }
  1679.  
  1680.     /**
  1681.      * calls calculateCelestialAngle
  1682.      */
  1683.     public float getCelestialAngle(float partialTicks)
  1684.     {
  1685.         return this.provider.calculateCelestialAngle(this.getWorldTime(), partialTicks);
  1686.     }
  1687.  
  1688.     @SideOnly(Side.CLIENT)
  1689.     public int getMoonPhase()
  1690.     {
  1691.         return this.provider.getMoonPhase(this.getWorldTime());
  1692.     }
  1693.  
  1694.     /**
  1695.      * gets the current fullness of the moon expressed as a float between 1.0 and 0.0, in steps of .25
  1696.      */
  1697.     public float getCurrentMoonPhaseFactor()
  1698.     {
  1699.         return provider.getCurrentMoonPhaseFactor();
  1700.     }
  1701.  
  1702.     public float getCurrentMoonPhaseFactorBody()
  1703.     {
  1704.         return WorldProvider.MOON_PHASE_FACTORS[this.provider.getMoonPhase(this.getWorldTime())];
  1705.     }
  1706.  
  1707.     /**
  1708.      * Return getCelestialAngle()*2*PI
  1709.      */
  1710.     public float getCelestialAngleRadians(float partialTicks)
  1711.     {
  1712.         float f = this.getCelestialAngle(partialTicks);
  1713.         return f * ((float)Math.PI * 2F);
  1714.     }
  1715.  
  1716.     @SideOnly(Side.CLIENT)
  1717.     public Vec3d getCloudColour(float partialTicks)
  1718.     {
  1719.         return this.provider.getCloudColor(partialTicks);
  1720.     }
  1721.  
  1722.     @SideOnly(Side.CLIENT)
  1723.     public Vec3d getCloudColorBody(float partialTicks)
  1724.     {
  1725.         float f = this.getCelestialAngle(partialTicks);
  1726.         float f1 = MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F;
  1727.         f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
  1728.         float f2 = 1.0F;
  1729.         float f3 = 1.0F;
  1730.         float f4 = 1.0F;
  1731.         float f5 = this.getRainStrength(partialTicks);
  1732.  
  1733.         if (f5 > 0.0F)
  1734.         {
  1735.             float f6 = (f2 * 0.3F + f3 * 0.59F + f4 * 0.11F) * 0.6F;
  1736.             float f7 = 1.0F - f5 * 0.95F;
  1737.             f2 = f2 * f7 + f6 * (1.0F - f7);
  1738.             f3 = f3 * f7 + f6 * (1.0F - f7);
  1739.             f4 = f4 * f7 + f6 * (1.0F - f7);
  1740.         }
  1741.  
  1742.         f2 = f2 * (f1 * 0.9F + 0.1F);
  1743.         f3 = f3 * (f1 * 0.9F + 0.1F);
  1744.         f4 = f4 * (f1 * 0.85F + 0.15F);
  1745.         float f9 = this.getThunderStrength(partialTicks);
  1746.  
  1747.         if (f9 > 0.0F)
  1748.         {
  1749.             float f10 = (f2 * 0.3F + f3 * 0.59F + f4 * 0.11F) * 0.2F;
  1750.             float f8 = 1.0F - f9 * 0.95F;
  1751.             f2 = f2 * f8 + f10 * (1.0F - f8);
  1752.             f3 = f3 * f8 + f10 * (1.0F - f8);
  1753.             f4 = f4 * f8 + f10 * (1.0F - f8);
  1754.         }
  1755.  
  1756.         return new Vec3d((double)f2, (double)f3, (double)f4);
  1757.     }
  1758.  
  1759.     /**
  1760.      * Returns vector(ish) with R/G/B for fog
  1761.      */
  1762.     @SideOnly(Side.CLIENT)
  1763.     public Vec3d getFogColor(float partialTicks)
  1764.     {
  1765.         float f = this.getCelestialAngle(partialTicks);
  1766.         return this.provider.getFogColor(f, partialTicks);
  1767.     }
  1768.  
  1769.     public BlockPos getPrecipitationHeight(BlockPos pos)
  1770.     {
  1771.         return this.getChunkFromBlockCoords(pos).getPrecipitationHeight(pos);
  1772.     }
  1773.  
  1774.     /**
  1775.      * Finds the highest block on the x and z coordinate that is solid or liquid, and returns its y coord.
  1776.      */
  1777.     public BlockPos getTopSolidOrLiquidBlock(BlockPos pos)
  1778.     {
  1779.         Chunk chunk = this.getChunkFromBlockCoords(pos);
  1780.         BlockPos blockpos;
  1781.         BlockPos blockpos1;
  1782.  
  1783.         for (blockpos = new BlockPos(pos.getX(), chunk.getTopFilledSegment() + 16, pos.getZ()); blockpos.getY() >= 0; blockpos = blockpos1)
  1784.         {
  1785.             blockpos1 = blockpos.down();
  1786.             IBlockState state = chunk.getBlockState(blockpos1);
  1787.  
  1788.             if (state.getMaterial().blocksMovement() && !state.getBlock().isLeaves(state, this, blockpos1) && !state.getBlock().isFoliage(this, blockpos1))
  1789.             {
  1790.                 break;
  1791.             }
  1792.         }
  1793.  
  1794.         return blockpos;
  1795.     }
  1796.  
  1797.     /**
  1798.      * How bright are stars in the sky
  1799.      */
  1800.     @SideOnly(Side.CLIENT)
  1801.     public float getStarBrightness(float partialTicks)
  1802.     {
  1803.         return this.provider.getStarBrightness(partialTicks);
  1804.     }
  1805.  
  1806.     @SideOnly(Side.CLIENT)
  1807.     public float getStarBrightnessBody(float partialTicks)
  1808.     {
  1809.         float f = this.getCelestialAngle(partialTicks);
  1810.         float f1 = 1.0F - (MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.25F);
  1811.         f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
  1812.         return f1 * f1 * 0.5F;
  1813.     }
  1814.  
  1815.     /**
  1816.      * Returns true if the identified block is scheduled to be updated.
  1817.      */
  1818.     public boolean isUpdateScheduled(BlockPos pos, Block blk)
  1819.     {
  1820.         return true;
  1821.     }
  1822.  
  1823.     public void scheduleUpdate(BlockPos pos, Block blockIn, int delay)
  1824.     {
  1825.     }
  1826.  
  1827.     public void updateBlockTick(BlockPos pos, Block blockIn, int delay, int priority)
  1828.     {
  1829.     }
  1830.  
  1831.     /**
  1832.      * Called by CommandClone and AnvilChunkLoader to force a block update.
  1833.      */
  1834.     public void scheduleBlockUpdate(BlockPos pos, Block blockIn, int delay, int priority)
  1835.     {
  1836.     }
  1837.  
  1838.     /**
  1839.      * Updates (and cleans up) entities and tile entities
  1840.      */
  1841.     public void updateEntities()
  1842.     {
  1843.         this.profiler.startSection("entities");
  1844.         this.profiler.startSection("global");
  1845.  
  1846.         for (int i = 0; i < this.weatherEffects.size(); ++i)
  1847.         {
  1848.             Entity entity = this.weatherEffects.get(i);
  1849.  
  1850.             try
  1851.             {
  1852.                 if(entity.updateBlocked) continue;
  1853.                 ++entity.ticksExisted;
  1854.                 entity.onUpdate();
  1855.             }
  1856.             catch (Throwable throwable2)
  1857.             {
  1858.                 CrashReport crashreport = CrashReport.makeCrashReport(throwable2, "Ticking entity");
  1859.                 CrashReportCategory crashreportcategory = crashreport.makeCategory("Entity being ticked");
  1860.  
  1861.                 if (entity == null)
  1862.                 {
  1863.                     crashreportcategory.addCrashSection("Entity", "~~NULL~~");
  1864.                 }
  1865.                 else
  1866.                 {
  1867.                     entity.addEntityCrashInfo(crashreportcategory);
  1868.                 }
  1869.  
  1870.                 if (net.minecraftforge.common.ForgeModContainer.removeErroringEntities)
  1871.                 {
  1872.                     net.minecraftforge.fml.common.FMLLog.log.fatal("{}", crashreport.getCompleteReport());
  1873.                     removeEntity(entity);
  1874.                 }
  1875.                 else
  1876.                 throw new ReportedException(crashreport);
  1877.             }
  1878.  
  1879.             if (entity.isDead)
  1880.             {
  1881.                 this.weatherEffects.remove(i--);
  1882.             }
  1883.         }
  1884.  
  1885.         this.profiler.endStartSection("remove");
  1886.         this.loadedEntityList.removeAll(this.unloadedEntityList);
  1887.  
  1888.         for (int k = 0; k < this.unloadedEntityList.size(); ++k)
  1889.         {
  1890.             Entity entity1 = this.unloadedEntityList.get(k);
  1891.             int j = entity1.chunkCoordX;
  1892.             int k1 = entity1.chunkCoordZ;
  1893.  
  1894.             if (entity1.addedToChunk && this.isChunkLoaded(j, k1, true))
  1895.             {
  1896.                 this.getChunkFromChunkCoords(j, k1).removeEntity(entity1);
  1897.             }
  1898.         }
  1899.  
  1900.         for (int l = 0; l < this.unloadedEntityList.size(); ++l)
  1901.         {
  1902.             this.onEntityRemoved(this.unloadedEntityList.get(l));
  1903.         }
  1904.  
  1905.         this.unloadedEntityList.clear();
  1906.         this.tickPlayers();
  1907.         this.profiler.endStartSection("regular");
  1908.  
  1909.         for (int i1 = 0; i1 < this.loadedEntityList.size(); ++i1)
  1910.         {
  1911.             Entity entity2 = this.loadedEntityList.get(i1);
  1912.             Entity entity3 = entity2.getRidingEntity();
  1913.  
  1914.             if (entity3 != null)
  1915.             {
  1916.                 if (!entity3.isDead && entity3.isPassenger(entity2))
  1917.                 {
  1918.                     continue;
  1919.                 }
  1920.  
  1921.                 entity2.dismountRidingEntity();
  1922.             }
  1923.  
  1924.             this.profiler.startSection("tick");
  1925.  
  1926.             if (!entity2.isDead && !(entity2 instanceof EntityPlayerMP))
  1927.             {
  1928.                 try
  1929.                 {
  1930.                     net.minecraftforge.server.timings.TimeTracker.ENTITY_UPDATE.trackStart(entity2);
  1931.                     this.updateEntity(entity2);
  1932.                     net.minecraftforge.server.timings.TimeTracker.ENTITY_UPDATE.trackEnd(entity2);
  1933.                 }
  1934.                 catch (Throwable throwable1)
  1935.                 {
  1936.                     CrashReport crashreport1 = CrashReport.makeCrashReport(throwable1, "Ticking entity");
  1937.                     CrashReportCategory crashreportcategory1 = crashreport1.makeCategory("Entity being ticked");
  1938.                     entity2.addEntityCrashInfo(crashreportcategory1);
  1939.                     if (net.minecraftforge.common.ForgeModContainer.removeErroringEntities)
  1940.                     {
  1941.                         net.minecraftforge.fml.common.FMLLog.log.fatal("{}", crashreport1.getCompleteReport());
  1942.                         removeEntity(entity2);
  1943.                     }
  1944.                     else
  1945.                     throw new ReportedException(crashreport1);
  1946.                 }
  1947.             }
  1948.  
  1949.             this.profiler.endSection();
  1950.             this.profiler.startSection("remove");
  1951.  
  1952.             if (entity2.isDead)
  1953.             {
  1954.                 int l1 = entity2.chunkCoordX;
  1955.                 int i2 = entity2.chunkCoordZ;
  1956.  
  1957.                 if (entity2.addedToChunk && this.isChunkLoaded(l1, i2, true))
  1958.                 {
  1959.                     this.getChunkFromChunkCoords(l1, i2).removeEntity(entity2);
  1960.                 }
  1961.  
  1962.                 this.loadedEntityList.remove(i1--);
  1963.                 this.onEntityRemoved(entity2);
  1964.             }
  1965.  
  1966.             this.profiler.endSection();
  1967.         }
  1968.  
  1969.         this.profiler.endStartSection("blockEntities");
  1970.  
  1971.         this.processingLoadedTiles = true; //FML Move above remove to prevent CMEs
  1972.  
  1973.         if (!this.tileEntitiesToBeRemoved.isEmpty())
  1974.         {
  1975.             for (Object tile : tileEntitiesToBeRemoved)
  1976.             {
  1977.                ((TileEntity)tile).onChunkUnload();
  1978.             }
  1979.  
  1980.             // forge: faster "contains" makes this removal much more efficient
  1981.             java.util.Set<TileEntity> remove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
  1982.             remove.addAll(tileEntitiesToBeRemoved);
  1983.             this.tickableTileEntities.removeAll(remove);
  1984.             this.loadedTileEntityList.removeAll(remove);
  1985.             this.tileEntitiesToBeRemoved.clear();
  1986.         }
  1987.  
  1988.         Iterator<TileEntity> iterator = this.tickableTileEntities.iterator();
  1989.  
  1990.         while (iterator.hasNext())
  1991.         {
  1992.             TileEntity tileentity = iterator.next();
  1993.  
  1994.             if (!tileentity.isInvalid() && tileentity.hasWorld())
  1995.             {
  1996.                 BlockPos blockpos = tileentity.getPos();
  1997.  
  1998.                 if (this.isBlockLoaded(blockpos, false) && this.worldBorder.contains(blockpos)) //Forge: Fix TE's getting an extra tick on the client side....
  1999.                 {
  2000.                     try
  2001.                     {
  2002.                         this.profiler.func_194340_a(() ->
  2003.                         {
  2004.                             return String.valueOf((Object)TileEntity.getKey(tileentity.getClass()));
  2005.                         });
  2006.                         net.minecraftforge.server.timings.TimeTracker.TILE_ENTITY_UPDATE.trackStart(tileentity);
  2007.                         ((ITickable)tileentity).update();
  2008.                         net.minecraftforge.server.timings.TimeTracker.TILE_ENTITY_UPDATE.trackEnd(tileentity);
  2009.                         this.profiler.endSection();
  2010.                     }
  2011.                     catch (Throwable throwable)
  2012.                     {
  2013.                         CrashReport crashreport2 = CrashReport.makeCrashReport(throwable, "Ticking block entity");
  2014.                         CrashReportCategory crashreportcategory2 = crashreport2.makeCategory("Block entity being ticked");
  2015.                         tileentity.addInfoToCrashReport(crashreportcategory2);
  2016.                         if (net.minecraftforge.common.ForgeModContainer.removeErroringTileEntities)
  2017.                         {
  2018.                             net.minecraftforge.fml.common.FMLLog.log.fatal("{}", crashreport2.getCompleteReport());
  2019.                             tileentity.invalidate();
  2020.                             this.removeTileEntity(tileentity.getPos());
  2021.                         }
  2022.                         else
  2023.                         throw new ReportedException(crashreport2);
  2024.                     }
  2025.                 }
  2026.             }
  2027.  
  2028.             if (tileentity.isInvalid())
  2029.             {
  2030.                 iterator.remove();
  2031.                 this.loadedTileEntityList.remove(tileentity);
  2032.  
  2033.                 if (this.isBlockLoaded(tileentity.getPos()))
  2034.                 {
  2035.                     //Forge: Bugfix: If we set the tile entity it immediately sets it in the chunk, so we could be desyned
  2036.                     Chunk chunk = this.getChunkFromBlockCoords(tileentity.getPos());
  2037.                     if (chunk.getTileEntity(tileentity.getPos(), net.minecraft.world.chunk.Chunk.EnumCreateEntityType.CHECK) == tileentity)
  2038.                         chunk.removeTileEntity(tileentity.getPos());
  2039.                 }
  2040.             }
  2041.         }
  2042.  
  2043.         this.processingLoadedTiles = false;
  2044.         this.profiler.endStartSection("pendingBlockEntities");
  2045.  
  2046.         if (!this.addedTileEntityList.isEmpty())
  2047.         {
  2048.             for (int j1 = 0; j1 < this.addedTileEntityList.size(); ++j1)
  2049.             {
  2050.                 TileEntity tileentity1 = this.addedTileEntityList.get(j1);
  2051.  
  2052.                 if (!tileentity1.isInvalid())
  2053.                 {
  2054.                     if (!this.loadedTileEntityList.contains(tileentity1))
  2055.                     {
  2056.                         this.addTileEntity(tileentity1);
  2057.                     }
  2058.  
  2059.                     if (this.isBlockLoaded(tileentity1.getPos()))
  2060.                     {
  2061.                         Chunk chunk = this.getChunkFromBlockCoords(tileentity1.getPos());
  2062.                         IBlockState iblockstate = chunk.getBlockState(tileentity1.getPos());
  2063.                         chunk.addTileEntity(tileentity1.getPos(), tileentity1);
  2064.                         this.notifyBlockUpdate(tileentity1.getPos(), iblockstate, iblockstate, 3);
  2065.                     }
  2066.                 }
  2067.             }
  2068.  
  2069.             this.addedTileEntityList.clear();
  2070.         }
  2071.  
  2072.         this.profiler.endSection();
  2073.         this.profiler.endSection();
  2074.     }
  2075.  
  2076.     protected void tickPlayers()
  2077.     {
  2078.     }
  2079.  
  2080.     public boolean addTileEntity(TileEntity tile)
  2081.     {
  2082.         // Forge - set the world early as vanilla doesn't set it until next tick
  2083.         if (tile.getWorld() != this) tile.setWorld(this);
  2084.         // Forge: wait to add new TE if we're currently processing existing ones
  2085.         if (processingLoadedTiles) return addedTileEntityList.add(tile);
  2086.  
  2087.         boolean flag = this.loadedTileEntityList.add(tile);
  2088.  
  2089.         if (flag && tile instanceof ITickable)
  2090.         {
  2091.             this.tickableTileEntities.add(tile);
  2092.         }
  2093.         tile.onLoad();
  2094.  
  2095.         if (this.isRemote)
  2096.         {
  2097.             BlockPos blockpos1 = tile.getPos();
  2098.             IBlockState iblockstate1 = this.getBlockState(blockpos1);
  2099.             this.notifyBlockUpdate(blockpos1, iblockstate1, iblockstate1, 2);
  2100.         }
  2101.  
  2102.         return flag;
  2103.     }
  2104.  
  2105.     public void addTileEntities(Collection<TileEntity> tileEntityCollection)
  2106.     {
  2107.         if (this.processingLoadedTiles)
  2108.         {
  2109.             for (TileEntity te : tileEntityCollection)
  2110.             {
  2111.                 if (te.getWorld() != this) // Forge - set the world early as vanilla doesn't set it until next tick
  2112.                     te.setWorld(this);
  2113.             }
  2114.             this.addedTileEntityList.addAll(tileEntityCollection);
  2115.         }
  2116.         else
  2117.         {
  2118.             for (TileEntity tileentity2 : tileEntityCollection)
  2119.             {
  2120.                 this.addTileEntity(tileentity2);
  2121.             }
  2122.         }
  2123.     }
  2124.  
  2125.     /**
  2126.      * Forcefully updates the entity.
  2127.      */
  2128.     public void updateEntity(Entity ent)
  2129.     {
  2130.         this.updateEntityWithOptionalForce(ent, true);
  2131.     }
  2132.  
  2133.     /**
  2134.      * Updates the entity in the world if the chunk the entity is in is currently loaded or its forced to update.
  2135.      */
  2136.     public void updateEntityWithOptionalForce(Entity entityIn, boolean forceUpdate)
  2137.     {
  2138.         if (!(entityIn instanceof EntityPlayer))
  2139.         {
  2140.             int j2 = MathHelper.floor(entityIn.posX);
  2141.             int k2 = MathHelper.floor(entityIn.posZ);
  2142.  
  2143.             boolean isForced = getPersistentChunks().containsKey(new net.minecraft.util.math.ChunkPos(j2 >> 4, k2 >> 4));
  2144.             int range = isForced ? 0 : 32;
  2145.             boolean canUpdate = !forceUpdate || this.isAreaLoaded(j2 - range, 0, k2 - range, j2 + range, 0, k2 + range, true);
  2146.             if (!canUpdate) canUpdate = net.minecraftforge.event.ForgeEventFactory.canEntityUpdate(entityIn);
  2147.  
  2148.             if (!canUpdate)
  2149.             {
  2150.                 return;
  2151.             }
  2152.         }
  2153.  
  2154.         entityIn.lastTickPosX = entityIn.posX;
  2155.         entityIn.lastTickPosY = entityIn.posY;
  2156.         entityIn.lastTickPosZ = entityIn.posZ;
  2157.         entityIn.prevRotationYaw = entityIn.rotationYaw;
  2158.         entityIn.prevRotationPitch = entityIn.rotationPitch;
  2159.  
  2160.         if (forceUpdate && entityIn.addedToChunk)
  2161.         {
  2162.             ++entityIn.ticksExisted;
  2163.  
  2164.             if (entityIn.isRiding())
  2165.             {
  2166.                 entityIn.updateRidden();
  2167.             }
  2168.             else
  2169.             {
  2170.                 if(!entityIn.updateBlocked)
  2171.                 entityIn.onUpdate();
  2172.             }
  2173.         }
  2174.  
  2175.         this.profiler.startSection("chunkCheck");
  2176.  
  2177.         if (Double.isNaN(entityIn.posX) || Double.isInfinite(entityIn.posX))
  2178.         {
  2179.             entityIn.posX = entityIn.lastTickPosX;
  2180.         }
  2181.  
  2182.         if (Double.isNaN(entityIn.posY) || Double.isInfinite(entityIn.posY))
  2183.         {
  2184.             entityIn.posY = entityIn.lastTickPosY;
  2185.         }
  2186.  
  2187.         if (Double.isNaN(entityIn.posZ) || Double.isInfinite(entityIn.posZ))
  2188.         {
  2189.             entityIn.posZ = entityIn.lastTickPosZ;
  2190.         }
  2191.  
  2192.         if (Double.isNaN((double)entityIn.rotationPitch) || Double.isInfinite((double)entityIn.rotationPitch))
  2193.         {
  2194.             entityIn.rotationPitch = entityIn.prevRotationPitch;
  2195.         }
  2196.  
  2197.         if (Double.isNaN((double)entityIn.rotationYaw) || Double.isInfinite((double)entityIn.rotationYaw))
  2198.         {
  2199.             entityIn.rotationYaw = entityIn.prevRotationYaw;
  2200.         }
  2201.  
  2202.         int i3 = MathHelper.floor(entityIn.posX / 16.0D);
  2203.         int j3 = MathHelper.floor(entityIn.posY / 16.0D);
  2204.         int k3 = MathHelper.floor(entityIn.posZ / 16.0D);
  2205.  
  2206.         if (!entityIn.addedToChunk || entityIn.chunkCoordX != i3 || entityIn.chunkCoordY != j3 || entityIn.chunkCoordZ != k3)
  2207.         {
  2208.             if (entityIn.addedToChunk && this.isChunkLoaded(entityIn.chunkCoordX, entityIn.chunkCoordZ, true))
  2209.             {
  2210.                 this.getChunkFromChunkCoords(entityIn.chunkCoordX, entityIn.chunkCoordZ).removeEntityAtIndex(entityIn, entityIn.chunkCoordY);
  2211.             }
  2212.  
  2213.             if (!entityIn.setPositionNonDirty() && !this.isChunkLoaded(i3, k3, true))
  2214.             {
  2215.                 entityIn.addedToChunk = false;
  2216.             }
  2217.             else
  2218.             {
  2219.                 this.getChunkFromChunkCoords(i3, k3).addEntity(entityIn);
  2220.             }
  2221.         }
  2222.  
  2223.         this.profiler.endSection();
  2224.  
  2225.         if (forceUpdate && entityIn.addedToChunk)
  2226.         {
  2227.             for (Entity entity4 : entityIn.getPassengers())
  2228.             {
  2229.                 if (!entity4.isDead && entity4.getRidingEntity() == entityIn)
  2230.                 {
  2231.                     this.updateEntity(entity4);
  2232.                 }
  2233.                 else
  2234.                 {
  2235.                     entity4.dismountRidingEntity();
  2236.                 }
  2237.             }
  2238.         }
  2239.     }
  2240.  
  2241.     /**
  2242.      * Returns true if there are no solid, live entities in the specified AxisAlignedBB
  2243.      */
  2244.     public boolean checkNoEntityCollision(AxisAlignedBB bb)
  2245.     {
  2246.         return this.checkNoEntityCollision(bb, (Entity)null);
  2247.     }
  2248.  
  2249.     /**
  2250.      * Returns true if there are no solid, live entities in the specified AxisAlignedBB, excluding the given entity
  2251.      */
  2252.     public boolean checkNoEntityCollision(AxisAlignedBB bb, @Nullable Entity entityIn)
  2253.     {
  2254.         List<Entity> list = this.getEntitiesWithinAABBExcludingEntity((Entity)null, bb);
  2255.  
  2256.         for (int j2 = 0; j2 < list.size(); ++j2)
  2257.         {
  2258.             Entity entity4 = list.get(j2);
  2259.  
  2260.             if (!entity4.isDead && entity4.preventEntitySpawning && entity4 != entityIn && (entityIn == null || !entity4.isRidingSameEntity(entityIn))) // Forge: fix MC-103516
  2261.             {
  2262.                 return false;
  2263.             }
  2264.         }
  2265.  
  2266.         return true;
  2267.     }
  2268.  
  2269.     /**
  2270.      * Returns true if there are any blocks in the region constrained by an AxisAlignedBB
  2271.      */
  2272.     public boolean checkBlockCollision(AxisAlignedBB bb)
  2273.     {
  2274.         int j2 = MathHelper.floor(bb.minX);
  2275.         int k2 = MathHelper.ceil(bb.maxX);
  2276.         int l2 = MathHelper.floor(bb.minY);
  2277.         int i3 = MathHelper.ceil(bb.maxY);
  2278.         int j3 = MathHelper.floor(bb.minZ);
  2279.         int k3 = MathHelper.ceil(bb.maxZ);
  2280.         BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  2281.  
  2282.         for (int l3 = j2; l3 < k2; ++l3)
  2283.         {
  2284.             for (int i4 = l2; i4 < i3; ++i4)
  2285.             {
  2286.                 for (int j4 = j3; j4 < k3; ++j4)
  2287.                 {
  2288.                     IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4));
  2289.  
  2290.                     if (iblockstate1.getMaterial() != Material.AIR)
  2291.                     {
  2292.                         blockpos$pooledmutableblockpos.release();
  2293.                         return true;
  2294.                     }
  2295.                 }
  2296.             }
  2297.         }
  2298.  
  2299.         blockpos$pooledmutableblockpos.release();
  2300.         return false;
  2301.     }
  2302.  
  2303.     /**
  2304.      * Checks if any of the blocks within the aabb are liquids.
  2305.      */
  2306.     public boolean containsAnyLiquid(AxisAlignedBB bb)
  2307.     {
  2308.         int j2 = MathHelper.floor(bb.minX);
  2309.         int k2 = MathHelper.ceil(bb.maxX);
  2310.         int l2 = MathHelper.floor(bb.minY);
  2311.         int i3 = MathHelper.ceil(bb.maxY);
  2312.         int j3 = MathHelper.floor(bb.minZ);
  2313.         int k3 = MathHelper.ceil(bb.maxZ);
  2314.         BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  2315.  
  2316.         for (int l3 = j2; l3 < k2; ++l3)
  2317.         {
  2318.             for (int i4 = l2; i4 < i3; ++i4)
  2319.             {
  2320.                 for (int j4 = j3; j4 < k3; ++j4)
  2321.                 {
  2322.                     IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4));
  2323.  
  2324.                     Boolean result = iblockstate1.getBlock().isAABBInsideLiquid(this, blockpos$pooledmutableblockpos, bb);
  2325.                     if (result != null) {
  2326.                         if (!result) continue;
  2327.                         blockpos$pooledmutableblockpos.release();
  2328.                         return true;
  2329.                     }
  2330.                     if (iblockstate1.getMaterial().isLiquid())
  2331.                     {
  2332.                         blockpos$pooledmutableblockpos.release();
  2333.                         return true;
  2334.                     }
  2335.                 }
  2336.             }
  2337.         }
  2338.  
  2339.         blockpos$pooledmutableblockpos.release();
  2340.         return false;
  2341.     }
  2342.  
  2343.     public boolean isFlammableWithin(AxisAlignedBB bb)
  2344.     {
  2345.         int j2 = MathHelper.floor(bb.minX);
  2346.         int k2 = MathHelper.ceil(bb.maxX);
  2347.         int l2 = MathHelper.floor(bb.minY);
  2348.         int i3 = MathHelper.ceil(bb.maxY);
  2349.         int j3 = MathHelper.floor(bb.minZ);
  2350.         int k3 = MathHelper.ceil(bb.maxZ);
  2351.  
  2352.         if (this.isAreaLoaded(j2, l2, j3, k2, i3, k3, true))
  2353.         {
  2354.             BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  2355.  
  2356.             for (int l3 = j2; l3 < k2; ++l3)
  2357.             {
  2358.                 for (int i4 = l2; i4 < i3; ++i4)
  2359.                 {
  2360.                     for (int j4 = j3; j4 < k3; ++j4)
  2361.                     {
  2362.                         Block block = this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4)).getBlock();
  2363.  
  2364.                         if (block == Blocks.FIRE || block == Blocks.FLOWING_LAVA || block == Blocks.LAVA)
  2365.                         {
  2366.                             blockpos$pooledmutableblockpos.release();
  2367.                             return true;
  2368.                         }
  2369.                         else if (block.isBurning(this, new BlockPos(l3, i4, j4)))
  2370.                         {
  2371.                             blockpos$pooledmutableblockpos.release();
  2372.                             return true;
  2373.                         }
  2374.                     }
  2375.                 }
  2376.             }
  2377.  
  2378.             blockpos$pooledmutableblockpos.release();
  2379.         }
  2380.  
  2381.         return false;
  2382.     }
  2383.  
  2384.     /**
  2385.      * handles the acceleration of an object whilst in water. Not sure if it is used elsewhere.
  2386.      */
  2387.     public boolean handleMaterialAcceleration(AxisAlignedBB bb, Material materialIn, Entity entityIn)
  2388.     {
  2389.         int j2 = MathHelper.floor(bb.minX);
  2390.         int k2 = MathHelper.ceil(bb.maxX);
  2391.         int l2 = MathHelper.floor(bb.minY);
  2392.         int i3 = MathHelper.ceil(bb.maxY);
  2393.         int j3 = MathHelper.floor(bb.minZ);
  2394.         int k3 = MathHelper.ceil(bb.maxZ);
  2395.  
  2396.         if (!this.isAreaLoaded(j2, l2, j3, k2, i3, k3, true))
  2397.         {
  2398.             return false;
  2399.         }
  2400.         else
  2401.         {
  2402.             boolean flag = false;
  2403.             Vec3d vec3d = Vec3d.ZERO;
  2404.             BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  2405.  
  2406.             for (int l3 = j2; l3 < k2; ++l3)
  2407.             {
  2408.                 for (int i4 = l2; i4 < i3; ++i4)
  2409.                 {
  2410.                     for (int j4 = j3; j4 < k3; ++j4)
  2411.                     {
  2412.                         blockpos$pooledmutableblockpos.setPos(l3, i4, j4);
  2413.                         IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos);
  2414.                         Block block = iblockstate1.getBlock();
  2415.  
  2416.                         Boolean result = block.isEntityInsideMaterial(this, blockpos$pooledmutableblockpos, iblockstate1, entityIn, (double)i3, materialIn, false);
  2417.                         if (result != null && result == true)
  2418.                         {
  2419.                             // Forge: When requested call blocks modifyAcceleration method, and more importantly cause this method to return true, which results in an entity being "inWater"
  2420.                             flag = true;
  2421.                             vec3d = block.modifyAcceleration(this, blockpos$pooledmutableblockpos, entityIn, vec3d);
  2422.                             continue;
  2423.                         }
  2424.                         else if (result != null && result == false) continue;
  2425.  
  2426.                         if (iblockstate1.getMaterial() == materialIn)
  2427.                         {
  2428.                             double d0 = (double)((float)(i4 + 1) - BlockLiquid.getLiquidHeightPercent(((Integer)iblockstate1.getValue(BlockLiquid.LEVEL)).intValue()));
  2429.  
  2430.                             if ((double)i3 >= d0)
  2431.                             {
  2432.                                 flag = true;
  2433.                                 vec3d = block.modifyAcceleration(this, blockpos$pooledmutableblockpos, entityIn, vec3d);
  2434.                             }
  2435.                         }
  2436.                     }
  2437.                 }
  2438.             }
  2439.  
  2440.             blockpos$pooledmutableblockpos.release();
  2441.  
  2442.             if (vec3d.lengthVector() > 0.0D && entityIn.isPushedByWater())
  2443.             {
  2444.                 vec3d = vec3d.normalize();
  2445.                 double d1 = 0.014D;
  2446.                 entityIn.motionX += vec3d.x * 0.014D;
  2447.                 entityIn.motionY += vec3d.y * 0.014D;
  2448.                 entityIn.motionZ += vec3d.z * 0.014D;
  2449.             }
  2450.  
  2451.             return flag;
  2452.         }
  2453.     }
  2454.  
  2455.     /**
  2456.      * Returns true if the given bounding box contains the given material
  2457.      */
  2458.     public boolean isMaterialInBB(AxisAlignedBB bb, Material materialIn)
  2459.     {
  2460.         int j2 = MathHelper.floor(bb.minX);
  2461.         int k2 = MathHelper.ceil(bb.maxX);
  2462.         int l2 = MathHelper.floor(bb.minY);
  2463.         int i3 = MathHelper.ceil(bb.maxY);
  2464.         int j3 = MathHelper.floor(bb.minZ);
  2465.         int k3 = MathHelper.ceil(bb.maxZ);
  2466.         BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  2467.  
  2468.         for (int l3 = j2; l3 < k2; ++l3)
  2469.         {
  2470.             for (int i4 = l2; i4 < i3; ++i4)
  2471.             {
  2472.                 for (int j4 = j3; j4 < k3; ++j4)
  2473.                 {
  2474.                     IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4));
  2475.                     Boolean result = iblockstate1.getBlock().isAABBInsideMaterial(this, blockpos$pooledmutableblockpos, bb, materialIn);
  2476.                     if (result != null) {
  2477.                         if (!result) continue;
  2478.                         blockpos$pooledmutableblockpos.release();
  2479.                         return true;
  2480.                     }
  2481.                     if (iblockstate1.getMaterial() == materialIn)
  2482.                     {
  2483.                         blockpos$pooledmutableblockpos.release();
  2484.                         return true;
  2485.                     }
  2486.                 }
  2487.             }
  2488.         }
  2489.  
  2490.         blockpos$pooledmutableblockpos.release();
  2491.         return false;
  2492.     }
  2493.  
  2494.     /**
  2495.      * Creates an explosion in the world.
  2496.      */
  2497.     public Explosion createExplosion(@Nullable Entity entityIn, double x, double y, double z, float strength, boolean isSmoking)
  2498.     {
  2499.         return this.newExplosion(entityIn, x, y, z, strength, false, isSmoking);
  2500.     }
  2501.  
  2502.     /**
  2503.      * returns a new explosion. Does initiation (at time of writing Explosion is not finished)
  2504.      */
  2505.     public Explosion newExplosion(@Nullable Entity entityIn, double x, double y, double z, float strength, boolean isFlaming, boolean isSmoking)
  2506.     {
  2507.         Explosion explosion = new Explosion(this, entityIn, x, y, z, strength, isFlaming, isSmoking);
  2508.         if (net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this, explosion)) return explosion;
  2509.         explosion.doExplosionA();
  2510.         explosion.doExplosionB(true);
  2511.         return explosion;
  2512.     }
  2513.  
  2514.     /**
  2515.      * Gets the percentage of real blocks within within a bounding box, along a specified vector.
  2516.      */
  2517.     public float getBlockDensity(Vec3d vec, AxisAlignedBB bb)
  2518.     {
  2519.         double d0 = 1.0D / ((bb.maxX - bb.minX) * 2.0D + 1.0D);
  2520.         double d1 = 1.0D / ((bb.maxY - bb.minY) * 2.0D + 1.0D);
  2521.         double d2 = 1.0D / ((bb.maxZ - bb.minZ) * 2.0D + 1.0D);
  2522.         double d3 = (1.0D - Math.floor(1.0D / d0) * d0) / 2.0D;
  2523.         double d4 = (1.0D - Math.floor(1.0D / d2) * d2) / 2.0D;
  2524.  
  2525.         if (d0 >= 0.0D && d1 >= 0.0D && d2 >= 0.0D)
  2526.         {
  2527.             int j2 = 0;
  2528.             int k2 = 0;
  2529.  
  2530.             for (float f = 0.0F; f <= 1.0F; f = (float)((double)f + d0))
  2531.             {
  2532.                 for (float f1 = 0.0F; f1 <= 1.0F; f1 = (float)((double)f1 + d1))
  2533.                 {
  2534.                     for (float f2 = 0.0F; f2 <= 1.0F; f2 = (float)((double)f2 + d2))
  2535.                     {
  2536.                         double d5 = bb.minX + (bb.maxX - bb.minX) * (double)f;
  2537.                         double d6 = bb.minY + (bb.maxY - bb.minY) * (double)f1;
  2538.                         double d7 = bb.minZ + (bb.maxZ - bb.minZ) * (double)f2;
  2539.  
  2540.                         if (this.rayTraceBlocks(new Vec3d(d5 + d3, d6, d7 + d4), vec) == null)
  2541.                         {
  2542.                             ++j2;
  2543.                         }
  2544.  
  2545.                         ++k2;
  2546.                     }
  2547.                 }
  2548.             }
  2549.  
  2550.             return (float)j2 / (float)k2;
  2551.         }
  2552.         else
  2553.         {
  2554.             return 0.0F;
  2555.         }
  2556.     }
  2557.  
  2558.     /**
  2559.      * Attempts to extinguish a fire
  2560.      */
  2561.     public boolean extinguishFire(@Nullable EntityPlayer player, BlockPos pos, EnumFacing side)
  2562.     {
  2563.         pos = pos.offset(side);
  2564.  
  2565.         if (this.getBlockState(pos).getBlock() == Blocks.FIRE)
  2566.         {
  2567.             this.playEvent(player, 1009, pos, 0);
  2568.             this.setBlockToAir(pos);
  2569.             return true;
  2570.         }
  2571.         else
  2572.         {
  2573.             return false;
  2574.         }
  2575.     }
  2576.  
  2577.     /**
  2578.      * This string is 'All: (number of loaded entities)' Viewable by press ing F3
  2579.      */
  2580.     @SideOnly(Side.CLIENT)
  2581.     public String getDebugLoadedEntities()
  2582.     {
  2583.         return "All: " + this.loadedEntityList.size();
  2584.     }
  2585.  
  2586.     /**
  2587.      * Returns the name of the current chunk provider, by calling chunkprovider.makeString()
  2588.      */
  2589.     @SideOnly(Side.CLIENT)
  2590.     public String getProviderName()
  2591.     {
  2592.         return this.chunkProvider.makeString();
  2593.     }
  2594.  
  2595.     @Nullable
  2596.     public TileEntity getTileEntity(BlockPos pos)
  2597.     {
  2598.         if (this.isOutsideBuildHeight(pos))
  2599.         {
  2600.             return null;
  2601.         }
  2602.         else
  2603.         {
  2604.             TileEntity tileentity2 = null;
  2605.  
  2606.             if (this.processingLoadedTiles)
  2607.             {
  2608.                 tileentity2 = this.getPendingTileEntityAt(pos);
  2609.             }
  2610.  
  2611.             if (tileentity2 == null)
  2612.             {
  2613.                 tileentity2 = this.getChunkFromBlockCoords(pos).getTileEntity(pos, Chunk.EnumCreateEntityType.IMMEDIATE);
  2614.             }
  2615.  
  2616.             if (tileentity2 == null)
  2617.             {
  2618.                 tileentity2 = this.getPendingTileEntityAt(pos);
  2619.             }
  2620.  
  2621.             return tileentity2;
  2622.         }
  2623.     }
  2624.  
  2625.     @Nullable
  2626.     private TileEntity getPendingTileEntityAt(BlockPos pos)
  2627.     {
  2628.         for (int j2 = 0; j2 < this.addedTileEntityList.size(); ++j2)
  2629.         {
  2630.             TileEntity tileentity2 = this.addedTileEntityList.get(j2);
  2631.  
  2632.             if (!tileentity2.isInvalid() && tileentity2.getPos().equals(pos))
  2633.             {
  2634.                 return tileentity2;
  2635.             }
  2636.         }
  2637.  
  2638.         return null;
  2639.     }
  2640.  
  2641.     public void setTileEntity(BlockPos pos, @Nullable TileEntity tileEntityIn)
  2642.     {
  2643.         pos = pos.toImmutable(); // Forge - prevent mutable BlockPos leaks
  2644.         if (!this.isOutsideBuildHeight(pos))
  2645.         {
  2646.             if (tileEntityIn != null && !tileEntityIn.isInvalid())
  2647.             {
  2648.                 if (this.processingLoadedTiles)
  2649.                 {
  2650.                     tileEntityIn.setPos(pos);
  2651.                     if (tileEntityIn.getWorld() != this)
  2652.                         tileEntityIn.setWorld(this); // Forge - set the world early as vanilla doesn't set it until next tick
  2653.                     Iterator<TileEntity> iterator1 = this.addedTileEntityList.iterator();
  2654.  
  2655.                     while (iterator1.hasNext())
  2656.                     {
  2657.                         TileEntity tileentity2 = iterator1.next();
  2658.  
  2659.                         if (tileentity2.getPos().equals(pos))
  2660.                         {
  2661.                             tileentity2.invalidate();
  2662.                             iterator1.remove();
  2663.                         }
  2664.                     }
  2665.  
  2666.                     this.addedTileEntityList.add(tileEntityIn);
  2667.                 }
  2668.                 else
  2669.                 {
  2670.                     Chunk chunk = this.getChunkFromBlockCoords(pos);
  2671.                     if (chunk != null) chunk.addTileEntity(pos, tileEntityIn);
  2672.                     this.addTileEntity(tileEntityIn);
  2673.                 }
  2674.             }
  2675.         }
  2676.     }
  2677.  
  2678.     public void removeTileEntity(BlockPos pos)
  2679.     {
  2680.         TileEntity tileentity2 = this.getTileEntity(pos);
  2681.  
  2682.         if (tileentity2 != null && this.processingLoadedTiles)
  2683.         {
  2684.             tileentity2.invalidate();
  2685.             this.addedTileEntityList.remove(tileentity2);
  2686.             if (!(tileentity2 instanceof ITickable)) //Forge: If they are not tickable they wont be removed in the update loop.
  2687.                 this.loadedTileEntityList.remove(tileentity2);
  2688.         }
  2689.         else
  2690.         {
  2691.             if (tileentity2 != null)
  2692.             {
  2693.                 this.addedTileEntityList.remove(tileentity2);
  2694.                 this.loadedTileEntityList.remove(tileentity2);
  2695.                 this.tickableTileEntities.remove(tileentity2);
  2696.             }
  2697.  
  2698.             this.getChunkFromBlockCoords(pos).removeTileEntity(pos);
  2699.         }
  2700.         this.updateComparatorOutputLevel(pos, getBlockState(pos).getBlock()); //Notify neighbors of changes
  2701.     }
  2702.  
  2703.     /**
  2704.      * Adds the specified TileEntity to the pending removal list.
  2705.      */
  2706.     public void markTileEntityForRemoval(TileEntity tileEntityIn)
  2707.     {
  2708.         this.tileEntitiesToBeRemoved.add(tileEntityIn);
  2709.     }
  2710.  
  2711.     public boolean isBlockFullCube(BlockPos pos)
  2712.     {
  2713.         AxisAlignedBB axisalignedbb = this.getBlockState(pos).getCollisionBoundingBox(this, pos);
  2714.         return axisalignedbb != Block.NULL_AABB && axisalignedbb.getAverageEdgeLength() >= 1.0D;
  2715.     }
  2716.  
  2717.     /**
  2718.      * Checks if a block's material is opaque, and that it takes up a full cube
  2719.      */
  2720.     public boolean isBlockNormalCube(BlockPos pos, boolean _default)
  2721.     {
  2722.         if (this.isOutsideBuildHeight(pos))
  2723.         {
  2724.             return false;
  2725.         }
  2726.         else
  2727.         {
  2728.             Chunk chunk1 = this.chunkProvider.getLoadedChunk(pos.getX() >> 4, pos.getZ() >> 4);
  2729.  
  2730.             if (chunk1 != null && !chunk1.isEmpty())
  2731.             {
  2732.                 IBlockState iblockstate1 = this.getBlockState(pos);
  2733.                 return iblockstate1.getBlock().isNormalCube(iblockstate1, this, pos);
  2734.             }
  2735.             else
  2736.             {
  2737.                 return _default;
  2738.             }
  2739.         }
  2740.     }
  2741.  
  2742.     /**
  2743.      * Called on construction of the World class to setup the initial skylight values
  2744.      */
  2745.     public void calculateInitialSkylight()
  2746.     {
  2747.         int j2 = this.calculateSkylightSubtracted(1.0F);
  2748.  
  2749.         if (j2 != this.skylightSubtracted)
  2750.         {
  2751.             this.skylightSubtracted = j2;
  2752.         }
  2753.     }
  2754.  
  2755.     /**
  2756.      * first boolean for hostile mobs and second for peaceful mobs
  2757.      */
  2758.     public void setAllowedSpawnTypes(boolean hostile, boolean peaceful)
  2759.     {
  2760.         this.spawnHostileMobs = hostile;
  2761.         this.spawnPeacefulMobs = peaceful;
  2762.         this.provider.setAllowedSpawnTypes(hostile, peaceful);
  2763.     }
  2764.  
  2765.     /**
  2766.      * Runs a single tick for the world
  2767.      */
  2768.     public void tick()
  2769.     {
  2770.         this.updateWeather();
  2771.     }
  2772.  
  2773.     /**
  2774.      * Called from World constructor to set rainingStrength and thunderingStrength
  2775.      */
  2776.     protected void calculateInitialWeather()
  2777.     {
  2778.         this.provider.calculateInitialWeather();
  2779.     }
  2780.  
  2781.     public void calculateInitialWeatherBody()
  2782.     {
  2783.         if (this.worldInfo.isRaining())
  2784.         {
  2785.             this.rainingStrength = 1.0F;
  2786.  
  2787.             if (this.worldInfo.isThundering())
  2788.             {
  2789.                 this.thunderingStrength = 1.0F;
  2790.             }
  2791.         }
  2792.     }
  2793.  
  2794.     /**
  2795.      * Updates all weather states.
  2796.      */
  2797.     protected void updateWeather()
  2798.     {
  2799.         this.provider.updateWeather();
  2800.     }
  2801.  
  2802.     public void updateWeatherBody()
  2803.     {
  2804.         if (this.provider.hasSkyLight())
  2805.         {
  2806.             if (!this.isRemote)
  2807.             {
  2808.                 boolean flag = this.getGameRules().getBoolean("doWeatherCycle");
  2809.  
  2810.                 if (flag)
  2811.                 {
  2812.                     int j2 = this.worldInfo.getCleanWeatherTime();
  2813.  
  2814.                     if (j2 > 0)
  2815.                     {
  2816.                         --j2;
  2817.                         this.worldInfo.setCleanWeatherTime(j2);
  2818.                         this.worldInfo.setThunderTime(this.worldInfo.isThundering() ? 1 : 2);
  2819.                         this.worldInfo.setRainTime(this.worldInfo.isRaining() ? 1 : 2);
  2820.                     }
  2821.  
  2822.                     int k2 = this.worldInfo.getThunderTime();
  2823.  
  2824.                     if (k2 <= 0)
  2825.                     {
  2826.                         if (this.worldInfo.isThundering())
  2827.                         {
  2828.                             this.worldInfo.setThunderTime(this.rand.nextInt(12000) + 3600);
  2829.                         }
  2830.                         else
  2831.                         {
  2832.                             this.worldInfo.setThunderTime(this.rand.nextInt(168000) + 12000);
  2833.                         }
  2834.                     }
  2835.                     else
  2836.                     {
  2837.                         --k2;
  2838.                         this.worldInfo.setThunderTime(k2);
  2839.  
  2840.                         if (k2 <= 0)
  2841.                         {
  2842.                             this.worldInfo.setThundering(!this.worldInfo.isThundering());
  2843.                         }
  2844.                     }
  2845.  
  2846.                     int l2 = this.worldInfo.getRainTime();
  2847.  
  2848.                     if (l2 <= 0)
  2849.                     {
  2850.                         if (this.worldInfo.isRaining())
  2851.                         {
  2852.                             this.worldInfo.setRainTime(this.rand.nextInt(12000) + 12000);
  2853.                         }
  2854.                         else
  2855.                         {
  2856.                             this.worldInfo.setRainTime(this.rand.nextInt(168000) + 12000);
  2857.                         }
  2858.                     }
  2859.                     else
  2860.                     {
  2861.                         --l2;
  2862.                         this.worldInfo.setRainTime(l2);
  2863.  
  2864.                         if (l2 <= 0)
  2865.                         {
  2866.                             this.worldInfo.setRaining(!this.worldInfo.isRaining());
  2867.                         }
  2868.                     }
  2869.                 }
  2870.  
  2871.                 this.prevThunderingStrength = this.thunderingStrength;
  2872.  
  2873.                 if (this.worldInfo.isThundering())
  2874.                 {
  2875.                     this.thunderingStrength = (float)((double)this.thunderingStrength + 0.01D);
  2876.                 }
  2877.                 else
  2878.                 {
  2879.                     this.thunderingStrength = (float)((double)this.thunderingStrength - 0.01D);
  2880.                 }
  2881.  
  2882.                 this.thunderingStrength = MathHelper.clamp(this.thunderingStrength, 0.0F, 1.0F);
  2883.                 this.prevRainingStrength = this.rainingStrength;
  2884.  
  2885.                 if (this.worldInfo.isRaining())
  2886.                 {
  2887.                     this.rainingStrength = (float)((double)this.rainingStrength + 0.01D);
  2888.                 }
  2889.                 else
  2890.                 {
  2891.                     this.rainingStrength = (float)((double)this.rainingStrength - 0.01D);
  2892.                 }
  2893.  
  2894.                 this.rainingStrength = MathHelper.clamp(this.rainingStrength, 0.0F, 1.0F);
  2895.             }
  2896.         }
  2897.     }
  2898.  
  2899.     @SideOnly(Side.CLIENT)
  2900.     protected void playMoodSoundAndCheckLight(int p_147467_1_, int p_147467_2_, Chunk chunkIn)
  2901.     {
  2902.         chunkIn.enqueueRelightChecks();
  2903.     }
  2904.  
  2905.     protected void updateBlocks()
  2906.     {
  2907.     }
  2908.  
  2909.     public void immediateBlockTick(BlockPos pos, IBlockState state, Random random)
  2910.     {
  2911.         this.scheduledUpdatesAreImmediate = true;
  2912.         state.getBlock().updateTick(this, pos, state, random);
  2913.         this.scheduledUpdatesAreImmediate = false;
  2914.     }
  2915.  
  2916.     public boolean canBlockFreezeWater(BlockPos pos)
  2917.     {
  2918.         return this.canBlockFreeze(pos, false);
  2919.     }
  2920.  
  2921.     public boolean canBlockFreezeNoWater(BlockPos pos)
  2922.     {
  2923.         return this.canBlockFreeze(pos, true);
  2924.     }
  2925.  
  2926.     /**
  2927.      * Checks to see if a given block is both water and cold enough to freeze.
  2928.      */
  2929.     public boolean canBlockFreeze(BlockPos pos, boolean noWaterAdj)
  2930.     {
  2931.         return this.provider.canBlockFreeze(pos, noWaterAdj);
  2932.     }
  2933.  
  2934.     public boolean canBlockFreezeBody(BlockPos pos, boolean noWaterAdj)
  2935.     {
  2936.         Biome biome = this.getBiome(pos);
  2937.         float f = biome.getTemperature(pos);
  2938.  
  2939.         if (f >= 0.15F)
  2940.         {
  2941.             return false;
  2942.         }
  2943.         else
  2944.         {
  2945.             if (pos.getY() >= 0 && pos.getY() < 256 && this.getLightFor(EnumSkyBlock.BLOCK, pos) < 10)
  2946.             {
  2947.                 IBlockState iblockstate1 = this.getBlockState(pos);
  2948.                 Block block = iblockstate1.getBlock();
  2949.  
  2950.                 if ((block == Blocks.WATER || block == Blocks.FLOWING_WATER) && ((Integer)iblockstate1.getValue(BlockLiquid.LEVEL)).intValue() == 0)
  2951.                 {
  2952.                     if (!noWaterAdj)
  2953.                     {
  2954.                         return true;
  2955.                     }
  2956.  
  2957.                     boolean flag = this.isWater(pos.west()) && this.isWater(pos.east()) && this.isWater(pos.north()) && this.isWater(pos.south());
  2958.  
  2959.                     if (!flag)
  2960.                     {
  2961.                         return true;
  2962.                     }
  2963.                 }
  2964.             }
  2965.  
  2966.             return false;
  2967.         }
  2968.     }
  2969.  
  2970.     private boolean isWater(BlockPos pos)
  2971.     {
  2972.         return this.getBlockState(pos).getMaterial() == Material.WATER;
  2973.     }
  2974.  
  2975.     /**
  2976.      * Checks to see if a given block can accumulate snow from it snowing
  2977.      */
  2978.     public boolean canSnowAt(BlockPos pos, boolean checkLight)
  2979.     {
  2980.         return this.provider.canSnowAt(pos, checkLight);
  2981.     }
  2982.  
  2983.     public boolean canSnowAtBody(BlockPos pos, boolean checkLight)
  2984.     {
  2985.         Biome biome = this.getBiome(pos);
  2986.         float f = biome.getTemperature(pos);
  2987.  
  2988.         if (f >= 0.15F)
  2989.         {
  2990.             return false;
  2991.         }
  2992.         else if (!checkLight)
  2993.         {
  2994.             return true;
  2995.         }
  2996.         else
  2997.         {
  2998.             if (pos.getY() >= 0 && pos.getY() < 256 && this.getLightFor(EnumSkyBlock.BLOCK, pos) < 10)
  2999.             {
  3000.                 IBlockState iblockstate1 = this.getBlockState(pos);
  3001.  
  3002.                 if (iblockstate1.getBlock().isAir(iblockstate1, this, pos) && Blocks.SNOW_LAYER.canPlaceBlockAt(this, pos))
  3003.                 {
  3004.                     return true;
  3005.                 }
  3006.             }
  3007.  
  3008.             return false;
  3009.         }
  3010.     }
  3011.  
  3012.     public boolean checkLight(BlockPos pos)
  3013.     {
  3014.         boolean flag = false;
  3015.  
  3016.         if (this.provider.hasSkyLight())
  3017.         {
  3018.             flag |= this.checkLightFor(EnumSkyBlock.SKY, pos);
  3019.         }
  3020.  
  3021.         flag = flag | this.checkLightFor(EnumSkyBlock.BLOCK, pos);
  3022.         return flag;
  3023.     }
  3024.  
  3025.     /**
  3026.      * gets the light level at the supplied position
  3027.      */
  3028.     private int getRawLight(BlockPos pos, EnumSkyBlock lightType)
  3029.     {
  3030.         if (lightType == EnumSkyBlock.SKY && this.canSeeSky(pos))
  3031.         {
  3032.             return 15;
  3033.         }
  3034.         else
  3035.         {
  3036.             IBlockState iblockstate1 = this.getBlockState(pos);
  3037.             int j2 = lightType == EnumSkyBlock.SKY ? 0 : iblockstate1.getBlock().getLightValue(iblockstate1, this, pos);
  3038.             int k2 = iblockstate1.getBlock().getLightOpacity(iblockstate1, this, pos);
  3039.  
  3040.             if (false) // Forge: fix MC-119932
  3041.             {
  3042.                 k2 = 1;
  3043.             }
  3044.  
  3045.             if (k2 < 1)
  3046.             {
  3047.                 k2 = 1;
  3048.             }
  3049.  
  3050.             if (k2 >= 15)
  3051.             {
  3052.                 return j2; // Forge: fix MC-119932
  3053.             }
  3054.             else if (j2 >= 14)
  3055.             {
  3056.                 return j2;
  3057.             }
  3058.             else
  3059.             {
  3060.                 BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  3061.  
  3062.                 try
  3063.                 {
  3064.                     for (EnumFacing enumfacing : EnumFacing.values())
  3065.                     {
  3066.                         blockpos$pooledmutableblockpos.setPos(pos).move(enumfacing);
  3067.                         int l2 = this.getLightFor(lightType, blockpos$pooledmutableblockpos) - k2;
  3068.  
  3069.                         if (l2 > j2)
  3070.                         {
  3071.                             j2 = l2;
  3072.                         }
  3073.  
  3074.                         if (j2 >= 14)
  3075.                         {
  3076.                             int i3 = j2;
  3077.                             return i3;
  3078.                         }
  3079.                     }
  3080.  
  3081.                     return j2;
  3082.                 }
  3083.                 finally
  3084.                 {
  3085.                     blockpos$pooledmutableblockpos.release();
  3086.                 }
  3087.             }
  3088.         }
  3089.     }
  3090.  
  3091.     public boolean checkLightFor(EnumSkyBlock lightType, BlockPos pos)
  3092.     {
  3093.         if (!this.isAreaLoaded(pos, 16, false))
  3094.         {
  3095.             return false;
  3096.         }
  3097.         else
  3098.         {
  3099.             int updateRange = this.isAreaLoaded(pos, 18, false) ? 17 : 15;
  3100.             int j2 = 0;
  3101.             int k2 = 0;
  3102.             this.profiler.startSection("getBrightness");
  3103.             int l2 = this.getLightFor(lightType, pos);
  3104.             int i3 = this.getRawLight(pos, lightType);
  3105.             int j3 = pos.getX();
  3106.             int k3 = pos.getY();
  3107.             int l3 = pos.getZ();
  3108.  
  3109.             if (i3 > l2)
  3110.             {
  3111.                 this.lightUpdateBlockList[k2++] = 133152;
  3112.             }
  3113.             else if (i3 < l2)
  3114.             {
  3115.                 this.lightUpdateBlockList[k2++] = 133152 | l2 << 18;
  3116.  
  3117.                 while (j2 < k2)
  3118.                 {
  3119.                     int i4 = this.lightUpdateBlockList[j2++];
  3120.                     int j4 = (i4 & 63) - 32 + j3;
  3121.                     int k4 = (i4 >> 6 & 63) - 32 + k3;
  3122.                     int l4 = (i4 >> 12 & 63) - 32 + l3;
  3123.                     int i5 = i4 >> 18 & 15;
  3124.                     BlockPos blockpos1 = new BlockPos(j4, k4, l4);
  3125.                     int j5 = this.getLightFor(lightType, blockpos1);
  3126.  
  3127.                     if (j5 == i5)
  3128.                     {
  3129.                         this.setLightFor(lightType, blockpos1, 0);
  3130.  
  3131.                         if (i5 > 0)
  3132.                         {
  3133.                             int k5 = MathHelper.abs(j4 - j3);
  3134.                             int l5 = MathHelper.abs(k4 - k3);
  3135.                             int i6 = MathHelper.abs(l4 - l3);
  3136.  
  3137.                             if (k5 + l5 + i6 < updateRange)
  3138.                             {
  3139.                                 BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
  3140.  
  3141.                                 for (EnumFacing enumfacing : EnumFacing.values())
  3142.                                 {
  3143.                                     int j6 = j4 + enumfacing.getFrontOffsetX();
  3144.                                     int k6 = k4 + enumfacing.getFrontOffsetY();
  3145.                                     int l6 = l4 + enumfacing.getFrontOffsetZ();
  3146.                                     blockpos$pooledmutableblockpos.setPos(j6, k6, l6);
  3147.                                     IBlockState bs = this.getBlockState(blockpos$pooledmutableblockpos);
  3148.                                     int i7 = Math.max(1, bs.getBlock().getLightOpacity(bs, this, blockpos$pooledmutableblockpos));
  3149.                                     j5 = this.getLightFor(lightType, blockpos$pooledmutableblockpos);
  3150.  
  3151.                                     if (j5 == i5 - i7 && k2 < this.lightUpdateBlockList.length)
  3152.                                     {
  3153.                                         this.lightUpdateBlockList[k2++] = j6 - j3 + 32 | k6 - k3 + 32 << 6 | l6 - l3 + 32 << 12 | i5 - i7 << 18;
  3154.                                     }
  3155.                                 }
  3156.  
  3157.                                 blockpos$pooledmutableblockpos.release();
  3158.                             }
  3159.                         }
  3160.                     }
  3161.                 }
  3162.  
  3163.                 j2 = 0;
  3164.             }
  3165.  
  3166.             this.profiler.endSection();
  3167.             this.profiler.startSection("checkedPosition < toCheckCount");
  3168.  
  3169.             while (j2 < k2)
  3170.             {
  3171.                 int j7 = this.lightUpdateBlockList[j2++];
  3172.                 int k7 = (j7 & 63) - 32 + j3;
  3173.                 int l7 = (j7 >> 6 & 63) - 32 + k3;
  3174.                 int i8 = (j7 >> 12 & 63) - 32 + l3;
  3175.                 BlockPos blockpos2 = new BlockPos(k7, l7, i8);
  3176.                 int j8 = this.getLightFor(lightType, blockpos2);
  3177.                 int k8 = this.getRawLight(blockpos2, lightType);
  3178.  
  3179.                 if (k8 != j8)
  3180.                 {
  3181.                     this.setLightFor(lightType, blockpos2, k8);
  3182.  
  3183.                     if (k8 > j8)
  3184.                     {
  3185.                         int l8 = Math.abs(k7 - j3);
  3186.                         int i9 = Math.abs(l7 - k3);
  3187.                         int j9 = Math.abs(i8 - l3);
  3188.                         boolean flag = k2 < this.lightUpdateBlockList.length - 6;
  3189.  
  3190.                         if (l8 + i9 + j9 < updateRange && flag)
  3191.                         {
  3192.                             if (this.getLightFor(lightType, blockpos2.west()) < k8)
  3193.                             {
  3194.                                 this.lightUpdateBlockList[k2++] = k7 - 1 - j3 + 32 + (l7 - k3 + 32 << 6) + (i8 - l3 + 32 << 12);
  3195.                             }
  3196.  
  3197.                             if (this.getLightFor(lightType, blockpos2.east()) < k8)
  3198.                             {
  3199.                                 this.lightUpdateBlockList[k2++] = k7 + 1 - j3 + 32 + (l7 - k3 + 32 << 6) + (i8 - l3 + 32 << 12);
  3200.                             }
  3201.  
  3202.                             if (this.getLightFor(lightType, blockpos2.down()) < k8)
  3203.                             {
  3204.                                 this.lightUpdateBlockList[k2++] = k7 - j3 + 32 + (l7 - 1 - k3 + 32 << 6) + (i8 - l3 + 32 << 12);
  3205.                             }
  3206.  
  3207.                             if (this.getLightFor(lightType, blockpos2.up()) < k8)
  3208.                             {
  3209.                                 this.lightUpdateBlockList[k2++] = k7 - j3 + 32 + (l7 + 1 - k3 + 32 << 6) + (i8 - l3 + 32 << 12);
  3210.                             }
  3211.  
  3212.                             if (this.getLightFor(lightType, blockpos2.north()) < k8)
  3213.                             {
  3214.                                 this.lightUpdateBlockList[k2++] = k7 - j3 + 32 + (l7 - k3 + 32 << 6) + (i8 - 1 - l3 + 32 << 12);
  3215.                             }
  3216.  
  3217.                             if (this.getLightFor(lightType, blockpos2.south()) < k8)
  3218.                             {
  3219.                                 this.lightUpdateBlockList[k2++] = k7 - j3 + 32 + (l7 - k3 + 32 << 6) + (i8 + 1 - l3 + 32 << 12);
  3220.                             }
  3221.                         }
  3222.                     }
  3223.                 }
  3224.             }
  3225.  
  3226.             this.profiler.endSection();
  3227.             return true;
  3228.         }
  3229.     }
  3230.  
  3231.     /**
  3232.      * Runs through the list of updates to run and ticks them
  3233.      */
  3234.     public boolean tickUpdates(boolean runAllPending)
  3235.     {
  3236.         return false;
  3237.     }
  3238.  
  3239.     @Nullable
  3240.     public List<NextTickListEntry> getPendingBlockUpdates(Chunk chunkIn, boolean remove)
  3241.     {
  3242.         return null;
  3243.     }
  3244.  
  3245.     @Nullable
  3246.     public List<NextTickListEntry> getPendingBlockUpdates(StructureBoundingBox structureBB, boolean remove)
  3247.     {
  3248.         return null;
  3249.     }
  3250.  
  3251.     /**
  3252.      * Will get all entities within the specified AABB excluding the one passed into it. Args: entityToExclude, aabb
  3253.      */
  3254.     public List<Entity> getEntitiesWithinAABBExcludingEntity(@Nullable Entity entityIn, AxisAlignedBB bb)
  3255.     {
  3256.         return this.getEntitiesInAABBexcluding(entityIn, bb, EntitySelectors.NOT_SPECTATING);
  3257.     }
  3258.  
  3259.     /**
  3260.      * Gets all entities within the specified AABB excluding the one passed into it.
  3261.      */
  3262.     public List<Entity> getEntitiesInAABBexcluding(@Nullable Entity entityIn, AxisAlignedBB boundingBox, @Nullable Predicate <? super Entity > predicate)
  3263.     {
  3264.         List<Entity> list = Lists.<Entity>newArrayList();
  3265.         int j2 = MathHelper.floor((boundingBox.minX - MAX_ENTITY_RADIUS) / 16.0D);
  3266.         int k2 = MathHelper.floor((boundingBox.maxX + MAX_ENTITY_RADIUS) / 16.0D);
  3267.         int l2 = MathHelper.floor((boundingBox.minZ - MAX_ENTITY_RADIUS) / 16.0D);
  3268.         int i3 = MathHelper.floor((boundingBox.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
  3269.  
  3270.         for (int j3 = j2; j3 <= k2; ++j3)
  3271.         {
  3272.             for (int k3 = l2; k3 <= i3; ++k3)
  3273.             {
  3274.                 if (this.isChunkLoaded(j3, k3, true))
  3275.                 {
  3276.                     this.getChunkFromChunkCoords(j3, k3).getEntitiesWithinAABBForEntity(entityIn, boundingBox, list, predicate);
  3277.                 }
  3278.             }
  3279.         }
  3280.  
  3281.         return list;
  3282.     }
  3283.  
  3284.     public <T extends Entity> List<T> getEntities(Class <? extends T > entityType, Predicate <? super T > filter)
  3285.     {
  3286.         List<T> list = Lists.<T>newArrayList();
  3287.  
  3288.         for (Entity entity4 : this.loadedEntityList)
  3289.         {
  3290.             if (entityType.isAssignableFrom(entity4.getClass()) && filter.apply((T)entity4))
  3291.             {
  3292.                 list.add((T)entity4);
  3293.             }
  3294.         }
  3295.  
  3296.         return list;
  3297.     }
  3298.  
  3299.     public <T extends Entity> List<T> getPlayers(Class <? extends T > playerType, Predicate <? super T > filter)
  3300.     {
  3301.         List<T> list = Lists.<T>newArrayList();
  3302.  
  3303.         for (Entity entity4 : this.playerEntities)
  3304.         {
  3305.             if (playerType.isAssignableFrom(entity4.getClass()) && filter.apply((T)entity4))
  3306.             {
  3307.                 list.add((T)entity4);
  3308.             }
  3309.         }
  3310.  
  3311.         return list;
  3312.     }
  3313.  
  3314.     /**
  3315.      * Gets all entities of the specified class type which intersect with the AABB.
  3316.      */
  3317.     public <T extends Entity> List<T> getEntitiesWithinAABB(Class <? extends T > classEntity, AxisAlignedBB bb)
  3318.     {
  3319.         return this.<T>getEntitiesWithinAABB(classEntity, bb, EntitySelectors.NOT_SPECTATING);
  3320.     }
  3321.  
  3322.     public <T extends Entity> List<T> getEntitiesWithinAABB(Class <? extends T > clazz, AxisAlignedBB aabb, @Nullable Predicate <? super T > filter)
  3323.     {
  3324.         int j2 = MathHelper.floor((aabb.minX - MAX_ENTITY_RADIUS) / 16.0D);
  3325.         int k2 = MathHelper.ceil((aabb.maxX + MAX_ENTITY_RADIUS) / 16.0D);
  3326.         int l2 = MathHelper.floor((aabb.minZ - MAX_ENTITY_RADIUS) / 16.0D);
  3327.         int i3 = MathHelper.ceil((aabb.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
  3328.         List<T> list = Lists.<T>newArrayList();
  3329.  
  3330.         for (int j3 = j2; j3 < k2; ++j3)
  3331.         {
  3332.             for (int k3 = l2; k3 < i3; ++k3)
  3333.             {
  3334.                 if (this.isChunkLoaded(j3, k3, true))
  3335.                 {
  3336.                     this.getChunkFromChunkCoords(j3, k3).getEntitiesOfTypeWithinAABB(clazz, aabb, list, filter);
  3337.                 }
  3338.             }
  3339.         }
  3340.  
  3341.         return list;
  3342.     }
  3343.  
  3344.     @Nullable
  3345.     public <T extends Entity> T findNearestEntityWithinAABB(Class <? extends T > entityType, AxisAlignedBB aabb, T closestTo)
  3346.     {
  3347.         List<T> list = this.<T>getEntitiesWithinAABB(entityType, aabb);
  3348.         T t = null;
  3349.         double d0 = Double.MAX_VALUE;
  3350.  
  3351.         for (int j2 = 0; j2 < list.size(); ++j2)
  3352.         {
  3353.             T t1 = list.get(j2);
  3354.  
  3355.             if (t1 != closestTo && EntitySelectors.NOT_SPECTATING.apply(t1))
  3356.             {
  3357.                 double d1 = closestTo.getDistanceSq(t1);
  3358.  
  3359.                 if (d1 <= d0)
  3360.                 {
  3361.                     t = t1;
  3362.                     d0 = d1;
  3363.                 }
  3364.             }
  3365.         }
  3366.  
  3367.         return t;
  3368.     }
  3369.  
  3370.     /**
  3371.      * Returns the Entity with the given ID, or null if it doesn't exist in this World.
  3372.      */
  3373.     @Nullable
  3374.     public Entity getEntityByID(int id)
  3375.     {
  3376.         return this.entitiesById.lookup(id);
  3377.     }
  3378.  
  3379.     /**
  3380.      * Accessor for world Loaded Entity List
  3381.      */
  3382.     @SideOnly(Side.CLIENT)
  3383.     public List<Entity> getLoadedEntityList()
  3384.     {
  3385.         return this.loadedEntityList;
  3386.     }
  3387.  
  3388.     public void markChunkDirty(BlockPos pos, TileEntity unusedTileEntity)
  3389.     {
  3390.         if (this.isBlockLoaded(pos))
  3391.         {
  3392.             this.getChunkFromBlockCoords(pos).markDirty();
  3393.         }
  3394.     }
  3395.  
  3396.     /**
  3397.      * Counts how many entities of an entity class exist in the world.
  3398.      */
  3399.     public int countEntities(Class<?> entityType)
  3400.     {
  3401.         int j2 = 0;
  3402.  
  3403.         for (Entity entity4 : this.loadedEntityList)
  3404.         {
  3405.             if ((!(entity4 instanceof EntityLiving) || !((EntityLiving)entity4).isNoDespawnRequired()) && entityType.isAssignableFrom(entity4.getClass()))
  3406.             {
  3407.                 ++j2;
  3408.             }
  3409.         }
  3410.  
  3411.         return j2;
  3412.     }
  3413.  
  3414.     public void loadEntities(Collection<Entity> entityCollection)
  3415.     {
  3416.         for (Entity entity4 : entityCollection)
  3417.         {
  3418.             if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entity4, this)))
  3419.             {
  3420.                 loadedEntityList.add(entity4);
  3421.                 this.onEntityAdded(entity4);
  3422.             }
  3423.         }
  3424.     }
  3425.  
  3426.     public void unloadEntities(Collection<Entity> entityCollection)
  3427.     {
  3428.         this.unloadedEntityList.addAll(entityCollection);
  3429.     }
  3430.  
  3431.     /**
  3432.      * Checks if the given block can be set at {@code pos}. {@code sidePlacedOn} is the side of the backing block that
  3433.      * was clicked on to trigger this placement.
  3434.      */
  3435.     public boolean mayPlace(Block blockIn, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
  3436.     {
  3437.         IBlockState iblockstate1 = this.getBlockState(pos);
  3438.         AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(this, pos);
  3439.  
  3440.         if (axisalignedbb != Block.NULL_AABB && !this.checkNoEntityCollision(axisalignedbb.offset(pos), placer))
  3441.         {
  3442.             return false;
  3443.         }
  3444.         else if (iblockstate1.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL)
  3445.         {
  3446.             return true;
  3447.         }
  3448.         else
  3449.         {
  3450.             return iblockstate1.getBlock().isReplaceable(this, pos) && blockIn.canPlaceBlockOnSide(this, pos, sidePlacedOn);
  3451.         }
  3452.     }
  3453.  
  3454.     public int getSeaLevel()
  3455.     {
  3456.         return this.seaLevel;
  3457.     }
  3458.  
  3459.     /**
  3460.      * Warning this value may not be respected in all cases as it is still hardcoded in many places.
  3461.      */
  3462.     public void setSeaLevel(int seaLevelIn)
  3463.     {
  3464.         this.seaLevel = seaLevelIn;
  3465.     }
  3466.  
  3467.     public int getStrongPower(BlockPos pos, EnumFacing direction)
  3468.     {
  3469.         return this.getBlockState(pos).getStrongPower(this, pos, direction);
  3470.     }
  3471.  
  3472.     public WorldType getWorldType()
  3473.     {
  3474.         return this.worldInfo.getTerrainType();
  3475.     }
  3476.  
  3477.     /**
  3478.      * Returns the single highest strong power out of all directions using getStrongPower(BlockPos, EnumFacing)
  3479.      */
  3480.     public int getStrongPower(BlockPos pos)
  3481.     {
  3482.         int j2 = 0;
  3483.         j2 = Math.max(j2, this.getStrongPower(pos.down(), EnumFacing.DOWN));
  3484.  
  3485.         if (j2 >= 15)
  3486.         {
  3487.             return j2;
  3488.         }
  3489.         else
  3490.         {
  3491.             j2 = Math.max(j2, this.getStrongPower(pos.up(), EnumFacing.UP));
  3492.  
  3493.             if (j2 >= 15)
  3494.             {
  3495.                 return j2;
  3496.             }
  3497.             else
  3498.             {
  3499.                 j2 = Math.max(j2, this.getStrongPower(pos.north(), EnumFacing.NORTH));
  3500.  
  3501.                 if (j2 >= 15)
  3502.                 {
  3503.                     return j2;
  3504.                 }
  3505.                 else
  3506.                 {
  3507.                     j2 = Math.max(j2, this.getStrongPower(pos.south(), EnumFacing.SOUTH));
  3508.  
  3509.                     if (j2 >= 15)
  3510.                     {
  3511.                         return j2;
  3512.                     }
  3513.                     else
  3514.                     {
  3515.                         j2 = Math.max(j2, this.getStrongPower(pos.west(), EnumFacing.WEST));
  3516.  
  3517.                         if (j2 >= 15)
  3518.                         {
  3519.                             return j2;
  3520.                         }
  3521.                         else
  3522.                         {
  3523.                             j2 = Math.max(j2, this.getStrongPower(pos.east(), EnumFacing.EAST));
  3524.                             return j2 >= 15 ? j2 : j2;
  3525.                         }
  3526.                     }
  3527.                 }
  3528.             }
  3529.         }
  3530.     }
  3531.  
  3532.     public boolean isSidePowered(BlockPos pos, EnumFacing side)
  3533.     {
  3534.         return this.getRedstonePower(pos, side) > 0;
  3535.     }
  3536.  
  3537.     public int getRedstonePower(BlockPos pos, EnumFacing facing)
  3538.     {
  3539.         IBlockState iblockstate1 = this.getBlockState(pos);
  3540.         return iblockstate1.getBlock().shouldCheckWeakPower(iblockstate1, this, pos, facing) ? this.getStrongPower(pos) : iblockstate1.getWeakPower(this, pos, facing);
  3541.     }
  3542.  
  3543.     public boolean isBlockPowered(BlockPos pos)
  3544.     {
  3545.         if (this.getRedstonePower(pos.down(), EnumFacing.DOWN) > 0)
  3546.         {
  3547.             return true;
  3548.         }
  3549.         else if (this.getRedstonePower(pos.up(), EnumFacing.UP) > 0)
  3550.         {
  3551.             return true;
  3552.         }
  3553.         else if (this.getRedstonePower(pos.north(), EnumFacing.NORTH) > 0)
  3554.         {
  3555.             return true;
  3556.         }
  3557.         else if (this.getRedstonePower(pos.south(), EnumFacing.SOUTH) > 0)
  3558.         {
  3559.             return true;
  3560.         }
  3561.         else if (this.getRedstonePower(pos.west(), EnumFacing.WEST) > 0)
  3562.         {
  3563.             return true;
  3564.         }
  3565.         else
  3566.         {
  3567.             return this.getRedstonePower(pos.east(), EnumFacing.EAST) > 0;
  3568.         }
  3569.     }
  3570.  
  3571.     /**
  3572.      * Checks if the specified block or its neighbors are powered by a neighboring block. Used by blocks like TNT and
  3573.      * Doors.
  3574.      */
  3575.     public int isBlockIndirectlyGettingPowered(BlockPos pos)
  3576.     {
  3577.         int j2 = 0;
  3578.  
  3579.         for (EnumFacing enumfacing : EnumFacing.values())
  3580.         {
  3581.             int k2 = this.getRedstonePower(pos.offset(enumfacing), enumfacing);
  3582.  
  3583.             if (k2 >= 15)
  3584.             {
  3585.                 return 15;
  3586.             }
  3587.  
  3588.             if (k2 > j2)
  3589.             {
  3590.                 j2 = k2;
  3591.             }
  3592.         }
  3593.  
  3594.         return j2;
  3595.     }
  3596.  
  3597.     /**
  3598.      * Gets the closest player to the entity within the specified distance.
  3599.      */
  3600.     @Nullable
  3601.     public EntityPlayer getClosestPlayerToEntity(Entity entityIn, double distance)
  3602.     {
  3603.         return this.getClosestPlayer(entityIn.posX, entityIn.posY, entityIn.posZ, distance, false);
  3604.     }
  3605.  
  3606.     @Nullable
  3607.     public EntityPlayer getNearestPlayerNotCreative(Entity entityIn, double distance)
  3608.     {
  3609.         return this.getClosestPlayer(entityIn.posX, entityIn.posY, entityIn.posZ, distance, true);
  3610.     }
  3611.  
  3612.     @Nullable
  3613.     public EntityPlayer getClosestPlayer(double posX, double posY, double posZ, double distance, boolean spectator)
  3614.     {
  3615.         Predicate<Entity> predicate = spectator ? EntitySelectors.CAN_AI_TARGET : EntitySelectors.NOT_SPECTATING;
  3616.         return this.getClosestPlayer(posX, posY, posZ, distance, predicate);
  3617.     }
  3618.  
  3619.     @Nullable
  3620.     public EntityPlayer getClosestPlayer(double x, double y, double z, double p_190525_7_, Predicate<Entity> p_190525_9_)
  3621.     {
  3622.         double d0 = -1.0D;
  3623.         EntityPlayer entityplayer = null;
  3624.  
  3625.         for (int j2 = 0; j2 < this.playerEntities.size(); ++j2)
  3626.         {
  3627.             EntityPlayer entityplayer1 = this.playerEntities.get(j2);
  3628.  
  3629.             if (p_190525_9_.apply(entityplayer1))
  3630.             {
  3631.                 double d1 = entityplayer1.getDistanceSq(x, y, z);
  3632.  
  3633.                 if ((p_190525_7_ < 0.0D || d1 < p_190525_7_ * p_190525_7_) && (d0 == -1.0D || d1 < d0))
  3634.                 {
  3635.                     d0 = d1;
  3636.                     entityplayer = entityplayer1;
  3637.                 }
  3638.             }
  3639.         }
  3640.  
  3641.         return entityplayer;
  3642.     }
  3643.  
  3644.     public boolean isAnyPlayerWithinRangeAt(double x, double y, double z, double range)
  3645.     {
  3646.         for (int j2 = 0; j2 < this.playerEntities.size(); ++j2)
  3647.         {
  3648.             EntityPlayer entityplayer = this.playerEntities.get(j2);
  3649.  
  3650.             if (EntitySelectors.NOT_SPECTATING.apply(entityplayer))
  3651.             {
  3652.                 double d0 = entityplayer.getDistanceSq(x, y, z);
  3653.  
  3654.                 if (range < 0.0D || d0 < range * range)
  3655.                 {
  3656.                     return true;
  3657.                 }
  3658.             }
  3659.         }
  3660.  
  3661.         return false;
  3662.     }
  3663.  
  3664.     @Nullable
  3665.     public EntityPlayer getNearestAttackablePlayer(Entity entityIn, double maxXZDistance, double maxYDistance)
  3666.     {
  3667.         return this.getNearestAttackablePlayer(entityIn.posX, entityIn.posY, entityIn.posZ, maxXZDistance, maxYDistance, (Function)null, (Predicate)null);
  3668.     }
  3669.  
  3670.     @Nullable
  3671.     public EntityPlayer getNearestAttackablePlayer(BlockPos pos, double maxXZDistance, double maxYDistance)
  3672.     {
  3673.         return this.getNearestAttackablePlayer((double)((float)pos.getX() + 0.5F), (double)((float)pos.getY() + 0.5F), (double)((float)pos.getZ() + 0.5F), maxXZDistance, maxYDistance, (Function)null, (Predicate)null);
  3674.     }
  3675.  
  3676.     @Nullable
  3677.     public EntityPlayer getNearestAttackablePlayer(double posX, double posY, double posZ, double maxXZDistance, double maxYDistance, @Nullable Function<EntityPlayer, Double> playerToDouble, @Nullable Predicate<EntityPlayer> p_184150_12_)
  3678.     {
  3679.         double d0 = -1.0D;
  3680.         EntityPlayer entityplayer = null;
  3681.  
  3682.         for (int j2 = 0; j2 < this.playerEntities.size(); ++j2)
  3683.         {
  3684.             EntityPlayer entityplayer1 = this.playerEntities.get(j2);
  3685.  
  3686.             if (!entityplayer1.capabilities.disableDamage && entityplayer1.isEntityAlive() && !entityplayer1.isSpectator() && (p_184150_12_ == null || p_184150_12_.apply(entityplayer1)))
  3687.             {
  3688.                 double d1 = entityplayer1.getDistanceSq(posX, entityplayer1.posY, posZ);
  3689.                 double d2 = maxXZDistance;
  3690.  
  3691.                 if (entityplayer1.isSneaking())
  3692.                 {
  3693.                     d2 = maxXZDistance * 0.800000011920929D;
  3694.                 }
  3695.  
  3696.                 if (entityplayer1.isInvisible())
  3697.                 {
  3698.                     float f = entityplayer1.getArmorVisibility();
  3699.  
  3700.                     if (f < 0.1F)
  3701.                     {
  3702.                         f = 0.1F;
  3703.                     }
  3704.  
  3705.                     d2 *= (double)(0.7F * f);
  3706.                 }
  3707.  
  3708.                 if (playerToDouble != null)
  3709.                 {
  3710.                     d2 *= ((Double)MoreObjects.firstNonNull(playerToDouble.apply(entityplayer1), Double.valueOf(1.0D))).doubleValue();
  3711.                 }
  3712.  
  3713.                 d2 = net.minecraftforge.common.ForgeHooks.getPlayerVisibilityDistance(entityplayer1, d2, maxYDistance);
  3714.  
  3715.                 if ((maxYDistance < 0.0D || Math.abs(entityplayer1.posY - posY) < maxYDistance * maxYDistance) && (maxXZDistance < 0.0D || d1 < d2 * d2) && (d0 == -1.0D || d1 < d0))
  3716.                 {
  3717.                     d0 = d1;
  3718.                     entityplayer = entityplayer1;
  3719.                 }
  3720.             }
  3721.         }
  3722.  
  3723.         return entityplayer;
  3724.     }
  3725.  
  3726.     /**
  3727.      * Find a player by name in this world.
  3728.      */
  3729.     @Nullable
  3730.     public EntityPlayer getPlayerEntityByName(String name)
  3731.     {
  3732.         for (int j2 = 0; j2 < this.playerEntities.size(); ++j2)
  3733.         {
  3734.             EntityPlayer entityplayer = this.playerEntities.get(j2);
  3735.  
  3736.             if (name.equals(entityplayer.getName()))
  3737.             {
  3738.                 return entityplayer;
  3739.             }
  3740.         }
  3741.  
  3742.         return null;
  3743.     }
  3744.  
  3745.     @Nullable
  3746.     public EntityPlayer getPlayerEntityByUUID(UUID uuid)
  3747.     {
  3748.         for (int j2 = 0; j2 < this.playerEntities.size(); ++j2)
  3749.         {
  3750.             EntityPlayer entityplayer = this.playerEntities.get(j2);
  3751.  
  3752.             if (uuid.equals(entityplayer.getUniqueID()))
  3753.             {
  3754.                 return entityplayer;
  3755.             }
  3756.         }
  3757.  
  3758.         return null;
  3759.     }
  3760.  
  3761.     /**
  3762.      * If on MP, sends a quitting packet.
  3763.      */
  3764.     @SideOnly(Side.CLIENT)
  3765.     public void sendQuittingDisconnectingPacket()
  3766.     {
  3767.     }
  3768.  
  3769.     /**
  3770.      * Checks whether the session lock file was modified by another process
  3771.      */
  3772.     public void checkSessionLock() throws MinecraftException
  3773.     {
  3774.         this.saveHandler.checkSessionLock();
  3775.     }
  3776.  
  3777.     @SideOnly(Side.CLIENT)
  3778.     public void setTotalWorldTime(long worldTime)
  3779.     {
  3780.         this.worldInfo.setWorldTotalTime(worldTime);
  3781.     }
  3782.  
  3783.     /**
  3784.      * gets the random world seed
  3785.      */
  3786.     public long getSeed()
  3787.     {
  3788.         return this.provider.getSeed();
  3789.     }
  3790.  
  3791.     public long getTotalWorldTime()
  3792.     {
  3793.         return this.worldInfo.getWorldTotalTime();
  3794.     }
  3795.  
  3796.     public long getWorldTime()
  3797.     {
  3798.         return this.provider.getWorldTime();
  3799.     }
  3800.  
  3801.     /**
  3802.      * Sets the world time.
  3803.      */
  3804.     public void setWorldTime(long time)
  3805.     {
  3806.         this.provider.setWorldTime(time);
  3807.     }
  3808.  
  3809.     /**
  3810.      * Gets the spawn point in the world
  3811.      */
  3812.     public BlockPos getSpawnPoint()
  3813.     {
  3814.         BlockPos blockpos1 = this.provider.getSpawnPoint();
  3815.  
  3816.         if (!this.getWorldBorder().contains(blockpos1))
  3817.         {
  3818.             blockpos1 = this.getHeight(new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ()));
  3819.         }
  3820.  
  3821.         return blockpos1;
  3822.     }
  3823.  
  3824.     public void setSpawnPoint(BlockPos pos)
  3825.     {
  3826.         this.provider.setSpawnPoint(pos);
  3827.     }
  3828.  
  3829.     /**
  3830.      * spwans an entity and loads surrounding chunks
  3831.      */
  3832.     @SideOnly(Side.CLIENT)
  3833.     public void joinEntityInSurroundings(Entity entityIn)
  3834.     {
  3835.         int j2 = MathHelper.floor(entityIn.posX / 16.0D);
  3836.         int k2 = MathHelper.floor(entityIn.posZ / 16.0D);
  3837.         int l2 = 2;
  3838.  
  3839.         for (int i3 = -2; i3 <= 2; ++i3)
  3840.         {
  3841.             for (int j3 = -2; j3 <= 2; ++j3)
  3842.             {
  3843.                 this.getChunkFromChunkCoords(j2 + i3, k2 + j3);
  3844.             }
  3845.         }
  3846.  
  3847.         if (!this.loadedEntityList.contains(entityIn))
  3848.         {
  3849.             if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entityIn, this)))
  3850.             this.loadedEntityList.add(entityIn);
  3851.         }
  3852.     }
  3853.  
  3854.     public boolean isBlockModifiable(EntityPlayer player, BlockPos pos)
  3855.     {
  3856.         return this.provider.canMineBlock(player, pos);
  3857.     }
  3858.  
  3859.     public boolean canMineBlockBody(EntityPlayer player, BlockPos pos)
  3860.     {
  3861.         return true;
  3862.     }
  3863.  
  3864.     /**
  3865.      * sends a Packet 38 (Entity Status) to all tracked players of that entity
  3866.      */
  3867.     public void setEntityState(Entity entityIn, byte state)
  3868.     {
  3869.     }
  3870.  
  3871.     /**
  3872.      * gets the world's chunk provider
  3873.      */
  3874.     public IChunkProvider getChunkProvider()
  3875.     {
  3876.         return this.chunkProvider;
  3877.     }
  3878.  
  3879.     public void addBlockEvent(BlockPos pos, Block blockIn, int eventID, int eventParam)
  3880.     {
  3881.         this.getBlockState(pos).onBlockEventReceived(this, pos, eventID, eventParam);
  3882.     }
  3883.  
  3884.     /**
  3885.      * Returns this world's current save handler
  3886.      */
  3887.     public ISaveHandler getSaveHandler()
  3888.     {
  3889.         return this.saveHandler;
  3890.     }
  3891.  
  3892.     /**
  3893.      * Returns the world's WorldInfo object
  3894.      */
  3895.     public WorldInfo getWorldInfo()
  3896.     {
  3897.         return this.worldInfo;
  3898.     }
  3899.  
  3900.     /**
  3901.      * Gets the GameRules instance.
  3902.      */
  3903.     public GameRules getGameRules()
  3904.     {
  3905.         return this.worldInfo.getGameRulesInstance();
  3906.     }
  3907.  
  3908.     /**
  3909.      * Updates the flag that indicates whether or not all players in the world are sleeping.
  3910.      */
  3911.     public void updateAllPlayersSleepingFlag()
  3912.     {
  3913.     }
  3914.  
  3915.     public float getThunderStrength(float delta)
  3916.     {
  3917.         return (this.prevThunderingStrength + (this.thunderingStrength - this.prevThunderingStrength) * delta) * this.getRainStrength(delta);
  3918.     }
  3919.  
  3920.     /**
  3921.      * Sets the strength of the thunder.
  3922.      */
  3923.     @SideOnly(Side.CLIENT)
  3924.     public void setThunderStrength(float strength)
  3925.     {
  3926.         this.prevThunderingStrength = strength;
  3927.         this.thunderingStrength = strength;
  3928.     }
  3929.  
  3930.     /**
  3931.      * Returns rain strength.
  3932.      */
  3933.     public float getRainStrength(float delta)
  3934.     {
  3935.         return this.prevRainingStrength + (this.rainingStrength - this.prevRainingStrength) * delta;
  3936.     }
  3937.  
  3938.     /**
  3939.      * Sets the strength of the rain.
  3940.      */
  3941.     @SideOnly(Side.CLIENT)
  3942.     public void setRainStrength(float strength)
  3943.     {
  3944.         this.prevRainingStrength = strength;
  3945.         this.rainingStrength = strength;
  3946.     }
  3947.  
  3948.     /**
  3949.      * Returns true if the current thunder strength (weighted with the rain strength) is greater than 0.9
  3950.      */
  3951.     public boolean isThundering()
  3952.     {
  3953.         return (double)this.getThunderStrength(1.0F) > 0.9D;
  3954.     }
  3955.  
  3956.     /**
  3957.      * Returns true if the current rain strength is greater than 0.2
  3958.      */
  3959.     public boolean isRaining()
  3960.     {
  3961.         return (double)this.getRainStrength(1.0F) > 0.2D;
  3962.     }
  3963.  
  3964.     /**
  3965.      * Check if precipitation is currently happening at a position
  3966.      */
  3967.     public boolean isRainingAt(BlockPos position)
  3968.     {
  3969.         if (!this.isRaining())
  3970.         {
  3971.             return false;
  3972.         }
  3973.         else if (!this.canSeeSky(position))
  3974.         {
  3975.             return false;
  3976.         }
  3977.         else if (this.getPrecipitationHeight(position).getY() > position.getY())
  3978.         {
  3979.             return false;
  3980.         }
  3981.         else
  3982.         {
  3983.             Biome biome = this.getBiome(position);
  3984.  
  3985.             if (biome.getEnableSnow())
  3986.             {
  3987.                 return false;
  3988.             }
  3989.             else
  3990.             {
  3991.                 return this.canSnowAt(position, false) ? false : biome.canRain();
  3992.             }
  3993.         }
  3994.     }
  3995.  
  3996.     public boolean isBlockinHighHumidity(BlockPos pos)
  3997.     {
  3998.         return this.provider.isBlockHighHumidity(pos);
  3999.     }
  4000.  
  4001.     @Nullable
  4002.     public MapStorage getMapStorage()
  4003.     {
  4004.         return this.mapStorage;
  4005.     }
  4006.  
  4007.     /**
  4008.      * Assigns the given String id to the given MapDataBase using the MapStorage, removing any existing ones of the same
  4009.      * id.
  4010.      */
  4011.     public void setData(String dataID, WorldSavedData worldSavedDataIn)
  4012.     {
  4013.         this.mapStorage.setData(dataID, worldSavedDataIn);
  4014.     }
  4015.  
  4016.     /**
  4017.      * Loads an existing MapDataBase corresponding to the given String id from disk using the MapStorage, instantiating
  4018.      * the given Class, or returns null if none such file exists.
  4019.      */
  4020.     @Nullable
  4021.     public WorldSavedData loadData(Class <? extends WorldSavedData > clazz, String dataID)
  4022.     {
  4023.         return this.mapStorage.getOrLoadData(clazz, dataID);
  4024.     }
  4025.  
  4026.     /**
  4027.      * Returns an unique new data id from the MapStorage for the given prefix and saves the idCounts map to the
  4028.      * 'idcounts' file.
  4029.      */
  4030.     public int getUniqueDataId(String key)
  4031.     {
  4032.         return this.mapStorage.getUniqueDataId(key);
  4033.     }
  4034.  
  4035.     public void playBroadcastSound(int id, BlockPos pos, int data)
  4036.     {
  4037.         for (int j2 = 0; j2 < this.eventListeners.size(); ++j2)
  4038.         {
  4039.             ((IWorldEventListener)this.eventListeners.get(j2)).broadcastSound(id, pos, data);
  4040.         }
  4041.     }
  4042.  
  4043.     public void playEvent(int type, BlockPos pos, int data)
  4044.     {
  4045.         this.playEvent((EntityPlayer)null, type, pos, data);
  4046.     }
  4047.  
  4048.     public void playEvent(@Nullable EntityPlayer player, int type, BlockPos pos, int data)
  4049.     {
  4050.         try
  4051.         {
  4052.             for (int j2 = 0; j2 < this.eventListeners.size(); ++j2)
  4053.             {
  4054.                 ((IWorldEventListener)this.eventListeners.get(j2)).playEvent(player, type, pos, data);
  4055.             }
  4056.         }
  4057.         catch (Throwable throwable3)
  4058.         {
  4059.             CrashReport crashreport3 = CrashReport.makeCrashReport(throwable3, "Playing level event");
  4060.             CrashReportCategory crashreportcategory3 = crashreport3.makeCategory("Level event being played");
  4061.             crashreportcategory3.addCrashSection("Block coordinates", CrashReportCategory.getCoordinateInfo(pos));
  4062.             crashreportcategory3.addCrashSection("Event source", player);
  4063.             crashreportcategory3.addCrashSection("Event type", Integer.valueOf(type));
  4064.             crashreportcategory3.addCrashSection("Event data", Integer.valueOf(data));
  4065.             throw new ReportedException(crashreport3);
  4066.         }
  4067.     }
  4068.  
  4069.     /**
  4070.      * Returns maximum world height.
  4071.      */
  4072.     public int getHeight()
  4073.     {
  4074.         return this.provider.getHeight();
  4075.     }
  4076.  
  4077.     /**
  4078.      * Returns current world height.
  4079.      */
  4080.     public int getActualHeight()
  4081.     {
  4082.         return this.provider.getActualHeight();
  4083.     }
  4084.  
  4085.     /**
  4086.      * puts the World Random seed to a specific state dependant on the inputs
  4087.      */
  4088.     public Random setRandomSeed(int p_72843_1_, int p_72843_2_, int p_72843_3_)
  4089.     {
  4090.         long j2 = (long)p_72843_1_ * 341873128712L + (long)p_72843_2_ * 132897987541L + this.getWorldInfo().getSeed() + (long)p_72843_3_;
  4091.         this.rand.setSeed(j2);
  4092.         return this.rand;
  4093.     }
  4094.  
  4095.     /**
  4096.      * Adds some basic stats of the world to the given crash report.
  4097.      */
  4098.     public CrashReportCategory addWorldInfoToCrashReport(CrashReport report)
  4099.     {
  4100.         CrashReportCategory crashreportcategory3 = report.makeCategoryDepth("Affected level", 1);
  4101.         crashreportcategory3.addCrashSection("Level name", this.worldInfo == null ? "????" : this.worldInfo.getWorldName());
  4102.         crashreportcategory3.addDetail("All players", new ICrashReportDetail<String>()
  4103.         {
  4104.             public String call()
  4105.             {
  4106.                 return World.this.playerEntities.size() + " total; " + World.this.playerEntities;
  4107.             }
  4108.         });
  4109.         crashreportcategory3.addDetail("Chunk stats", new ICrashReportDetail<String>()
  4110.         {
  4111.             public String call()
  4112.             {
  4113.                 return World.this.chunkProvider.makeString();
  4114.             }
  4115.         });
  4116.  
  4117.         try
  4118.         {
  4119.             this.worldInfo.addToCrashReport(crashreportcategory3);
  4120.         }
  4121.         catch (Throwable throwable3)
  4122.         {
  4123.             crashreportcategory3.addCrashSectionThrowable("Level Data Unobtainable", throwable3);
  4124.         }
  4125.  
  4126.         return crashreportcategory3;
  4127.     }
  4128.  
  4129.     /**
  4130.      * Returns horizon height for use in rendering the sky.
  4131.      */
  4132.     @SideOnly(Side.CLIENT)
  4133.     public double getHorizon()
  4134.     {
  4135.         return provider.getHorizon();
  4136.     }
  4137.  
  4138.     public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress)
  4139.     {
  4140.         for (int j2 = 0; j2 < this.eventListeners.size(); ++j2)
  4141.         {
  4142.             IWorldEventListener iworldeventlistener = this.eventListeners.get(j2);
  4143.             iworldeventlistener.sendBlockBreakProgress(breakerId, pos, progress);
  4144.         }
  4145.     }
  4146.  
  4147.     /**
  4148.      * returns a calendar object containing the current date
  4149.      */
  4150.     public Calendar getCurrentDate()
  4151.     {
  4152.         if (this.getTotalWorldTime() % 600L == 0L)
  4153.         {
  4154.             this.calendar.setTimeInMillis(MinecraftServer.getCurrentTimeMillis());
  4155.         }
  4156.  
  4157.         return this.calendar;
  4158.     }
  4159.  
  4160.     @SideOnly(Side.CLIENT)
  4161.     public void makeFireworks(double x, double y, double z, double motionX, double motionY, double motionZ, @Nullable NBTTagCompound compound)
  4162.     {
  4163.     }
  4164.  
  4165.     public Scoreboard getScoreboard()
  4166.     {
  4167.         return this.worldScoreboard;
  4168.     }
  4169.  
  4170.     public void updateComparatorOutputLevel(BlockPos pos, Block blockIn)
  4171.     {
  4172.         for (EnumFacing enumfacing : EnumFacing.VALUES)
  4173.         {
  4174.             BlockPos blockpos1 = pos.offset(enumfacing);
  4175.  
  4176.             if (this.isBlockLoaded(blockpos1))
  4177.             {
  4178.                 IBlockState iblockstate1 = this.getBlockState(blockpos1);
  4179.  
  4180.                 iblockstate1.getBlock().onNeighborChange(this, blockpos1, pos);
  4181.                 if (iblockstate1.getBlock().isNormalCube(iblockstate1, this, blockpos1))
  4182.                 {
  4183.                     blockpos1 = blockpos1.offset(enumfacing);
  4184.                     iblockstate1 = this.getBlockState(blockpos1);
  4185.  
  4186.                     if (iblockstate1.getBlock().getWeakChanges(this, blockpos1))
  4187.                     {
  4188.                         iblockstate1.getBlock().onNeighborChange(this, blockpos1, pos);
  4189.                     }
  4190.                 }
  4191.             }
  4192.         }
  4193.     }
  4194.  
  4195.     public DifficultyInstance getDifficultyForLocation(BlockPos pos)
  4196.     {
  4197.         long j2 = 0L;
  4198.         float f = 0.0F;
  4199.  
  4200.         if (this.isBlockLoaded(pos))
  4201.         {
  4202.             f = this.getCurrentMoonPhaseFactor();
  4203.             j2 = this.getChunkFromBlockCoords(pos).getInhabitedTime();
  4204.         }
  4205.  
  4206.         return new DifficultyInstance(this.getDifficulty(), this.getWorldTime(), j2, f);
  4207.     }
  4208.  
  4209.     public EnumDifficulty getDifficulty()
  4210.     {
  4211.         return this.getWorldInfo().getDifficulty();
  4212.     }
  4213.  
  4214.     public int getSkylightSubtracted()
  4215.     {
  4216.         return this.skylightSubtracted;
  4217.     }
  4218.  
  4219.     public void setSkylightSubtracted(int newSkylightSubtracted)
  4220.     {
  4221.         this.skylightSubtracted = newSkylightSubtracted;
  4222.     }
  4223.  
  4224.     @SideOnly(Side.CLIENT)
  4225.     public int getLastLightningBolt()
  4226.     {
  4227.         return this.lastLightningBolt;
  4228.     }
  4229.  
  4230.     public void setLastLightningBolt(int lastLightningBoltIn)
  4231.     {
  4232.         this.lastLightningBolt = lastLightningBoltIn;
  4233.     }
  4234.  
  4235.     public VillageCollection getVillageCollection()
  4236.     {
  4237.         return this.villageCollection;
  4238.     }
  4239.  
  4240.     public WorldBorder getWorldBorder()
  4241.     {
  4242.         return this.worldBorder;
  4243.     }
  4244.  
  4245.     /**
  4246.      * Returns true if the chunk is located near the spawn point
  4247.      */
  4248.     public boolean isSpawnChunk(int x, int z)
  4249.     {
  4250.         BlockPos blockpos1 = this.getSpawnPoint();
  4251.         int j2 = x * 16 + 8 - blockpos1.getX();
  4252.         int k2 = z * 16 + 8 - blockpos1.getZ();
  4253.         int l2 = 128;
  4254.         return j2 >= -128 && j2 <= 128 && k2 >= -128 && k2 <= 128;
  4255.     }
  4256.  
  4257.     /* ======================================== FORGE START =====================================*/
  4258.     /**
  4259.      * Determine if the given block is considered solid on the
  4260.      * specified side.  Used by placement logic.
  4261.      *
  4262.      * @param pos Block Position
  4263.      * @param side The Side in question
  4264.      * @return True if the side is solid
  4265.     */
  4266.     public boolean isSideSolid(BlockPos pos, EnumFacing side)
  4267.     {
  4268.        return isSideSolid(pos, side, false);
  4269.     }
  4270.  
  4271.     /**
  4272.      * Determine if the given block is considered solid on the
  4273.      * specified side.  Used by placement logic.
  4274.      *
  4275.      * @param pos Block Position
  4276.      * @param side The Side in question
  4277.      * @param _default The default to return if the block doesn't exist.
  4278.      * @return True if the side is solid
  4279.      */
  4280.     @Override
  4281.     public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default)
  4282.     {
  4283.         if (!this.isValid(pos)) return _default;
  4284.  
  4285.         Chunk chunk = getChunkFromBlockCoords(pos);
  4286.         if (chunk == null || chunk.isEmpty()) return _default;
  4287.         return getBlockState(pos).isSideSolid(this, pos, side);
  4288.     }
  4289.  
  4290.     /**
  4291.      * Get the persistent chunks for this world
  4292.      *
  4293.      * @return
  4294.      */
  4295.     public com.google.common.collect.ImmutableSetMultimap<net.minecraft.util.math.ChunkPos, net.minecraftforge.common.ForgeChunkManager.Ticket> getPersistentChunks()
  4296.     {
  4297.         return net.minecraftforge.common.ForgeChunkManager.getPersistentChunksFor(this);
  4298.     }
  4299.  
  4300.     public Iterator<Chunk> getPersistentChunkIterable(Iterator<Chunk> chunkIterator)
  4301.     {
  4302.         return net.minecraftforge.common.ForgeChunkManager.getPersistentChunksIterableFor(this, chunkIterator);
  4303.     }
  4304.     /**
  4305.      * Readded as it was removed, very useful helper function
  4306.      *
  4307.      * @param pos Block position
  4308.      * @return The blocks light opacity
  4309.      */
  4310.     public int getBlockLightOpacity(BlockPos pos)
  4311.     {
  4312.         if (!this.isValid(pos)) return 0;
  4313.         return getChunkFromBlockCoords(pos).getBlockLightOpacity(pos);
  4314.     }
  4315.  
  4316.     /**
  4317.      * Returns a count of entities that classify themselves as the specified creature type.
  4318.      */
  4319.     public int countEntities(net.minecraft.entity.EnumCreatureType type, boolean forSpawnCount)
  4320.     {
  4321.         int count = 0;
  4322.         for (int x = 0; x < loadedEntityList.size(); x++)
  4323.         {
  4324.             if (((Entity)loadedEntityList.get(x)).isCreatureType(type, forSpawnCount))
  4325.             {
  4326.                 count++;
  4327.             }
  4328.         }
  4329.         return count;
  4330.     }
  4331.  
  4332.     @Deprecated // remove in 1.13
  4333.     public void markTileEntitiesInChunkForRemoval(Chunk chunk)
  4334.     {
  4335.         for (TileEntity tileentity : chunk.getTileEntityMap().values())
  4336.         {
  4337.             markTileEntityForRemoval(tileentity);
  4338.         }
  4339.     }
  4340.  
  4341.     protected void initCapabilities()
  4342.     {
  4343.         net.minecraftforge.common.capabilities.ICapabilityProvider parent = provider.initCapabilities();
  4344.         capabilities = net.minecraftforge.event.ForgeEventFactory.gatherCapabilities(this, parent);
  4345.         net.minecraftforge.common.util.WorldCapabilityData data = (net.minecraftforge.common.util.WorldCapabilityData)perWorldStorage.getOrLoadData(net.minecraftforge.common.util.WorldCapabilityData.class, net.minecraftforge.common.util.WorldCapabilityData.ID);
  4346.         if (data == null)
  4347.         {
  4348.             capabilityData = new net.minecraftforge.common.util.WorldCapabilityData(capabilities);
  4349.             perWorldStorage.setData(capabilityData.mapName, capabilityData);
  4350.         }
  4351.         else
  4352.         {
  4353.             capabilityData = data;
  4354.             capabilityData.setCapabilities(provider, capabilities);
  4355.         }
  4356.     }
  4357.     @Override
  4358.     public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, @Nullable EnumFacing facing)
  4359.     {
  4360.         return capabilities == null ? false : capabilities.hasCapability(capability, facing);
  4361.     }
  4362.     @Override
  4363.     @Nullable
  4364.     public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable EnumFacing facing)
  4365.     {
  4366.         return capabilities == null ? null : capabilities.getCapability(capability, facing);
  4367.     }
  4368.  
  4369.     protected MapStorage perWorldStorage; //Moved to a getter to simulate final without being final so we can load in subclasses.
  4370.     public MapStorage getPerWorldStorage()
  4371.     {
  4372.         return perWorldStorage;
  4373.     }
  4374.  
  4375.     public void sendPacketToServer(Packet<?> packetIn)
  4376.     {
  4377.         throw new UnsupportedOperationException("Can't send packets to server unless you're on the client.");
  4378.     }
  4379.  
  4380.     public LootTableManager getLootTableManager()
  4381.     {
  4382.         return this.lootTable;
  4383.     }
  4384.  
  4385.     @Nullable
  4386.     public BlockPos findNearestStructure(String p_190528_1_, BlockPos p_190528_2_, boolean p_190528_3_)
  4387.     {
  4388.         return null;
  4389.     }
  4390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement