package net.minecraft.world;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Callable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockHopper;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.BlockSnow;
import net.minecraft.block.BlockStairs;
import net.minecraft.block.material.Material;
import net.minecraft.command.IEntitySelector;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.pathfinding.PathEntity;
import net.minecraft.pathfinding.PathFinder;
import net.minecraft.profiler.Profiler;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Direction;
import net.minecraft.util.Facing;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.ReportedException;
import net.minecraft.util.Vec3;
import net.minecraft.util.Vec3Pool;
import net.minecraft.village.VillageCollection;
import net.minecraft.village.VillageSiege;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.biome.WorldChunkManager;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraft.world.storage.MapStorage;
import net.minecraft.world.storage.WorldInfo;

import cpw.mods.fml.common.FMLLog;

import com.google.common.collect.ImmutableSetMultimap;

import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.common.WorldSpecificSaveHandler;
import net.minecraftforge.event.entity.EntityEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
import net.minecraft.entity.EnumCreatureType;

public abstract class World implements IBlockAccess
{
   /**
	 * Used in the getEntitiesWithinAABB functions to expand the search area for entities.
	 * Modders should change this variable to a higher value if it is less then the radius
	 * of one of there entities.
	 */
	public static double MAX_ENTITY_RADIUS = 2.0D;

	public final MapStorage perWorldStorage;

	public boolean scheduledUpdatesAreImmediate;
	public List loadedEntityList = new ArrayList();
	protected List unloadedEntityList = new ArrayList();
	public List loadedTileEntityList = new ArrayList();
	private List addedTileEntityList = new ArrayList();
	private List field_147483_b = new ArrayList();
	public List playerEntities = new ArrayList();
	public List weatherEffects = new ArrayList();
	private long cloudColour = 16777215L;
	public int skylightSubtracted;
	protected int updateLCG = (new Random()).nextInt();
	protected final int DIST_HASH_MAGIC = 1013904223;
	public float prevRainingStrength;
	public float rainingStrength;
	public float prevThunderingStrength;
	public float thunderingStrength;
	public int lastLightningBolt;
	public EnumDifficulty difficultySetting;
	public Random rand = new Random();
	public final WorldProvider provider;
	protected List worldAccesses = new ArrayList();
	protected IChunkProvider chunkProvider;
	protected final ISaveHandler saveHandler;
	protected WorldInfo worldInfo;
	public boolean findingSpawnPoint;
	public MapStorage mapStorage;
	public VillageCollection villageCollectionObj;
	protected final VillageSiege villageSiegeObj = new VillageSiege(this);
	public final Profiler theProfiler;
	private final Vec3Pool vecPool = new Vec3Pool(300, 2000);
	private final Calendar theCalendar = Calendar.getInstance();
	protected Scoreboard worldScoreboard = new Scoreboard();
	public boolean isRemote;
	protected Set activeChunkSet = new HashSet();
	private int ambientTickCountdown;
	protected boolean spawnHostileMobs;
	protected boolean spawnPeacefulMobs;
	private ArrayList collidingBoundingBoxes;
	private boolean field_147481_N;
	int[] lightUpdateBlockList;
	private static final String __OBFID = "CL_00000140";

	public BiomeGenBase getBiomeGenForCoords(final int par1, final int par2)
	{
		return provider.getBiomeGenForCoords(par1, par2);
	}

	public BiomeGenBase getBiomeGenForCoordsBody(final int par1, final int par2)
	{
		if (this.blockExists(par1, 0, par2))
		{
			Chunk chunk = this.getChunkFromBlockCoords(par1, par2);

			try
			{
				return chunk.getBiomeGenForWorldCoords(par1 & 15, par2 & 15, this.provider.worldChunkMgr);
			}
			catch (Throwable throwable)
			{
				CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Getting biome");
				CrashReportCategory crashreportcategory = crashreport.makeCategory("Coordinates of biome request");
				crashreportcategory.addCrashSectionCallable("Location", new Callable()
				{
					private static final String __OBFID = "CL_00000141";
					public String call()
					{
						return CrashReportCategory.getLocationInfo(par1, 0, par2);
					}
				});
				throw new ReportedException(crashreport);
			}
		}
		else
		{
			return this.provider.worldChunkMgr.getBiomeGenAt(par1, par2);
		}
	}

	public WorldChunkManager getWorldChunkManager()
	{
		return this.provider.worldChunkMgr;
	}

	@SideOnly(Side.CLIENT)
	public World(ISaveHandler p_i45368_1_, String p_i45368_2_, WorldProvider p_i45368_3_, WorldSettings p_i45368_4_, Profiler p_i45368_5_)
	{
		this.ambientTickCountdown = this.rand.nextInt(12000);
		this.spawnHostileMobs = true;
		this.spawnPeacefulMobs = true;
		this.collidingBoundingBoxes = new ArrayList();
		this.lightUpdateBlockList = new int[32768];
		this.saveHandler = p_i45368_1_;
		this.theProfiler = p_i45368_5_;
		this.worldInfo = new WorldInfo(p_i45368_4_, p_i45368_2_);
		this.provider = p_i45368_3_;
		perWorldStorage = new MapStorage((ISaveHandler)null);
	}

	// Broken up so that the WorldClient gets the chance to set the mapstorage object before the dimension initializes
	@SideOnly(Side.CLIENT)
	protected void finishSetup()
	{
		VillageCollection villagecollection = (VillageCollection)this.mapStorage.loadData(VillageCollection.class, "villages");

		if (villagecollection == null)
		{
			this.villageCollectionObj = new VillageCollection(this);
			this.mapStorage.setData("villages", this.villageCollectionObj);
		}
		else
		{
			this.villageCollectionObj = villagecollection;
			this.villageCollectionObj.func_82566_a(this);
		}

		// Guarantee the dimension ID was not reset by the provider
		int providerDim = this.provider.dimensionId;
		this.provider.registerWorld(this);
		this.provider.dimensionId = providerDim;
		this.chunkProvider = this.createChunkProvider();
		this.calculateInitialSkylight();
		this.calculateInitialWeather();
	}

	public World(ISaveHandler p_i45369_1_, String p_i45369_2_, WorldSettings p_i45369_3_, WorldProvider p_i45369_4_, Profiler p_i45369_5_)
	{
		this.ambientTickCountdown = this.rand.nextInt(12000);
		this.spawnHostileMobs = true;
		this.spawnPeacefulMobs = true;
		this.collidingBoundingBoxes = new ArrayList();
		this.lightUpdateBlockList = new int[32768];
		this.saveHandler = p_i45369_1_;
		this.theProfiler = p_i45369_5_;
		this.mapStorage = getMapStorage(p_i45369_1_);
		this.worldInfo = p_i45369_1_.loadWorldInfo();

		if (p_i45369_4_ != null)
		{
			this.provider = p_i45369_4_;
		}
		else if (this.worldInfo != null && this.worldInfo.getVanillaDimension() != 0)
		{
			this.provider = WorldProvider.getProviderForDimension(this.worldInfo.getVanillaDimension());
		}
		else
		{
			this.provider = WorldProvider.getProviderForDimension(0);
		}

		if (this.worldInfo == null)
		{
			this.worldInfo = new WorldInfo(p_i45369_3_, p_i45369_2_);
		}
		else
		{
			this.worldInfo.setWorldName(p_i45369_2_);
		}

		this.provider.registerWorld(this);
		this.chunkProvider = this.createChunkProvider();

		if (this instanceof WorldServer)
		{
			this.perWorldStorage = new MapStorage(new WorldSpecificSaveHandler((WorldServer)this, p_i45369_1_));
		}
		else
		{
			this.perWorldStorage = new MapStorage((ISaveHandler)null);
		}

		if (!this.worldInfo.isInitialized())
		{
			try
			{
				this.initialize(p_i45369_3_);
			}
			catch (Throwable throwable1)
			{
				CrashReport crashreport = CrashReport.makeCrashReport(throwable1, "Exception initializing level");

				try
				{
					this.addWorldInfoToCrashReport(crashreport);
				}
				catch (Throwable throwable)
				{
					;
				}

				throw new ReportedException(crashreport);
			}

			this.worldInfo.setServerInitialized(true);
		}

		VillageCollection villagecollection = (VillageCollection)this.perWorldStorage.loadData(VillageCollection.class, "villages");

		if (villagecollection == null)
		{
			this.villageCollectionObj = new VillageCollection(this);
			this.perWorldStorage.setData("villages", this.villageCollectionObj);
		}
		else
		{
			this.villageCollectionObj = villagecollection;
			this.villageCollectionObj.func_82566_a(this);
		}

		this.calculateInitialSkylight();
		this.calculateInitialWeather();
	}

	private static MapStorage s_mapStorage;
	private static ISaveHandler s_savehandler;
	//Provides a solution for different worlds getting different copies of the same data, potentially rewriting the data or causing race conditions/stale data
	//Buildcraft has suffered from the issue this fixes.  If you load the same data from two different worlds they can get two different copies of the same object, thus the last saved gets final say.
	private MapStorage getMapStorage(ISaveHandler savehandler)
	{
		if (s_savehandler != savehandler || s_mapStorage == null)
		{
			s_mapStorage = new MapStorage(savehandler);
			s_savehandler = savehandler;
		}
		return s_mapStorage;
	}

	protected abstract IChunkProvider createChunkProvider();

	protected void initialize(WorldSettings par1WorldSettings)
	{
		this.worldInfo.setServerInitialized(true);
	}

	@SideOnly(Side.CLIENT)
	public void setSpawnLocation()
	{
		this.setSpawnLocation(8, 64, 8);
	}

	public Block getTopBlock(int p_147474_1_, int p_147474_2_)
	{
		int k;

		for (k = 63; !this.isAirBlock(p_147474_1_, k + 1, p_147474_2_); ++k)
		{
			;
		}

		return this.getBlock(p_147474_1_, k, p_147474_2_);
	}

	public Block getBlock(int p_147439_1_, int p_147439_2_, int p_147439_3_)
	{
		if (p_147439_1_ >= -30000000 && p_147439_3_ >= -30000000 && p_147439_1_ < 30000000 && p_147439_3_ < 30000000 && p_147439_2_ >= 0 && p_147439_2_ < 256)
		{
			Chunk chunk = null;

			try
			{
				chunk = this.getChunkFromChunkCoords(p_147439_1_ >> 4, p_147439_3_ >> 4);
				return chunk.getBlock(p_147439_1_ & 15, p_147439_2_, p_147439_3_ & 15);
			}
			catch (Throwable throwable)
			{
				CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception getting block type in world");
				CrashReportCategory crashreportcategory = crashreport.makeCategory("Requested block coordinates");
				crashreportcategory.addCrashSection("Found chunk", Boolean.valueOf(chunk == null));
				crashreportcategory.addCrashSection("Location", CrashReportCategory.getLocationInfo(p_147439_1_, p_147439_2_, p_147439_3_));
				throw new ReportedException(crashreport);
			}
		}
		else
		{
			return Blocks.air;
		}
	}

	public boolean isAirBlock(int p_147437_1_, int p_147437_2_, int p_147437_3_)
	{
		Block block = this.getBlock(p_147437_1_, p_147437_2_, p_147437_3_);
		return block.isAir(this, p_147437_1_, p_147437_2_, p_147437_3_);
	}

	public boolean blockExists(int par1, int par2, int par3)
	{
		return par2 >= 0 && par2 < 256 ? this.chunkExists(par1 >> 4, par3 >> 4) : false;
	}

	public boolean doChunksNearChunkExist(int par1, int par2, int par3, int par4)
	{
		return this.checkChunksExist(par1 - par4, par2 - par4, par3 - par4, par1 + par4, par2 + par4, par3 + par4);
	}

	public boolean checkChunksExist(int par1, int par2, int par3, int par4, int par5, int par6)
	{
		if (par5 >= 0 && par2 < 256)
		{
			par1 >>= 4;
			par3 >>= 4;
			par4 >>= 4;
			par6 >>= 4;

			for (int k1 = par1; k1 <= par4; ++k1)
			{
				for (int l1 = par3; l1 <= par6; ++l1)
				{
					if (!this.chunkExists(k1, l1))
					{
						return false;
					}
				}
			}

			return true;
		}
		else
		{
			return false;
		}
	}

	protected boolean chunkExists(int par1, int par2)
	{
		return this.chunkProvider.chunkExists(par1, par2);
	}

	public Chunk getChunkFromBlockCoords(int par1, int par2)
	{
		return this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4);
	}

	public Chunk getChunkFromChunkCoords(int par1, int par2)
	{
		return this.chunkProvider.provideChunk(par1, par2);
	}

	public boolean setBlock(int p_147465_1_, int p_147465_2_, int p_147465_3_, Block p_147465_4_, int p_147465_5_, int p_147465_6_)
	{
		if (p_147465_1_ >= -30000000 && p_147465_3_ >= -30000000 && p_147465_1_ < 30000000 && p_147465_3_ < 30000000)
		{
			if (p_147465_2_ < 0)
			{
				return false;
			}
			else if (p_147465_2_ >= 256)
			{
				return false;
			}
			else
			{
				Chunk chunk = this.getChunkFromChunkCoords(p_147465_1_ >> 4, p_147465_3_ >> 4);
				Block block1 = null;

				if ((p_147465_6_ & 1) != 0)
				{
					block1 = chunk.getBlock(p_147465_1_ & 15, p_147465_2_, p_147465_3_ & 15);
				}

				boolean flag = chunk.func_150807_a(p_147465_1_ & 15, p_147465_2_, p_147465_3_ & 15, p_147465_4_, p_147465_5_);
				this.theProfiler.startSection("checkLight");
				this.func_147451_t(p_147465_1_, p_147465_2_, p_147465_3_);
				this.theProfiler.endSection();

				if (flag)
				{
					if ((p_147465_6_ & 2) != 0 && (!this.isRemote || (p_147465_6_ & 4) == 0) && chunk.func_150802_k())
					{
						this.markBlockForUpdate(p_147465_1_, p_147465_2_, p_147465_3_);
					}

					if (!this.isRemote && (p_147465_6_ & 1) != 0)
					{
						this.notifyBlockChange(p_147465_1_, p_147465_2_, p_147465_3_, block1);

						if (p_147465_4_.hasComparatorInputOverride())
						{
							this.func_147453_f(p_147465_1_, p_147465_2_, p_147465_3_, p_147465_4_);
						}
					}
				}

				return flag;
			}
		}
		else
		{
			return false;
		}
	}

	public int getBlockMetadata(int par1, int par2, int par3)
	{
		if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000)
		{
			if (par2 < 0)
			{
				return 0;
			}
			else if (par2 >= 256)
			{
				return 0;
			}
			else
			{
				Chunk chunk = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
				par1 &= 15;
				par3 &= 15;
				return chunk.getBlockMetadata(par1, par2, par3);
			}
		}
		else
		{
			return 0;
		}
	}

	public boolean setBlockMetadataWithNotify(int par1, int par2, int par3, int par4, int par5)
	{
		if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000)
		{
			if (par2 < 0)
			{
				return false;
			}
			else if (par2 >= 256)
			{
				return false;
			}
			else
			{
				Chunk chunk = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
				int j1 = par1 & 15;
				int k1 = par3 & 15;
				boolean flag = chunk.setBlockMetadata(j1, par2, k1, par4);

				if (flag)
				{
					Block block = chunk.getBlock(j1, par2, k1);

					if ((par5 & 2) != 0 && (!this.isRemote || (par5 & 4) == 0) && chunk.func_150802_k())
					{
						this.markBlockForUpdate(par1, par2, par3);
					}

					if (!this.isRemote && (par5 & 1) != 0)
					{
						this.notifyBlockChange(par1, par2, par3, block);

						if (block.hasComparatorInputOverride())
						{
							this.func_147453_f(par1, par2, par3, block);
						}
					}
				}

				return flag;
			}
		}
		else
		{
			return false;
		}
	}

	public boolean setBlockToAir(int p_147468_1_, int p_147468_2_, int p_147468_3_)
	{
		return this.setBlock(p_147468_1_, p_147468_2_, p_147468_3_, Blocks.air, 0, 3);
	}

	public boolean func_147480_a(int p_147480_1_, int p_147480_2_, int p_147480_3_, boolean p_147480_4_)
	{
		Block block = this.getBlock(p_147480_1_, p_147480_2_, p_147480_3_);

		if (block.getMaterial() == Material.air)
		{
			return false;
		}
		else
		{
			int l = this.getBlockMetadata(p_147480_1_, p_147480_2_, p_147480_3_);
			this.playAuxSFX(2001, p_147480_1_, p_147480_2_, p_147480_3_, Block.getIdFromBlock(block) + (l << 12));

			if (p_147480_4_)
			{
				block.dropBlockAsItem(this, p_147480_1_, p_147480_2_, p_147480_3_, l, 0);
			}

			return this.setBlock(p_147480_1_, p_147480_2_, p_147480_3_, Blocks.air, 0, 3);
		}
	}

	public boolean setBlock(int p_147449_1_, int p_147449_2_, int p_147449_3_, Block p_147449_4_)
	{
		return this.setBlock(p_147449_1_, p_147449_2_, p_147449_3_, p_147449_4_, 0, 3);
	}

	public void markBlockForUpdate(int p_147471_1_, int p_147471_2_, int p_147471_3_)
	{
		for (int l = 0; l < this.worldAccesses.size(); ++l)
		{
			((IWorldAccess)this.worldAccesses.get(l)).markBlockForUpdate(p_147471_1_, p_147471_2_, p_147471_3_);
		}
	}

	public void notifyBlockChange(int p_147444_1_, int p_147444_2_, int p_147444_3_, Block p_147444_4_)
	{
		this.notifyBlocksOfNeighborChange(p_147444_1_, p_147444_2_, p_147444_3_, p_147444_4_);
	}

	public void markBlocksDirtyVertical(int par1, int par2, int par3, int par4)
	{
		int i1;

		if (par3 > par4)
		{
			i1 = par4;
			par4 = par3;
			par3 = i1;
		}

		if (!this.provider.hasNoSky)
		{
			for (i1 = par3; i1 <= par4; ++i1)
			{
				this.updateLightByType(EnumSkyBlock.Sky, par1, i1, par2);
			}
		}

		this.markBlockRangeForRenderUpdate(par1, par3, par2, par1, par4, par2);
	}

	public void markBlockRangeForRenderUpdate(int p_147458_1_, int p_147458_2_, int p_147458_3_, int p_147458_4_, int p_147458_5_, int p_147458_6_)
	{
		for (int k1 = 0; k1 < this.worldAccesses.size(); ++k1)
		{
			((IWorldAccess)this.worldAccesses.get(k1)).markBlockRangeForRenderUpdate(p_147458_1_, p_147458_2_, p_147458_3_, p_147458_4_, p_147458_5_, p_147458_6_);
		}
	}

	public void notifyBlocksOfNeighborChange(int p_147459_1_, int p_147459_2_, int p_147459_3_, Block p_147459_4_)
	{
		this.notifyBlockOfNeighborChange(p_147459_1_ - 1, p_147459_2_, p_147459_3_, p_147459_4_);
		this.notifyBlockOfNeighborChange(p_147459_1_ + 1, p_147459_2_, p_147459_3_, p_147459_4_);
		this.notifyBlockOfNeighborChange(p_147459_1_, p_147459_2_ - 1, p_147459_3_, p_147459_4_);
		this.notifyBlockOfNeighborChange(p_147459_1_, p_147459_2_ + 1, p_147459_3_, p_147459_4_);
		this.notifyBlockOfNeighborChange(p_147459_1_, p_147459_2_, p_147459_3_ - 1, p_147459_4_);
		this.notifyBlockOfNeighborChange(p_147459_1_, p_147459_2_, p_147459_3_ + 1, p_147459_4_);
	}

	public void notifyBlocksOfNeighborChange(int p_147441_1_, int p_147441_2_, int p_147441_3_, Block p_147441_4_, int p_147441_5_)
	{
		if (p_147441_5_ != 4)
		{
			this.notifyBlockOfNeighborChange(p_147441_1_ - 1, p_147441_2_, p_147441_3_, p_147441_4_);
		}

		if (p_147441_5_ != 5)
		{
			this.notifyBlockOfNeighborChange(p_147441_1_ + 1, p_147441_2_, p_147441_3_, p_147441_4_);
		}

		if (p_147441_5_ != 0)
		{
			this.notifyBlockOfNeighborChange(p_147441_1_, p_147441_2_ - 1, p_147441_3_, p_147441_4_);
		}

		if (p_147441_5_ != 1)
		{
			this.notifyBlockOfNeighborChange(p_147441_1_, p_147441_2_ + 1, p_147441_3_, p_147441_4_);
		}

		if (p_147441_5_ != 2)
		{
			this.notifyBlockOfNeighborChange(p_147441_1_, p_147441_2_, p_147441_3_ - 1, p_147441_4_);
		}

		if (p_147441_5_ != 3)
		{
			this.notifyBlockOfNeighborChange(p_147441_1_, p_147441_2_, p_147441_3_ + 1, p_147441_4_);
		}
	}

	public void notifyBlockOfNeighborChange(int p_147460_1_, int p_147460_2_, int p_147460_3_, final Block p_147460_4_)
	{
		if (!this.isRemote)
		{
			Block block = this.getBlock(p_147460_1_, p_147460_2_, p_147460_3_);

			try
			{
				block.onNeighborBlockChange(this, p_147460_1_, p_147460_2_, p_147460_3_, p_147460_4_);
			}
			catch (Throwable throwable1)
			{
				CrashReport crashreport = CrashReport.makeCrashReport(throwable1, "Exception while updating neighbours");
				CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being updated");
				int l;

				try
				{
					l = this.getBlockMetadata(p_147460_1_, p_147460_2_, p_147460_3_);
				}
				catch (Throwable throwable)
				{
					l = -1;
				}

				crashreportcategory.addCrashSectionCallable("Source block type", new Callable()
				{
					private static final String __OBFID = "CL_00000142";
					public String call()
					{
						try
						{
							return String.format("ID #%d (%s // %s)", new Object[] {Integer.valueOf(Block.getIdFromBlock(p_147460_4_)), p_147460_4_.getUnlocalizedName(), p_147460_4_.getClass().getCanonicalName()});
						}
						catch (Throwable throwable2)
						{
							return "ID #" + Block.getIdFromBlock(p_147460_4_);
						}
					}
				});
				CrashReportCategory.func_147153_a(crashreportcategory, p_147460_1_, p_147460_2_, p_147460_3_, block, l);
				throw new ReportedException(crashreport);
			}
		}
	}

	public boolean isBlockTickScheduledThisTick(int p_147477_1_, int p_147477_2_, int p_147477_3_, Block p_147477_4_)
	{
		return false;
	}

	public boolean canBlockSeeTheSky(int par1, int par2, int par3)
	{
		return this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).canBlockSeeTheSky(par1 & 15, par2, par3 & 15);
	}

	public int getFullBlockLightValue(int par1, int par2, int par3)
	{
		if (par2 < 0)
		{
			return 0;
		}
		else
		{
			if (par2 >= 256)
			{
				par2 = 255;
			}

			return this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).getBlockLightValue(par1 & 15, par2, par3 & 15, 0);
		}
	}

	public int getBlockLightValue(int par1, int par2, int par3)
	{
		return this.getBlockLightValue_do(par1, par2, par3, true);
	}

	public int getBlockLightValue_do(int par1, int par2, int par3, boolean par4)
	{
		if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000)
		{
			if (par4 && this.getBlock(par1, par2, par3).getUseNeighborBrightness())
			{
				int l1 = this.getBlockLightValue_do(par1, par2 + 1, par3, false);
				int l = this.getBlockLightValue_do(par1 + 1, par2, par3, false);
				int i1 = this.getBlockLightValue_do(par1 - 1, par2, par3, false);
				int j1 = this.getBlockLightValue_do(par1, par2, par3 + 1, false);
				int k1 = this.getBlockLightValue_do(par1, par2, par3 - 1, false);

				if (l > l1)
				{
					l1 = l;
				}

				if (i1 > l1)
				{
					l1 = i1;
				}

				if (j1 > l1)
				{
					l1 = j1;
				}

				if (k1 > l1)
				{
					l1 = k1;
				}

				return l1;
			}
			else if (par2 < 0)
			{
				return 0;
			}
			else
			{
				if (par2 >= 256)
				{
					par2 = 255;
				}

				Chunk chunk = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
				par1 &= 15;
				par3 &= 15;
				return chunk.getBlockLightValue(par1, par2, par3, this.skylightSubtracted);
			}
		}
		else
		{
			return 15;
		}
	}

	public int getHeightValue(int par1, int par2)
	{
		if (par1 >= -30000000 && par2 >= -30000000 && par1 < 30000000 && par2 < 30000000)
		{
			if (!this.chunkExists(par1 >> 4, par2 >> 4))
			{
				return 0;
			}
			else
			{
				Chunk chunk = this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4);
				return chunk.getHeightValue(par1 & 15, par2 & 15);
			}
		}
		else
		{
			return 64;
		}
	}

	public int getChunkHeightMapMinimum(int par1, int par2)
	{
		if (par1 >= -30000000 && par2 >= -30000000 && par1 < 30000000 && par2 < 30000000)
		{
			if (!this.chunkExists(par1 >> 4, par2 >> 4))
			{
				return 0;
			}
			else
			{
				Chunk chunk = this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4);
				return chunk.heightMapMinimum;
			}
		}
		else
		{
			return 64;
		}
	}

	@SideOnly(Side.CLIENT)
	public int getSkyBlockTypeBrightness(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
	{
		if (this.provider.hasNoSky && par1EnumSkyBlock == EnumSkyBlock.Sky)
		{
			return 0;
		}
		else
		{
			if (par3 < 0)
			{
				par3 = 0;
			}

			if (par3 >= 256)
			{
				return par1EnumSkyBlock.defaultLightValue;
			}
			else if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000)
			{
				int l = par2 >> 4;
				int i1 = par4 >> 4;

				if (!this.chunkExists(l, i1))
				{
					return par1EnumSkyBlock.defaultLightValue;
				}
				else if (this.getBlock(par2, par3, par4).getUseNeighborBrightness())
				{
					int j2 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3 + 1, par4);
					int j1 = this.getSavedLightValue(par1EnumSkyBlock, par2 + 1, par3, par4);
					int k1 = this.getSavedLightValue(par1EnumSkyBlock, par2 - 1, par3, par4);
					int l1 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3, par4 + 1);
					int i2 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3, par4 - 1);

					if (j1 > j2)
					{
						j2 = j1;
					}

					if (k1 > j2)
					{
						j2 = k1;
					}

					if (l1 > j2)
					{
						j2 = l1;
					}

					if (i2 > j2)
					{
						j2 = i2;
					}

					return j2;
				}
				else
				{
					Chunk chunk = this.getChunkFromChunkCoords(l, i1);
					return chunk.getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
				}
			}
			else
			{
				return par1EnumSkyBlock.defaultLightValue;
			}
		}
	}

	public int getSavedLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
	{
		if (par3 < 0)
		{
			par3 = 0;
		}

		if (par3 >= 256)
		{
			par3 = 255;
		}

		if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000)
		{
			int l = par2 >> 4;
			int i1 = par4 >> 4;

			if (!this.chunkExists(l, i1))
			{
				return par1EnumSkyBlock.defaultLightValue;
			}
			else
			{
				Chunk chunk = this.getChunkFromChunkCoords(l, i1);
				return chunk.getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
			}
		}
		else
		{
			return par1EnumSkyBlock.defaultLightValue;
		}
	}

	public void setLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4, int par5)
	{
		if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000)
		{
			if (par3 >= 0)
			{
				if (par3 < 256)
				{
					if (this.chunkExists(par2 >> 4, par4 >> 4))
					{
						Chunk chunk = this.getChunkFromChunkCoords(par2 >> 4, par4 >> 4);
						chunk.setLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15, par5);

						for (int i1 = 0; i1 < this.worldAccesses.size(); ++i1)
						{
							((IWorldAccess)this.worldAccesses.get(i1)).markBlockForRenderUpdate(par2, par3, par4);
						}
					}
				}
			}
		}
	}

	public void func_147479_m(int p_147479_1_, int p_147479_2_, int p_147479_3_)
	{
		for (int l = 0; l < this.worldAccesses.size(); ++l)
		{
			((IWorldAccess)this.worldAccesses.get(l)).markBlockForRenderUpdate(p_147479_1_, p_147479_2_, p_147479_3_);
		}
	}

	@SideOnly(Side.CLIENT)
	public int getLightBrightnessForSkyBlocks(int par1, int par2, int par3, int par4)
	{
		int i1 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Sky, par1, par2, par3);
		int j1 = this.getSkyBlockTypeBrightness(EnumSkyBlock.Block, par1, par2, par3);

		if (j1 < par4)
		{
			j1 = par4;
		}

		return i1 << 20 | j1 << 4;
	}

	public float getLightBrightness(int par1, int par2, int par3)
	{
		return this.provider.lightBrightnessTable[this.getBlockLightValue(par1, par2, par3)];
	}

	public boolean isDaytime()
	{
		return provider.isDaytime();
	}

	public MovingObjectPosition rayTraceBlocks(Vec3 par1Vec3, Vec3 par2Vec3)
	{
		return this.func_147447_a(par1Vec3, par2Vec3, false, false, false);
	}

	public MovingObjectPosition rayTraceBlocks(Vec3 par1Vec3, Vec3 par2Vec3, boolean par3)
	{
		return this.func_147447_a(par1Vec3, par2Vec3, par3, false, false);
	}

	public MovingObjectPosition func_147447_a(Vec3 p_147447_1_, Vec3 p_147447_2_, boolean p_147447_3_, boolean p_147447_4_, boolean p_147447_5_)
	{
		if (!Double.isNaN(p_147447_1_.xCoord) && !Double.isNaN(p_147447_1_.yCoord) && !Double.isNaN(p_147447_1_.zCoord))
		{
			if (!Double.isNaN(p_147447_2_.xCoord) && !Double.isNaN(p_147447_2_.yCoord) && !Double.isNaN(p_147447_2_.zCoord))
			{
				int i = MathHelper.floor_double(p_147447_2_.xCoord);
				int j = MathHelper.floor_double(p_147447_2_.yCoord);
				int k = MathHelper.floor_double(p_147447_2_.zCoord);
				int l = MathHelper.floor_double(p_147447_1_.xCoord);
				int i1 = MathHelper.floor_double(p_147447_1_.yCoord);
				int j1 = MathHelper.floor_double(p_147447_1_.zCoord);
				Block block = this.getBlock(l, i1, j1);
				int k1 = this.getBlockMetadata(l, i1, j1);

				if ((!p_147447_4_ || block.getCollisionBoundingBoxFromPool(this, l, i1, j1) != null) && block.canCollideCheck(k1, p_147447_3_))
				{
					MovingObjectPosition movingobjectposition = block.collisionRayTrace(this, l, i1, j1, p_147447_1_, p_147447_2_);

					if (movingobjectposition != null)
					{
						return movingobjectposition;
					}
				}

				MovingObjectPosition movingobjectposition2 = null;
				k1 = 200;

				while (k1-- >= 0)
				{
					if (Double.isNaN(p_147447_1_.xCoord) || Double.isNaN(p_147447_1_.yCoord) || Double.isNaN(p_147447_1_.zCoord))
					{
						return null;
					}

					if (l == i && i1 == j && j1 == k)
					{
						return p_147447_5_ ? movingobjectposition2 : null;
					}

					boolean flag6 = true;
					boolean flag3 = true;
					boolean flag4 = true;
					double d0 = 999.0D;
					double d1 = 999.0D;
					double d2 = 999.0D;

					if (i > l)
					{
						d0 = (double)l + 1.0D;
					}
					else if (i < l)
					{
						d0 = (double)l + 0.0D;
					}
					else
					{
						flag6 = false;
					}

					if (j > i1)
					{
						d1 = (double)i1 + 1.0D;
					}
					else if (j < i1)
					{
						d1 = (double)i1 + 0.0D;
					}
					else
					{
						flag3 = false;
					}

					if (k > j1)
					{
						d2 = (double)j1 + 1.0D;
					}
					else if (k < j1)
					{
						d2 = (double)j1 + 0.0D;
					}
					else
					{
						flag4 = false;
					}

					double d3 = 999.0D;
					double d4 = 999.0D;
					double d5 = 999.0D;
					double d6 = p_147447_2_.xCoord - p_147447_1_.xCoord;
					double d7 = p_147447_2_.yCoord - p_147447_1_.yCoord;
					double d8 = p_147447_2_.zCoord - p_147447_1_.zCoord;

					if (flag6)
					{
						d3 = (d0 - p_147447_1_.xCoord) / d6;
					}

					if (flag3)
					{
						d4 = (d1 - p_147447_1_.yCoord) / d7;
					}

					if (flag4)
					{
						d5 = (d2 - p_147447_1_.zCoord) / d8;
					}

					boolean flag5 = false;
					byte b0;

					if (d3 < d4 && d3 < d5)
					{
						if (i > l)
						{
							b0 = 4;
						}
						else
						{
							b0 = 5;
						}

						p_147447_1_.xCoord = d0;
						p_147447_1_.yCoord += d7 * d3;
						p_147447_1_.zCoord += d8 * d3;
					}
					else if (d4 < d5)
					{
						if (j > i1)
						{
							b0 = 0;
						}
						else
						{
							b0 = 1;
						}

						p_147447_1_.xCoord += d6 * d4;
						p_147447_1_.yCoord = d1;
						p_147447_1_.zCoord += d8 * d4;
					}
					else
					{
						if (k > j1)
						{
							b0 = 2;
						}
						else
						{
							b0 = 3;
						}

						p_147447_1_.xCoord += d6 * d5;
						p_147447_1_.yCoord += d7 * d5;
						p_147447_1_.zCoord = d2;
					}

					Vec3 vec32 = this.getWorldVec3Pool().getVecFromPool(p_147447_1_.xCoord, p_147447_1_.yCoord, p_147447_1_.zCoord);
					l = (int)(vec32.xCoord = (double)MathHelper.floor_double(p_147447_1_.xCoord));

					if (b0 == 5)
					{
						--l;
						++vec32.xCoord;
					}

					i1 = (int)(vec32.yCoord = (double)MathHelper.floor_double(p_147447_1_.yCoord));

					if (b0 == 1)
					{
						--i1;
						++vec32.yCoord;
					}

					j1 = (int)(vec32.zCoord = (double)MathHelper.floor_double(p_147447_1_.zCoord));

					if (b0 == 3)
					{
						--j1;
						++vec32.zCoord;
					}

					Block block1 = this.getBlock(l, i1, j1);
					int l1 = this.getBlockMetadata(l, i1, j1);

					if (!p_147447_4_ || block1.getCollisionBoundingBoxFromPool(this, l, i1, j1) != null)
					{
						if (block1.canCollideCheck(l1, p_147447_3_))
						{
							MovingObjectPosition movingobjectposition1 = block1.collisionRayTrace(this, l, i1, j1, p_147447_1_, p_147447_2_);

							if (movingobjectposition1 != null)
							{
								return movingobjectposition1;
							}
						}
						else
						{
							movingobjectposition2 = new MovingObjectPosition(l, i1, j1, b0, p_147447_1_, false);
						}
					}
				}

				return p_147447_5_ ? movingobjectposition2 : null;
			}
			else
			{
				return null;
			}
		}
		else
		{
			return null;
		}
	}

	public void playSoundAtEntity(Entity par1Entity, String par2Str, float par3, float par4)
	{
		PlaySoundAtEntityEvent event = new PlaySoundAtEntityEvent(par1Entity, par2Str, par3, par4);
		if (MinecraftForge.EVENT_BUS.post(event))
		{
			return;
		}
		par2Str = event.name;
		for (int i = 0; i < this.worldAccesses.size(); ++i)
		{
			((IWorldAccess)this.worldAccesses.get(i)).playSound(par2Str, par1Entity.posX, par1Entity.posY - (double)par1Entity.yOffset, par1Entity.posZ, par3, par4);
		}
	}

	public void playSoundToNearExcept(EntityPlayer par1EntityPlayer, String par2Str, float par3, float par4)
	{
		PlaySoundAtEntityEvent event = new PlaySoundAtEntityEvent(par1EntityPlayer, par2Str, par3, par4);
		if (MinecraftForge.EVENT_BUS.post(event))
		{
			return;
		}
		par2Str = event.name;
		for (int i = 0; i < this.worldAccesses.size(); ++i)
		{
			((IWorldAccess)this.worldAccesses.get(i)).playSoundToNearExcept(par1EntityPlayer, par2Str, par1EntityPlayer.posX, par1EntityPlayer.posY - (double)par1EntityPlayer.yOffset, par1EntityPlayer.posZ, par3, par4);
		}
	}

	public void playSoundEffect(double par1, double par3, double par5, String par7Str, float par8, float par9)
	{
		for (int i = 0; i < this.worldAccesses.size(); ++i)
		{
			((IWorldAccess)this.worldAccesses.get(i)).playSound(par7Str, par1, par3, par5, par8, par9);
		}
	}

	public void playSound(double par1, double par3, double par5, String par7Str, float par8, float par9, boolean par10) {}

	public void playRecord(String par1Str, int par2, int par3, int par4)
	{
		for (int l = 0; l < this.worldAccesses.size(); ++l)
		{
			((IWorldAccess)this.worldAccesses.get(l)).playRecord(par1Str, par2, par3, par4);
		}
	}

	public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10, double par12)
	{
		for (int i = 0; i < this.worldAccesses.size(); ++i)
		{
			((IWorldAccess)this.worldAccesses.get(i)).spawnParticle(par1Str, par2, par4, par6, par8, par10, par12);
		}
	}

	public boolean addWeatherEffect(Entity par1Entity)
	{
		this.weatherEffects.add(par1Entity);
		return true;
	}

	public boolean spawnEntityInWorld(Entity par1Entity)
	{
		int i = MathHelper.floor_double(par1Entity.posX / 16.0D);
		int j = MathHelper.floor_double(par1Entity.posZ / 16.0D);
		boolean flag = par1Entity.forceSpawn;

		if (par1Entity instanceof EntityPlayer)
		{
			flag = true;
		}

		if (!flag && !this.chunkExists(i, j))
		{
			return false;
		}
		else
		{
			if (par1Entity instanceof EntityPlayer)
			{
				EntityPlayer entityplayer = (EntityPlayer)par1Entity;
				this.playerEntities.add(entityplayer);
				this.updateAllPlayersSleepingFlag();
			}
			if (MinecraftForge.EVENT_BUS.post(new EntityJoinWorldEvent(par1Entity, this)) && !flag) return false;

			this.getChunkFromChunkCoords(i, j).addEntity(par1Entity);
			this.loadedEntityList.add(par1Entity);
			this.onEntityAdded(par1Entity);
			return true;
		}
	}

	public void onEntityAdded(Entity par1Entity)
	{
		for (int i = 0; i < this.worldAccesses.size(); ++i)
		{
			((IWorldAccess)this.worldAccesses.get(i)).onEntityCreate(par1Entity);
		}
	}

	public void onEntityRemoved(Entity par1Entity)
	{
		for (int i = 0; i < this.worldAccesses.size(); ++i)
		{
			((IWorldAccess)this.worldAccesses.get(i)).onEntityDestroy(par1Entity);
		}
	}

	public void removeEntity(Entity par1Entity)
	{
		if (par1Entity.riddenByEntity != null)
		{
			par1Entity.riddenByEntity.mountEntity((Entity)null);
		}

		if (par1Entity.ridingEntity != null)
		{
			par1Entity.mountEntity((Entity)null);
		}

		par1Entity.setDead();

		if (par1Entity instanceof EntityPlayer)
		{
			this.playerEntities.remove(par1Entity);
			this.updateAllPlayersSleepingFlag();
		}
	}

	public void removePlayerEntityDangerously(Entity par1Entity)
	{
		par1Entity.setDead();

		if (par1Entity instanceof EntityPlayer)
		{
			this.playerEntities.remove(par1Entity);
			this.updateAllPlayersSleepingFlag();
		}

		int i = par1Entity.chunkCoordX;
		int j = par1Entity.chunkCoordZ;

		if (par1Entity.addedToChunk && this.chunkExists(i, j))
		{
			this.getChunkFromChunkCoords(i, j).removeEntity(par1Entity);
		}

		this.loadedEntityList.remove(par1Entity);
		this.onEntityRemoved(par1Entity);
	}

	public void addWorldAccess(IWorldAccess par1IWorldAccess)
	{
		this.worldAccesses.add(par1IWorldAccess);
	}

	public List getCollidingBoundingBoxes(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB)
	{
		this.collidingBoundingBoxes.clear();
		int i = MathHelper.floor_double(par2AxisAlignedBB.minX);
		int j = MathHelper.floor_double(par2AxisAlignedBB.maxX + 1.0D);
		int k = MathHelper.floor_double(par2AxisAlignedBB.minY);
		int l = MathHelper.floor_double(par2AxisAlignedBB.maxY + 1.0D);
		int i1 = MathHelper.floor_double(par2AxisAlignedBB.minZ);
		int j1 = MathHelper.floor_double(par2AxisAlignedBB.maxZ + 1.0D);

		for (int k1 = i; k1 < j; ++k1)
		{
			for (int l1 = i1; l1 < j1; ++l1)
			{
				if (this.blockExists(k1, 64, l1))
				{
					for (int i2 = k - 1; i2 < l; ++i2)
					{
						Block block;

						if (k1 >= -30000000 && k1 < 30000000 && l1 >= -30000000 && l1 < 30000000)
						{
							block = this.getBlock(k1, i2, l1);
						}
						else
						{
							block = Blocks.stone;
						}

						block.addCollisionBoxesToList(this, k1, i2, l1, par2AxisAlignedBB, this.collidingBoundingBoxes, par1Entity);
					}
				}
			}
		}

		double d0 = 0.25D;
		List list = this.getEntitiesWithinAABBExcludingEntity(par1Entity, par2AxisAlignedBB.expand(d0, d0, d0));

		for (int j2 = 0; j2 < list.size(); ++j2)
		{
			AxisAlignedBB axisalignedbb1 = ((Entity)list.get(j2)).getBoundingBox();

			if (axisalignedbb1 != null && axisalignedbb1.intersectsWith(par2AxisAlignedBB))
			{
				this.collidingBoundingBoxes.add(axisalignedbb1);
			}

			axisalignedbb1 = par1Entity.getCollisionBox((Entity)list.get(j2));

			if (axisalignedbb1 != null && axisalignedbb1.intersectsWith(par2AxisAlignedBB))
			{
				this.collidingBoundingBoxes.add(axisalignedbb1);
			}
		}

		return this.collidingBoundingBoxes;
	}

	public List func_147461_a(AxisAlignedBB p_147461_1_)
	{
		this.collidingBoundingBoxes.clear();
		int i = MathHelper.floor_double(p_147461_1_.minX);
		int j = MathHelper.floor_double(p_147461_1_.maxX + 1.0D);
		int k = MathHelper.floor_double(p_147461_1_.minY);
		int l = MathHelper.floor_double(p_147461_1_.maxY + 1.0D);
		int i1 = MathHelper.floor_double(p_147461_1_.minZ);
		int j1 = MathHelper.floor_double(p_147461_1_.maxZ + 1.0D);

		for (int k1 = i; k1 < j; ++k1)
		{
			for (int l1 = i1; l1 < j1; ++l1)
			{
				if (this.blockExists(k1, 64, l1))
				{
					for (int i2 = k - 1; i2 < l; ++i2)
					{
						Block block;

						if (k1 >= -30000000 && k1 < 30000000 && l1 >= -30000000 && l1 < 30000000)
						{
							block = this.getBlock(k1, i2, l1);
						}
						else
						{
							block = Blocks.bedrock;
						}

						block.addCollisionBoxesToList(this, k1, i2, l1, p_147461_1_, this.collidingBoundingBoxes, (Entity)null);
					}
				}
			}
		}

		return this.collidingBoundingBoxes;
	}

	public int calculateSkylightSubtracted(float par1)
	{
		float f1 = this.getCelestialAngle(par1);
		float f2 = 1.0F - (MathHelper.cos(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F);

		if (f2 < 0.0F)
		{
			f2 = 0.0F;
		}

		if (f2 > 1.0F)
		{
			f2 = 1.0F;
		}

		f2 = 1.0F - f2;
		f2 = (float)((double)f2 * (1.0D - (double)(this.getRainStrength(par1) * 5.0F) / 16.0D));
		f2 = (float)((double)f2 * (1.0D - (double)(this.getWeightedThunderStrength(par1) * 5.0F) / 16.0D));
		f2 = 1.0F - f2;
		return (int)(f2 * 11.0F);
	}

	public void removeWorldAccess(IWorldAccess par1IWorldAccess)
	{
		this.worldAccesses.remove(par1IWorldAccess);
	}

	@SideOnly(Side.CLIENT)
	public float getSunBrightness(float par1)
	{
		float f1 = this.getCelestialAngle(par1);
		float f2 = 1.0F - (MathHelper.cos(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.2F);

		if (f2 < 0.0F)
		{
			f2 = 0.0F;
		}

		if (f2 > 1.0F)
		{
			f2 = 1.0F;
		}

		f2 = 1.0F - f2;
		f2 = (float)((double)f2 * (1.0D - (double)(this.getRainStrength(par1) * 5.0F) / 16.0D));
		f2 = (float)((double)f2 * (1.0D - (double)(this.getWeightedThunderStrength(par1) * 5.0F) / 16.0D));
		return f2 * 0.8F + 0.2F;
	}

	@SideOnly(Side.CLIENT)
	public Vec3 getSkyColor(Entity par1Entity, float par2)
	{
		return provider.getSkyColor(par1Entity, par2);
	}

	@SideOnly(Side.CLIENT)
	public Vec3 getSkyColorBody(Entity par1Entity, float par2)
	{
		float f1 = this.getCelestialAngle(par2);
		float f2 = MathHelper.cos(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;

		if (f2 < 0.0F)
		{
			f2 = 0.0F;
		}

		if (f2 > 1.0F)
		{
			f2 = 1.0F;
		}

		int i = MathHelper.floor_double(par1Entity.posX);
		int j = MathHelper.floor_double(par1Entity.posY);
		int k = MathHelper.floor_double(par1Entity.posZ);
		int l = ForgeHooksClient.getSkyBlendColour(this, i, j, k);
		float f4 = (float)(l >> 16 & 255) / 255.0F;
		float f5 = (float)(l >> 8 & 255) / 255.0F;
		float f6 = (float)(l & 255) / 255.0F;
		f4 *= f2;
		f5 *= f2;
		f6 *= f2;
		float f7 = this.getRainStrength(par2);
		float f8;
		float f9;

		if (f7 > 0.0F)
		{
			f8 = (f4 * 0.3F + f5 * 0.59F + f6 * 0.11F) * 0.6F;
			f9 = 1.0F - f7 * 0.75F;
			f4 = f4 * f9 + f8 * (1.0F - f9);
			f5 = f5 * f9 + f8 * (1.0F - f9);
			f6 = f6 * f9 + f8 * (1.0F - f9);
		}

		f8 = this.getWeightedThunderStrength(par2);

		if (f8 > 0.0F)
		{
			f9 = (f4 * 0.3F + f5 * 0.59F + f6 * 0.11F) * 0.2F;
			float f10 = 1.0F - f8 * 0.75F;
			f4 = f4 * f10 + f9 * (1.0F - f10);
			f5 = f5 * f10 + f9 * (1.0F - f10);
			f6 = f6 * f10 + f9 * (1.0F - f10);
		}

		if (this.lastLightningBolt > 0)
		{
			f9 = (float)this.lastLightningBolt - par2;

			if (f9 > 1.0F)
			{
				f9 = 1.0F;
			}

			f9 *= 0.45F;
			f4 = f4 * (1.0F - f9) + 0.8F * f9;
			f5 = f5 * (1.0F - f9) + 0.8F * f9;
			f6 = f6 * (1.0F - f9) + 1.0F * f9;
		}

		return this.getWorldVec3Pool().getVecFromPool((double)f4, (double)f5, (double)f6);
	}

	public float getCelestialAngle(float par1)
	{
		return this.provider.calculateCelestialAngle(this.worldInfo.getWorldTime(), par1);
	}

	@SideOnly(Side.CLIENT)
	public int getMoonPhase()
	{
		return this.provider.getMoonPhase(this.worldInfo.getWorldTime());
	}

	public float getCurrentMoonPhaseFactor()
	{
		return WorldProvider.moonPhaseFactors[this.provider.getMoonPhase(this.worldInfo.getWorldTime())];
	}

	public float getCelestialAngleRadians(float par1)
	{
		float f1 = this.getCelestialAngle(par1);
		return f1 * (float)Math.PI * 2.0F;
	}

	@SideOnly(Side.CLIENT)
	public Vec3 getCloudColour(float par1)
	{
		return provider.drawClouds(par1);
	}

	@SideOnly(Side.CLIENT)
	public Vec3 drawCloudsBody(float par1)
	{
		float f1 = this.getCelestialAngle(par1);
		float f2 = MathHelper.cos(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;

		if (f2 < 0.0F)
		{
			f2 = 0.0F;
		}

		if (f2 > 1.0F)
		{
			f2 = 1.0F;
		}

		float f3 = (float)(this.cloudColour >> 16 & 255L) / 255.0F;
		float f4 = (float)(this.cloudColour >> 8 & 255L) / 255.0F;
		float f5 = (float)(this.cloudColour & 255L) / 255.0F;
		float f6 = this.getRainStrength(par1);
		float f7;
		float f8;

		if (f6 > 0.0F)
		{
			f7 = (f3 * 0.3F + f4 * 0.59F + f5 * 0.11F) * 0.6F;
			f8 = 1.0F - f6 * 0.95F;
			f3 = f3 * f8 + f7 * (1.0F - f8);
			f4 = f4 * f8 + f7 * (1.0F - f8);
			f5 = f5 * f8 + f7 * (1.0F - f8);
		}

		f3 *= f2 * 0.9F + 0.1F;
		f4 *= f2 * 0.9F + 0.1F;
		f5 *= f2 * 0.85F + 0.15F;
		f7 = this.getWeightedThunderStrength(par1);

		if (f7 > 0.0F)
		{
			f8 = (f3 * 0.3F + f4 * 0.59F + f5 * 0.11F) * 0.2F;
			float f9 = 1.0F - f7 * 0.95F;
			f3 = f3 * f9 + f8 * (1.0F - f9);
			f4 = f4 * f9 + f8 * (1.0F - f9);
			f5 = f5 * f9 + f8 * (1.0F - f9);
		}

		return this.getWorldVec3Pool().getVecFromPool((double)f3, (double)f4, (double)f5);
	}

	@SideOnly(Side.CLIENT)
	public Vec3 getFogColor(float par1)
	{
		float f1 = this.getCelestialAngle(par1);
		return this.provider.getFogColor(f1, par1);
	}

	public int getPrecipitationHeight(int par1, int par2)
	{
		return this.getChunkFromBlockCoords(par1, par2).getPrecipitationHeight(par1 & 15, par2 & 15);
	}

	public int getTopSolidOrLiquidBlock(int par1, int par2)
	{
		Chunk chunk = this.getChunkFromBlockCoords(par1, par2);
		int x = par1;
		int z = par2;
		int k = chunk.getTopFilledSegment() + 15;
		par1 &= 15;

		for (par2 &= 15; k > 0; --k)
		{
			Block block = chunk.getBlock(par1, k, par2);

			if (block.getMaterial().blocksMovement() && block.getMaterial() != Material.leaves && !block.isFoliage(this, x, k, z))
			{
				return k + 1;
			}
		}

		return -1;
	}

	@SideOnly(Side.CLIENT)
	public float getStarBrightness(float par1)
	{
		return provider.getStarBrightness(par1);
	}

	@SideOnly(Side.CLIENT)
	public float getStarBrightnessBody(float par1)
	{
		float f1 = this.getCelestialAngle(par1);
		float f2 = 1.0F - (MathHelper.cos(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.25F);

		if (f2 < 0.0F)
		{
			f2 = 0.0F;
		}

		if (f2 > 1.0F)
		{
			f2 = 1.0F;
		}

		return f2 * f2 * 0.5F;
	}

	public void scheduleBlockUpdate(int p_147464_1_, int p_147464_2_, int p_147464_3_, Block p_147464_4_, int p_147464_5_) {}

	public void scheduleBlockUpdateWithPriority(int p_147454_1_, int p_147454_2_, int p_147454_3_, Block p_147454_4_, int p_147454_5_, int p_147454_6_) {}

	public void func_147446_b(int p_147446_1_, int p_147446_2_, int p_147446_3_, Block p_147446_4_, int p_147446_5_, int p_147446_6_) {}

	public void updateEntities()
	{
		this.theProfiler.startSection("entities");
		this.theProfiler.startSection("global");
		int i;
		Entity entity;
		CrashReport crashreport;
		CrashReportCategory crashreportcategory;

		for (i = 0; i < this.weatherEffects.size(); ++i)
		{
			entity = (Entity)this.weatherEffects.get(i);

			try
			{
				++entity.ticksExisted;
				entity.onUpdate();
			}
			catch (Throwable throwable2)
			{
				crashreport = CrashReport.makeCrashReport(throwable2, "Ticking entity");
				crashreportcategory = crashreport.makeCategory("Entity being ticked");

				if (entity == null)
				{
					crashreportcategory.addCrashSection("Entity", "~~NULL~~");
				}
				else
				{
					entity.addEntityCrashInfo(crashreportcategory);
				}

				if (ForgeModContainer.removeErroringEntities)
				{
					FMLLog.severe(crashreport.getCompleteReport());
					removeEntity(entity);
				}
				else
				{
					throw new ReportedException(crashreport);
				}
			}

			if (entity.isDead)
			{
				this.weatherEffects.remove(i--);
			}
		}

		this.theProfiler.endStartSection("remove");
		this.loadedEntityList.removeAll(this.unloadedEntityList);
		int j;
		int l;

		for (i = 0; i < this.unloadedEntityList.size(); ++i)
		{
			entity = (Entity)this.unloadedEntityList.get(i);
			j = entity.chunkCoordX;
			l = entity.chunkCoordZ;

			if (entity.addedToChunk && this.chunkExists(j, l))
			{
				this.getChunkFromChunkCoords(j, l).removeEntity(entity);
			}
		}

		for (i = 0; i < this.unloadedEntityList.size(); ++i)
		{
			this.onEntityRemoved((Entity)this.unloadedEntityList.get(i));
		}

		this.unloadedEntityList.clear();
		this.theProfiler.endStartSection("regular");

		for (i = 0; i < this.loadedEntityList.size(); ++i)
		{
			entity = (Entity)this.loadedEntityList.get(i);

			if (entity.ridingEntity != null)
			{
				if (!entity.ridingEntity.isDead && entity.ridingEntity.riddenByEntity == entity)
				{
					continue;
				}

				entity.ridingEntity.riddenByEntity = null;
				entity.ridingEntity = null;
			}

			this.theProfiler.startSection("tick");

			if (!entity.isDead)
			{
				try
				{
					this.updateEntity(entity);
				}
				catch (Throwable throwable1)
				{
					crashreport = CrashReport.makeCrashReport(throwable1, "Ticking entity");
					crashreportcategory = crashreport.makeCategory("Entity being ticked");
					entity.addEntityCrashInfo(crashreportcategory);

					if (ForgeModContainer.removeErroringEntities)
					{
						FMLLog.severe(crashreport.getCompleteReport());
						removeEntity(entity);
					}
					else
					{
						throw new ReportedException(crashreport);
					}
				}
			}

			this.theProfiler.endSection();
			this.theProfiler.startSection("remove");

			if (entity.isDead)
			{
				j = entity.chunkCoordX;
				l = entity.chunkCoordZ;

				if (entity.addedToChunk && this.chunkExists(j, l))
				{
					this.getChunkFromChunkCoords(j, l).removeEntity(entity);
				}

				this.loadedEntityList.remove(i--);
				this.onEntityRemoved(entity);
			}

			this.theProfiler.endSection();
		}

		this.theProfiler.endStartSection("blockEntities");
		this.field_147481_N = true;
		Iterator iterator = this.loadedTileEntityList.iterator();

		while (iterator.hasNext())
		{
			TileEntity tileentity = (TileEntity)iterator.next();

			if (!tileentity.isInvalid() && tileentity.hasWorldObj() && this.blockExists(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord))
			{
				try
				{
					tileentity.updateEntity();
				}
				catch (Throwable throwable)
				{
					crashreport = CrashReport.makeCrashReport(throwable, "Ticking block entity");
					crashreportcategory = crashreport.makeCategory("Block entity being ticked");
					tileentity.func_145828_a(crashreportcategory);
					if (ForgeModContainer.removeErroringTileEntities)
					{
						FMLLog.severe(crashreport.getCompleteReport());
						tileentity.invalidate();
						setBlockToAir(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord);
					}
					else
					{
						throw new ReportedException(crashreport);
					}
				}
			}

			if (tileentity.isInvalid())
			{
				iterator.remove();

				if (this.chunkExists(tileentity.xCoord >> 4, tileentity.zCoord >> 4))
				{
					Chunk chunk = this.getChunkFromChunkCoords(tileentity.xCoord >> 4, tileentity.zCoord >> 4);

					if (chunk != null)
					{
						chunk.removeInvalidTileEntity(tileentity.xCoord & 15, tileentity.yCoord, tileentity.zCoord & 15);
					}
				}
			}
		}

		if (!this.field_147483_b.isEmpty())
		{
			for (Object tile : field_147483_b)
			{
			   ((TileEntity)tile).onChunkUnload();
			}
			this.loadedTileEntityList.removeAll(this.field_147483_b);
			this.field_147483_b.clear();
		}

		this.field_147481_N = false;

		this.theProfiler.endStartSection("pendingBlockEntities");

		if (!this.addedTileEntityList.isEmpty())
		{
			for (int k = 0; k < this.addedTileEntityList.size(); ++k)
			{
				TileEntity tileentity1 = (TileEntity)this.addedTileEntityList.get(k);

				if (!tileentity1.isInvalid())
				{
					if (!this.loadedTileEntityList.contains(tileentity1))
					{
						this.loadedTileEntityList.add(tileentity1);
					}
				}
				else
				{
					if (this.chunkExists(tileentity1.xCoord >> 4, tileentity1.zCoord >> 4))
					{
						Chunk chunk1 = this.getChunkFromChunkCoords(tileentity1.xCoord >> 4, tileentity1.zCoord >> 4);

						if (chunk1 != null)
						{
							chunk1.removeInvalidTileEntity(tileentity1.xCoord & 15, tileentity1.yCoord, tileentity1.zCoord & 15);
						}
					}
				}
			}

			this.addedTileEntityList.clear();
		}

		this.theProfiler.endSection();
		this.theProfiler.endSection();
	}

	public void func_147448_a(Collection p_147448_1_)
	{
		List dest = field_147481_N ? addedTileEntityList : loadedTileEntityList;
		for(TileEntity entity : (Collection<TileEntity>)p_147448_1_)
		{
			if(entity.canUpdate()) dest.add(entity);
		}
	}

	public void updateEntity(Entity par1Entity)
	{
		this.updateEntityWithOptionalForce(par1Entity, true);
	}

	public void updateEntityWithOptionalForce(Entity par1Entity, boolean par2)
	{
		int i = MathHelper.floor_double(par1Entity.posX);
		int j = MathHelper.floor_double(par1Entity.posZ);
		boolean isForced = getPersistentChunks().containsKey(new ChunkCoordIntPair(i >> 4, j >> 4));
		byte b0 = isForced ? (byte)0 : 32;
		boolean canUpdate = !par2 || this.checkChunksExist(i - b0, 0, j - b0, i + b0, 0, j + b0);

		if (!canUpdate)
		{
			EntityEvent.CanUpdate event = new EntityEvent.CanUpdate(par1Entity);
			MinecraftForge.EVENT_BUS.post(event);
			canUpdate = event.canUpdate;
		}

		if (canUpdate)
		{
			par1Entity.lastTickPosX = par1Entity.posX;
			par1Entity.lastTickPosY = par1Entity.posY;
			par1Entity.lastTickPosZ = par1Entity.posZ;
			par1Entity.prevRotationYaw = par1Entity.rotationYaw;
			par1Entity.prevRotationPitch = par1Entity.rotationPitch;

			if (par2 && par1Entity.addedToChunk)
			{
				++par1Entity.ticksExisted;

				if (par1Entity.ridingEntity != null)
				{
					par1Entity.updateRidden();
				}
				else
				{
					par1Entity.onUpdate();
				}
			}

			this.theProfiler.startSection("chunkCheck");

			if (Double.isNaN(par1Entity.posX) || Double.isInfinite(par1Entity.posX))
			{
				par1Entity.posX = par1Entity.lastTickPosX;
			}

			if (Double.isNaN(par1Entity.posY) || Double.isInfinite(par1Entity.posY))
			{
				par1Entity.posY = par1Entity.lastTickPosY;
			}

			if (Double.isNaN(par1Entity.posZ) || Double.isInfinite(par1Entity.posZ))
			{
				par1Entity.posZ = par1Entity.lastTickPosZ;
			}

			if (Double.isNaN((double)par1Entity.rotationPitch) || Double.isInfinite((double)par1Entity.rotationPitch))
			{
				par1Entity.rotationPitch = par1Entity.prevRotationPitch;
			}

			if (Double.isNaN((double)par1Entity.rotationYaw) || Double.isInfinite((double)par1Entity.rotationYaw))
			{
				par1Entity.rotationYaw = par1Entity.prevRotationYaw;
			}

			int k = MathHelper.floor_double(par1Entity.posX / 16.0D);
			int l = MathHelper.floor_double(par1Entity.posY / 16.0D);
			int i1 = MathHelper.floor_double(par1Entity.posZ / 16.0D);

			if (!par1Entity.addedToChunk || par1Entity.chunkCoordX != k || par1Entity.chunkCoordY != l || par1Entity.chunkCoordZ != i1)
			{
				if (par1Entity.addedToChunk && this.chunkExists(par1Entity.chunkCoordX, par1Entity.chunkCoordZ))
				{
					this.getChunkFromChunkCoords(par1Entity.chunkCoordX, par1Entity.chunkCoordZ).removeEntityAtIndex(par1Entity, par1Entity.chunkCoordY);
				}

				if (this.chunkExists(k, i1))
				{
					par1Entity.addedToChunk = true;
					this.getChunkFromChunkCoords(k, i1).addEntity(par1Entity);
				}
				else
				{
					par1Entity.addedToChunk = false;
				}
			}

			this.theProfiler.endSection();

			if (par2 && par1Entity.addedToChunk && par1Entity.riddenByEntity != null)
			{
				if (!par1Entity.riddenByEntity.isDead && par1Entity.riddenByEntity.ridingEntity == par1Entity)
				{
					this.updateEntity(par1Entity.riddenByEntity);
				}
				else
				{
					par1Entity.riddenByEntity.ridingEntity = null;
					par1Entity.riddenByEntity = null;
				}
			}
		}
	}

	public boolean checkNoEntityCollision(AxisAlignedBB par1AxisAlignedBB)
	{
		return this.checkNoEntityCollision(par1AxisAlignedBB, (Entity)null);
	}

	public boolean checkNoEntityCollision(AxisAlignedBB par1AxisAlignedBB, Entity par2Entity)
	{
		List list = this.getEntitiesWithinAABBExcludingEntity((Entity)null, par1AxisAlignedBB);

		for (int i = 0; i < list.size(); ++i)
		{
			Entity entity1 = (Entity)list.get(i);

			if (!entity1.isDead && entity1.preventEntitySpawning && entity1 != par2Entity)
			{
				return false;
			}
		}

		return true;
	}

	public boolean checkBlockCollision(AxisAlignedBB par1AxisAlignedBB)
	{
		int i = MathHelper.floor_double(par1AxisAlignedBB.minX);
		int j = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
		int k = MathHelper.floor_double(par1AxisAlignedBB.minY);
		int l = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
		int i1 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
		int j1 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);

		if (par1AxisAlignedBB.minX < 0.0D)
		{
			--i;
		}

		if (par1AxisAlignedBB.minY < 0.0D)
		{
			--k;
		}

		if (par1AxisAlignedBB.minZ < 0.0D)
		{
			--i1;
		}

		for (int k1 = i; k1 < j; ++k1)
		{
			for (int l1 = k; l1 < l; ++l1)
			{
				for (int i2 = i1; i2 < j1; ++i2)
				{
					Block block = this.getBlock(k1, l1, i2);

					if (block.getMaterial() != Material.air)
					{
						return true;
					}
				}
			}
		}

		return false;
	}

	public boolean isAnyLiquid(AxisAlignedBB par1AxisAlignedBB)
	{
		int i = MathHelper.floor_double(par1AxisAlignedBB.minX);
		int j = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
		int k = MathHelper.floor_double(par1AxisAlignedBB.minY);
		int l = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
		int i1 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
		int j1 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);

		if (par1AxisAlignedBB.minX < 0.0D)
		{
			--i;
		}

		if (par1AxisAlignedBB.minY < 0.0D)
		{
			--k;
		}

		if (par1AxisAlignedBB.minZ < 0.0D)
		{
			--i1;
		}

		for (int k1 = i; k1 < j; ++k1)
		{
			for (int l1 = k; l1 < l; ++l1)
			{
				for (int i2 = i1; i2 < j1; ++i2)
				{
					Block block = this.getBlock(k1, l1, i2);

					if (block.getMaterial().isLiquid())
					{
						return true;
					}
				}
			}
		}

		return false;
	}

	public boolean func_147470_e(AxisAlignedBB p_147470_1_)
	{
		int i = MathHelper.floor_double(p_147470_1_.minX);
		int j = MathHelper.floor_double(p_147470_1_.maxX + 1.0D);
		int k = MathHelper.floor_double(p_147470_1_.minY);
		int l = MathHelper.floor_double(p_147470_1_.maxY + 1.0D);
		int i1 = MathHelper.floor_double(p_147470_1_.minZ);
		int j1 = MathHelper.floor_double(p_147470_1_.maxZ + 1.0D);

		if (this.checkChunksExist(i, k, i1, j, l, j1))
		{
			for (int k1 = i; k1 < j; ++k1)
			{
				for (int l1 = k; l1 < l; ++l1)
				{
					for (int i2 = i1; i2 < j1; ++i2)
					{
						Block block = this.getBlock(k1, l1, i2);

						if (block == Blocks.fire || block == Blocks.flowing_lava || block == Blocks.lava)
						{
							return true;
						}
						else
						{
							if (block.isBurning(this, k1, l1, i2)) return true;
						}
					}
				}
			}
		}

		return false;
	}

	public boolean handleMaterialAcceleration(AxisAlignedBB par1AxisAlignedBB, Material par2Material, Entity par3Entity)
	{
		int i = MathHelper.floor_double(par1AxisAlignedBB.minX);
		int j = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
		int k = MathHelper.floor_double(par1AxisAlignedBB.minY);
		int l = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
		int i1 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
		int j1 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);

		if (!this.checkChunksExist(i, k, i1, j, l, j1))
		{
			return false;
		}
		else
		{
			boolean flag = false;
			Vec3 vec3 = this.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D);

			for (int k1 = i; k1 < j; ++k1)
			{
				for (int l1 = k; l1 < l; ++l1)
				{
					for (int i2 = i1; i2 < j1; ++i2)
					{
						Block block = this.getBlock(k1, l1, i2);

						if (block.getMaterial() == par2Material)
						{
							double d0 = (double)((float)(l1 + 1) - BlockLiquid.getLiquidHeightPercent(this.getBlockMetadata(k1, l1, i2)));

							if ((double)l >= d0)
							{
								flag = true;
								block.velocityToAddToEntity(this, k1, l1, i2, par3Entity, vec3);
							}
						}
					}
				}
			}

			if (vec3.lengthVector() > 0.0D && par3Entity.isPushedByWater())
			{
				vec3 = vec3.normalize();
				double d1 = 0.014D;
				par3Entity.motionX += vec3.xCoord * d1;
				par3Entity.motionY += vec3.yCoord * d1;
				par3Entity.motionZ += vec3.zCoord * d1;
			}

			return flag;
		}
	}

	public boolean isMaterialInBB(AxisAlignedBB par1AxisAlignedBB, Material par2Material)
	{
		int i = MathHelper.floor_double(par1AxisAlignedBB.minX);
		int j = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
		int k = MathHelper.floor_double(par1AxisAlignedBB.minY);
		int l = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
		int i1 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
		int j1 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);

		for (int k1 = i; k1 < j; ++k1)
		{
			for (int l1 = k; l1 < l; ++l1)
			{
				for (int i2 = i1; i2 < j1; ++i2)
				{
					if (this.getBlock(k1, l1, i2).getMaterial() == par2Material)
					{
						return true;
					}
				}
			}
		}

		return false;
	}

	public boolean isAABBInMaterial(AxisAlignedBB par1AxisAlignedBB, Material par2Material)
	{
		int i = MathHelper.floor_double(par1AxisAlignedBB.minX);
		int j = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
		int k = MathHelper.floor_double(par1AxisAlignedBB.minY);
		int l = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
		int i1 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
		int j1 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);

		for (int k1 = i; k1 < j; ++k1)
		{
			for (int l1 = k; l1 < l; ++l1)
			{
				for (int i2 = i1; i2 < j1; ++i2)
				{
					Block block = this.getBlock(k1, l1, i2);

					if (block.getMaterial() == par2Material)
					{
						int j2 = this.getBlockMetadata(k1, l1, i2);
						double d0 = (double)(l1 + 1);

						if (j2 < 8)
						{
							d0 = (double)(l1 + 1) - (double)j2 / 8.0D;
						}

						if (d0 >= par1AxisAlignedBB.minY)
						{
							return true;
						}
					}
				}
			}
		}

		return false;
	}

	public Explosion createExplosion(Entity par1Entity, double par2, double par4, double par6, float par8, boolean par9)
	{
		return this.newExplosion(par1Entity, par2, par4, par6, par8, false, par9);
	}

	public Explosion newExplosion(Entity par1Entity, double par2, double par4, double par6, float par8, boolean par9, boolean par10)
	{
		Explosion explosion = new Explosion(this, par1Entity, par2, par4, par6, par8);
		explosion.isFlaming = par9;
		explosion.isSmoking = par10;
		explosion.doExplosionA();
		explosion.doExplosionB(true);
		return explosion;
	}

	public float getBlockDensity(Vec3 par1Vec3, AxisAlignedBB par2AxisAlignedBB)
	{
		double d0 = 1.0D / ((par2AxisAlignedBB.maxX - par2AxisAlignedBB.minX) * 2.0D + 1.0D);
		double d1 = 1.0D / ((par2AxisAlignedBB.maxY - par2AxisAlignedBB.minY) * 2.0D + 1.0D);
		double d2 = 1.0D / ((par2AxisAlignedBB.maxZ - par2AxisAlignedBB.minZ) * 2.0D + 1.0D);
		int i = 0;
		int j = 0;

		for (float f = 0.0F; f <= 1.0F; f = (float)((double)f + d0))
		{
			for (float f1 = 0.0F; f1 <= 1.0F; f1 = (float)((double)f1 + d1))
			{
				for (float f2 = 0.0F; f2 <= 1.0F; f2 = (float)((double)f2 + d2))
				{
					double d3 = par2AxisAlignedBB.minX + (par2AxisAlignedBB.maxX - par2AxisAlignedBB.minX) * (double)f;
					double d4 = par2AxisAlignedBB.minY + (par2AxisAlignedBB.maxY - par2AxisAlignedBB.minY) * (double)f1;
					double d5 = par2AxisAlignedBB.minZ + (par2AxisAlignedBB.maxZ - par2AxisAlignedBB.minZ) * (double)f2;

					if (this.rayTraceBlocks(this.getWorldVec3Pool().getVecFromPool(d3, d4, d5), par1Vec3) == null)
					{
						++i;
					}

					++j;
				}
			}
		}

		return (float)i / (float)j;
	}

	public boolean extinguishFire(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5)
	{
		if (par5 == 0)
		{
			--par3;
		}

		if (par5 == 1)
		{
			++par3;
		}

		if (par5 == 2)
		{
			--par4;
		}

		if (par5 == 3)
		{
			++par4;
		}

		if (par5 == 4)
		{
			--par2;
		}

		if (par5 == 5)
		{
			++par2;
		}

		if (this.getBlock(par2, par3, par4) == Blocks.fire)
		{
			this.playAuxSFXAtEntity(par1EntityPlayer, 1004, par2, par3, par4, 0);
			this.setBlockToAir(par2, par3, par4);
			return true;
		}
		else
		{
			return false;
		}
	}

	@SideOnly(Side.CLIENT)
	public String getDebugLoadedEntities()
	{
		return "All: " + this.loadedEntityList.size();
	}

	@SideOnly(Side.CLIENT)
	public String getProviderName()
	{
		return this.chunkProvider.makeString();
	}

	public TileEntity getTileEntity(int p_147438_1_, int p_147438_2_, int p_147438_3_)
	{
		if (p_147438_2_ >= 0 && p_147438_2_ < 256)
		{
			TileEntity tileentity = null;
			int l;
			TileEntity tileentity1;

			if (this.field_147481_N)
			{
				for (l = 0; l < this.addedTileEntityList.size(); ++l)
				{
					tileentity1 = (TileEntity)this.addedTileEntityList.get(l);

					if (!tileentity1.isInvalid() && tileentity1.xCoord == p_147438_1_ && tileentity1.yCoord == p_147438_2_ && tileentity1.zCoord == p_147438_3_)
					{
						tileentity = tileentity1;
						break;
					}
				}
			}

			if (tileentity == null)
			{
				Chunk chunk = this.getChunkFromChunkCoords(p_147438_1_ >> 4, p_147438_3_ >> 4);

				if (chunk != null)
				{
					tileentity = chunk.func_150806_e(p_147438_1_ & 15, p_147438_2_, p_147438_3_ & 15);
				}
			}

			if (tileentity == null)
			{
				for (l = 0; l < this.addedTileEntityList.size(); ++l)
				{
					tileentity1 = (TileEntity)this.addedTileEntityList.get(l);

					if (!tileentity1.isInvalid() && tileentity1.xCoord == p_147438_1_ && tileentity1.yCoord == p_147438_2_ && tileentity1.zCoord == p_147438_3_)
					{
						tileentity = tileentity1;
						break;
					}
				}
			}

			return tileentity;
		}
		else
		{
			return null;
		}
	}

	public void setTileEntity(int p_147455_1_, int p_147455_2_, int p_147455_3_, TileEntity p_147455_4_)
	{
		if (p_147455_4_ == null || p_147455_4_.isInvalid())
		{
			return;
		}

		if (p_147455_4_.canUpdate())
		{
			if (this.field_147481_N)
			{
				Iterator iterator = this.addedTileEntityList.iterator();

				while (iterator.hasNext())
				{
					TileEntity tileentity1 = (TileEntity)iterator.next();

					if (tileentity1.xCoord == p_147455_1_ && tileentity1.yCoord == p_147455_2_ && tileentity1.zCoord == p_147455_3_)
					{
						tileentity1.invalidate();
						iterator.remove();
					}
				}

				this.addedTileEntityList.add(p_147455_4_);
			}
			else
			{
				this.loadedTileEntityList.add(p_147455_4_);
			}
		}
		Chunk chunk = this.getChunkFromChunkCoords(p_147455_1_ >> 4, p_147455_3_ >> 4);
		if (chunk != null)
		{
			chunk.func_150812_a(p_147455_1_ & 15, p_147455_2_, p_147455_3_ & 15, p_147455_4_);
		}
		//notify tile changes
		func_147453_f(p_147455_1_, p_147455_2_, p_147455_3_, getBlock(p_147455_1_, p_147455_2_, p_147455_3_));
	}

	public void removeTileEntity(int p_147475_1_, int p_147475_2_, int p_147475_3_)
	{
		Chunk chunk = getChunkFromChunkCoords(p_147475_1_ >> 4, p_147475_3_ >> 4);
		if (chunk != null) chunk.removeTileEntity(p_147475_1_ & 15, p_147475_2_, p_147475_3_ & 15);
		func_147453_f(p_147475_1_, p_147475_2_, p_147475_3_, getBlock(p_147475_1_, p_147475_2_, p_147475_3_));
	}

	public void func_147457_a(TileEntity p_147457_1_)
	{
		this.field_147483_b.add(p_147457_1_);
	}

	public boolean func_147469_q(int p_147469_1_, int p_147469_2_, int p_147469_3_)
	{
		AxisAlignedBB axisalignedbb = this.getBlock(p_147469_1_, p_147469_2_, p_147469_3_).getCollisionBoundingBoxFromPool(this, p_147469_1_, p_147469_2_, p_147469_3_);
		return axisalignedbb != null && axisalignedbb.getAverageEdgeLength() >= 1.0D;
	}

	public static boolean doesBlockHaveSolidTopSurface(IBlockAccess p_147466_0_, int p_147466_1_, int p_147466_2_, int p_147466_3_)
	{
		Block block = p_147466_0_.getBlock(p_147466_1_, p_147466_2_, p_147466_3_);
		return block.isSideSolid(p_147466_0_, p_147466_1_, p_147466_2_, p_147466_3_, ForgeDirection.UP);
	}

	public boolean isBlockNormalCubeDefault(int p_147445_1_, int p_147445_2_, int p_147445_3_, boolean p_147445_4_)
	{
		if (p_147445_1_ >= -30000000 && p_147445_3_ >= -30000000 && p_147445_1_ < 30000000 && p_147445_3_ < 30000000)
		{
			Chunk chunk = this.chunkProvider.provideChunk(p_147445_1_ >> 4, p_147445_3_ >> 4);

			if (chunk != null && !chunk.isEmpty())
			{
				Block block = this.getBlock(p_147445_1_, p_147445_2_, p_147445_3_);
				return block.isNormalCube(this, p_147445_1_, p_147445_2_, p_147445_3_);
			}
			else
			{
				return p_147445_4_;
			}
		}
		else
		{
			return p_147445_4_;
		}
	}

	public void calculateInitialSkylight()
	{
		int i = this.calculateSkylightSubtracted(1.0F);

		if (i != this.skylightSubtracted)
		{
			this.skylightSubtracted = i;
		}
	}

	public void setAllowedSpawnTypes(boolean par1, boolean par2)
	{
		provider.setAllowedSpawnTypes(par1, par2);
	}

	public void tick()
	{
		this.updateWeather();
	}

	private void calculateInitialWeather()
	{
		provider.calculateInitialWeather();
	}

	public void calculateInitialWeatherBody()
	{
		if (this.worldInfo.isRaining())
		{
			this.rainingStrength = 1.0F;

			if (this.worldInfo.isThundering())
			{
				this.thunderingStrength = 1.0F;
			}
		}
	}

	protected void updateWeather()
	{
		provider.updateWeather();
	}

	public void updateWeatherBody()
	{
		if (!this.provider.hasNoSky)
		{
			if (!this.isRemote)
			{
				int i = this.worldInfo.getThunderTime();

				if (i <= 0)
				{
					if (this.worldInfo.isThundering())
					{
						this.worldInfo.setThunderTime(this.rand.nextInt(12000) + 3600);
					}
					else
					{
						this.worldInfo.setThunderTime(this.rand.nextInt(168000) + 12000);
					}
				}
				else
				{
					--i;
					this.worldInfo.setThunderTime(i);

					if (i <= 0)
					{
						this.worldInfo.setThundering(!this.worldInfo.isThundering());
					}
				}

				this.prevThunderingStrength = this.thunderingStrength;

				if (this.worldInfo.isThundering())
				{
					this.thunderingStrength = (float)((double)this.thunderingStrength + 0.01D);
				}
				else
				{
					this.thunderingStrength = (float)((double)this.thunderingStrength - 0.01D);
				}

				this.thunderingStrength = MathHelper.clamp_float(this.thunderingStrength, 0.0F, 1.0F);
				int j = this.worldInfo.getRainTime();

				if (j <= 0)
				{
					if (this.worldInfo.isRaining())
					{
						this.worldInfo.setRainTime(this.rand.nextInt(12000) + 12000);
					}
					else
					{
						this.worldInfo.setRainTime(this.rand.nextInt(168000) + 12000);
					}
				}
				else
				{
					--j;
					this.worldInfo.setRainTime(j);

					if (j <= 0)
					{
						this.worldInfo.setRaining(!this.worldInfo.isRaining());
					}
				}

				this.prevRainingStrength = this.rainingStrength;

				if (this.worldInfo.isRaining())
				{
					this.rainingStrength = (float)((double)this.rainingStrength + 0.01D);
				}
				else
				{
					this.rainingStrength = (float)((double)this.rainingStrength - 0.01D);
				}

				this.rainingStrength = MathHelper.clamp_float(this.rainingStrength, 0.0F, 1.0F);
			}
		}
	}

	protected void setActivePlayerChunksAndCheckLight()
	{
		this.activeChunkSet.clear();
		this.theProfiler.startSection("buildList");
		this.activeChunkSet.addAll(getPersistentChunks().keySet());
		int i;
		EntityPlayer entityplayer;
		int j;
		int k;

		for (i = 0; i < this.playerEntities.size(); ++i)
		{
			entityplayer = (EntityPlayer)this.playerEntities.get(i);
			j = MathHelper.floor_double(entityplayer.posX / 16.0D);
			k = MathHelper.floor_double(entityplayer.posZ / 16.0D);
			byte b0 = 7;

			for (int l = -b0; l <= b0; ++l)
			{
				for (int i1 = -b0; i1 <= b0; ++i1)
				{
					this.activeChunkSet.add(new ChunkCoordIntPair(l + j, i1 + k));
				}
			}
		}

		this.theProfiler.endSection();

		if (this.ambientTickCountdown > 0)
		{
			--this.ambientTickCountdown;
		}

		this.theProfiler.startSection("playerCheckLight");

		if (!this.playerEntities.isEmpty())
		{
			i = this.rand.nextInt(this.playerEntities.size());
			entityplayer = (EntityPlayer)this.playerEntities.get(i);
			j = MathHelper.floor_double(entityplayer.posX) + this.rand.nextInt(11) - 5;
			k = MathHelper.floor_double(entityplayer.posY) + this.rand.nextInt(11) - 5;
			int j1 = MathHelper.floor_double(entityplayer.posZ) + this.rand.nextInt(11) - 5;
			this.func_147451_t(j, k, j1);
		}

		this.theProfiler.endSection();
	}

	protected void func_147467_a(int p_147467_1_, int p_147467_2_, Chunk p_147467_3_)
	{
		this.theProfiler.endStartSection("moodSound");

		if (this.ambientTickCountdown == 0 && !this.isRemote)
		{
			this.updateLCG = this.updateLCG * 3 + 1013904223;
			int k = this.updateLCG >> 2;
			int l = k & 15;
			int i1 = k >> 8 & 15;
			int j1 = k >> 16 & 255;
			Block block = p_147467_3_.getBlock(l, j1, i1);
			l += p_147467_1_;
			i1 += p_147467_2_;

			if (block.getMaterial() == Material.air && this.getFullBlockLightValue(l, j1, i1) <= this.rand.nextInt(8) && this.getSavedLightValue(EnumSkyBlock.Sky, l, j1, i1) <= 0)
			{
				EntityPlayer entityplayer = this.getClosestPlayer((double)l + 0.5D, (double)j1 + 0.5D, (double)i1 + 0.5D, 8.0D);

				if (entityplayer != null && entityplayer.getDistanceSq((double)l + 0.5D, (double)j1 + 0.5D, (double)i1 + 0.5D) > 4.0D)
				{
					this.playSoundEffect((double)l + 0.5D, (double)j1 + 0.5D, (double)i1 + 0.5D, "ambient.cave.cave", 0.7F, 0.8F + this.rand.nextFloat() * 0.2F);
					this.ambientTickCountdown = this.rand.nextInt(12000) + 6000;
				}
			}
		}

		this.theProfiler.endStartSection("checkLight");
		p_147467_3_.enqueueRelightChecks();
	}

	protected void func_147456_g()
	{
		this.setActivePlayerChunksAndCheckLight();
	}

	public boolean isBlockFreezable(int par1, int par2, int par3)
	{
		return this.canBlockFreeze(par1, par2, par3, false);
	}

	public boolean isBlockFreezableNaturally(int par1, int par2, int par3)
	{
		return this.canBlockFreeze(par1, par2, par3, true);
	}

	public boolean canBlockFreeze(int par1, int par2, int par3, boolean par4)
	{
		return provider.canBlockFreeze(par1, par2, par3, par4);
	}

	public boolean canBlockFreezeBody(int par1, int par2, int par3, boolean par4)
	{
		BiomeGenBase biomegenbase = this.getBiomeGenForCoords(par1, par3);
		float f = biomegenbase.getFloatTemperature(par1, par2, par3);

		if (f > 0.15F)
		{
			return false;
		}
		else
		{
			if (par2 >= 0 && par2 < 256 && this.getSavedLightValue(EnumSkyBlock.Block, par1, par2, par3) < 10)
			{
				Block block = this.getBlock(par1, par2, par3);

				if ((block == Blocks.water || block == Blocks.flowing_water) && this.getBlockMetadata(par1, par2, par3) == 0)
				{
					if (!par4)
					{
						return true;
					}

					boolean flag1 = true;

					if (flag1 && this.getBlock(par1 - 1, par2, par3).getMaterial() != Material.water)
					{
						flag1 = false;
					}

					if (flag1 && this.getBlock(par1 + 1, par2, par3).getMaterial() != Material.water)
					{
						flag1 = false;
					}

					if (flag1 && this.getBlock(par1, par2, par3 - 1).getMaterial() != Material.water)
					{
						flag1 = false;
					}

					if (flag1 && this.getBlock(par1, par2, par3 + 1).getMaterial() != Material.water)
					{
						flag1 = false;
					}

					if (!flag1)
					{
						return true;
					}
				}
			}

			return false;
		}
	}

	public boolean func_147478_e(int p_147478_1_, int p_147478_2_, int p_147478_3_, boolean p_147478_4_)
	{
		return provider.canSnowAt(p_147478_1_, p_147478_2_, p_147478_3_, p_147478_4_);
	}

	public boolean canSnowAtBody(int p_147478_1_, int p_147478_2_, int p_147478_3_, boolean p_147478_4_)
	{
		BiomeGenBase biomegenbase = this.getBiomeGenForCoords(p_147478_1_, p_147478_3_);
		float f = biomegenbase.getFloatTemperature(p_147478_1_, p_147478_2_, p_147478_3_);

		if (f > 0.15F)
		{
			return false;
		}
		else if (!p_147478_4_)
		{
			return true;
		}
		else
		{
			if (p_147478_2_ >= 0 && p_147478_2_ < 256 && this.getSavedLightValue(EnumSkyBlock.Block, p_147478_1_, p_147478_2_, p_147478_3_) < 10)
			{
				Block block = this.getBlock(p_147478_1_, p_147478_2_, p_147478_3_);

				if (block.getMaterial() == Material.air && Blocks.snow_layer.canPlaceBlockAt(this, p_147478_1_, p_147478_2_, p_147478_3_))
				{
					return true;
				}
			}

			return false;
		}
	}

	public boolean func_147451_t(int p_147451_1_, int p_147451_2_, int p_147451_3_)
	{
		boolean flag = false;

		if (!this.provider.hasNoSky)
		{
			flag |= this.updateLightByType(EnumSkyBlock.Sky, p_147451_1_, p_147451_2_, p_147451_3_);
		}

		flag |= this.updateLightByType(EnumSkyBlock.Block, p_147451_1_, p_147451_2_, p_147451_3_);
		return flag;
	}

	private int computeLightValue(int par1, int par2, int par3, EnumSkyBlock par4EnumSkyBlock)
	{
		if (par4EnumSkyBlock == EnumSkyBlock.Sky && this.canBlockSeeTheSky(par1, par2, par3))
		{
			return 15;
		}
		else
		{
			Block block = this.getBlock(par1, par2, par3);
			int blockLight = block.getLightValue(this, par1, par2, par3);
			int l = par4EnumSkyBlock == EnumSkyBlock.Sky ? 0 : blockLight;
			int i1 = block.getLightOpacity(this, par1, par2, par3);

			if (i1 >= 15 && blockLight > 0)
			{
				i1 = 1;
			}

			if (i1 < 1)
			{
				i1 = 1;
			}

			if (i1 >= 15)
			{
				return 0;
			}
			else if (l >= 14)
			{
				return l;
			}
			else
			{
				for (int j1 = 0; j1 < 6; ++j1)
				{
					int k1 = par1 + Facing.offsetsXForSide[j1];
					int l1 = par2 + Facing.offsetsYForSide[j1];
					int i2 = par3 + Facing.offsetsZForSide[j1];
					int j2 = this.getSavedLightValue(par4EnumSkyBlock, k1, l1, i2) - i1;

					if (j2 > l)
					{
						l = j2;
					}

					if (l >= 14)
					{
						return l;
					}
				}

				return l;
			}
		}
	}

	public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int p_147463_3_, int p_147463_4_)
	{
		if (!this.doChunksNearChunkExist(p_147463_2_, p_147463_3_, p_147463_4_, 17))
		{
			return false;
		}
		else
		{
			int l = 0;
			int i1 = 0;
			this.theProfiler.startSection("getBrightness");
			int j1 = this.getSavedLightValue(p_147463_1_, p_147463_2_, p_147463_3_, p_147463_4_);
			int k1 = this.computeLightValue(p_147463_2_, p_147463_3_, p_147463_4_, p_147463_1_);
			int l1;
			int i2;
			int j2;
			int k2;
			int l2;
			int i3;
			int j3;
			int k3;
			int l3;

			if (k1 > j1)
			{
				this.lightUpdateBlockList[i1++] = 133152;
			}
			else if (k1 < j1)
			{
				this.lightUpdateBlockList[i1++] = 133152 | j1 << 18;

				while (l < i1)
				{
					l1 = this.lightUpdateBlockList[l++];
					i2 = (l1 & 63) - 32 + p_147463_2_;
					j2 = (l1 >> 6 & 63) - 32 + p_147463_3_;
					k2 = (l1 >> 12 & 63) - 32 + p_147463_4_;
					l2 = l1 >> 18 & 15;
					i3 = this.getSavedLightValue(p_147463_1_, i2, j2, k2);

					if (i3 == l2)
					{
						this.setLightValue(p_147463_1_, i2, j2, k2, 0);

						if (l2 > 0)
						{
							j3 = MathHelper.abs_int(i2 - p_147463_2_);
							k3 = MathHelper.abs_int(j2 - p_147463_3_);
							l3 = MathHelper.abs_int(k2 - p_147463_4_);

							if (j3 + k3 + l3 < 17)
							{
								for (int i4 = 0; i4 < 6; ++i4)
								{
									int j4 = i2 + Facing.offsetsXForSide[i4];
									int k4 = j2 + Facing.offsetsYForSide[i4];
									int l4 = k2 + Facing.offsetsZForSide[i4];
									int i5 = Math.max(1, this.getBlock(j4, k4, l4).getLightOpacity(this, j4, k4, l4));
									i3 = this.getSavedLightValue(p_147463_1_, j4, k4, l4);

									if (i3 == l2 - i5 && i1 < this.lightUpdateBlockList.length)
									{
										this.lightUpdateBlockList[i1++] = j4 - p_147463_2_ + 32 | k4 - p_147463_3_ + 32 << 6 | l4 - p_147463_4_ + 32 << 12 | l2 - i5 << 18;
									}
								}
							}
						}
					}
				}

				l = 0;
			}

			this.theProfiler.endSection();
			this.theProfiler.startSection("checkedPosition < toCheckCount");

			while (l < i1)
			{
				l1 = this.lightUpdateBlockList[l++];
				i2 = (l1 & 63) - 32 + p_147463_2_;
				j2 = (l1 >> 6 & 63) - 32 + p_147463_3_;
				k2 = (l1 >> 12 & 63) - 32 + p_147463_4_;
				l2 = this.getSavedLightValue(p_147463_1_, i2, j2, k2);
				i3 = this.computeLightValue(i2, j2, k2, p_147463_1_);

				if (i3 != l2)
				{
					this.setLightValue(p_147463_1_, i2, j2, k2, i3);

					if (i3 > l2)
					{
						j3 = Math.abs(i2 - p_147463_2_);
						k3 = Math.abs(j2 - p_147463_3_);
						l3 = Math.abs(k2 - p_147463_4_);
						boolean flag = i1 < this.lightUpdateBlockList.length - 6;

						if (j3 + k3 + l3 < 17 && flag)
						{
							if (this.getSavedLightValue(p_147463_1_, i2 - 1, j2, k2) < i3)
							{
								this.lightUpdateBlockList[i1++] = i2 - 1 - p_147463_2_ + 32 + (j2 - p_147463_3_ + 32 << 6) + (k2 - p_147463_4_ + 32 << 12);
							}

							if (this.getSavedLightValue(p_147463_1_, i2 + 1, j2, k2) < i3)
							{
								this.lightUpdateBlockList[i1++] = i2 + 1 - p_147463_2_ + 32 + (j2 - p_147463_3_ + 32 << 6) + (k2 - p_147463_4_ + 32 << 12);
							}

							if (this.getSavedLightValue(p_147463_1_, i2, j2 - 1, k2) < i3)
							{
								this.lightUpdateBlockList[i1++] = i2 - p_147463_2_ + 32 + (j2 - 1 - p_147463_3_ + 32 << 6) + (k2 - p_147463_4_ + 32 << 12);
							}

							if (this.getSavedLightValue(p_147463_1_, i2, j2 + 1, k2) < i3)
							{
								this.lightUpdateBlockList[i1++] = i2 - p_147463_2_ + 32 + (j2 + 1 - p_147463_3_ + 32 << 6) + (k2 - p_147463_4_ + 32 << 12);
							}

							if (this.getSavedLightValue(p_147463_1_, i2, j2, k2 - 1) < i3)
							{
								this.lightUpdateBlockList[i1++] = i2 - p_147463_2_ + 32 + (j2 - p_147463_3_ + 32 << 6) + (k2 - 1 - p_147463_4_ + 32 << 12);
							}

							if (this.getSavedLightValue(p_147463_1_, i2, j2, k2 + 1) < i3)
							{
								this.lightUpdateBlockList[i1++] = i2 - p_147463_2_ + 32 + (j2 - p_147463_3_ + 32 << 6) + (k2 + 1 - p_147463_4_ + 32 << 12);
							}
						}
					}
				}
			}

			this.theProfiler.endSection();
			return true;
		}
	}

	public boolean tickUpdates(boolean par1)
	{
		return false;
	}

	public List getPendingBlockUpdates(Chunk par1Chunk, boolean par2)
	{
		return null;
	}

	public List getEntitiesWithinAABBExcludingEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB)
	{
		return this.getEntitiesWithinAABBExcludingEntity(par1Entity, par2AxisAlignedBB, (IEntitySelector)null);
	}

	public List getEntitiesWithinAABBExcludingEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB, IEntitySelector par3IEntitySelector)
	{
		ArrayList arraylist = new ArrayList();
		int i = MathHelper.floor_double((par2AxisAlignedBB.minX - MAX_ENTITY_RADIUS) / 16.0D);
		int j = MathHelper.floor_double((par2AxisAlignedBB.maxX + MAX_ENTITY_RADIUS) / 16.0D);
		int k = MathHelper.floor_double((par2AxisAlignedBB.minZ - MAX_ENTITY_RADIUS) / 16.0D);
		int l = MathHelper.floor_double((par2AxisAlignedBB.maxZ + MAX_ENTITY_RADIUS) / 16.0D);

		for (int i1 = i; i1 <= j; ++i1)
		{
			for (int j1 = k; j1 <= l; ++j1)
			{
				if (this.chunkExists(i1, j1))
				{
					this.getChunkFromChunkCoords(i1, j1).getEntitiesWithinAABBForEntity(par1Entity, par2AxisAlignedBB, arraylist, par3IEntitySelector);
				}
			}
		}

		return arraylist;
	}

	public List getEntitiesWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB)
	{
		return this.selectEntitiesWithinAABB(par1Class, par2AxisAlignedBB, (IEntitySelector)null);
	}

	public List selectEntitiesWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB, IEntitySelector par3IEntitySelector)
	{
		int i = MathHelper.floor_double((par2AxisAlignedBB.minX - MAX_ENTITY_RADIUS) / 16.0D);
		int j = MathHelper.floor_double((par2AxisAlignedBB.maxX + MAX_ENTITY_RADIUS) / 16.0D);
		int k = MathHelper.floor_double((par2AxisAlignedBB.minZ - MAX_ENTITY_RADIUS) / 16.0D);
		int l = MathHelper.floor_double((par2AxisAlignedBB.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
		ArrayList arraylist = new ArrayList();

		for (int i1 = i; i1 <= j; ++i1)
		{
			for (int j1 = k; j1 <= l; ++j1)
			{
				if (this.chunkExists(i1, j1))
				{
					this.getChunkFromChunkCoords(i1, j1).getEntitiesOfTypeWithinAAAB(par1Class, par2AxisAlignedBB, arraylist, par3IEntitySelector);
				}
			}
		}

		return arraylist;
	}

	public Entity findNearestEntityWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB, Entity par3Entity)
	{
		List list = this.getEntitiesWithinAABB(par1Class, par2AxisAlignedBB);
		Entity entity1 = null;
		double d0 = Double.MAX_VALUE;

		for (int i = 0; i < list.size(); ++i)
		{
			Entity entity2 = (Entity)list.get(i);

			if (entity2 != par3Entity)
			{
				double d1 = par3Entity.getDistanceSqToEntity(entity2);

				if (d1 <= d0)
				{
					entity1 = entity2;
					d0 = d1;
				}
			}
		}

		return entity1;
	}

	public abstract Entity getEntityByID(int var1);

	@SideOnly(Side.CLIENT)
	public List getLoadedEntityList()
	{
		return this.loadedEntityList;
	}

	public void markTileEntityChunkModified(int p_147476_1_, int p_147476_2_, int p_147476_3_, TileEntity p_147476_4_)
	{
		if (this.blockExists(p_147476_1_, p_147476_2_, p_147476_3_))
		{
			this.getChunkFromBlockCoords(p_147476_1_, p_147476_3_).setChunkModified();
		}
	}

	public int countEntities(Class par1Class)
	{
		int i = 0;

		for (int j = 0; j < this.loadedEntityList.size(); ++j)
		{
			Entity entity = (Entity)this.loadedEntityList.get(j);

			if ((!(entity instanceof EntityLiving) || !((EntityLiving)entity).isNoDespawnRequired()) && par1Class.isAssignableFrom(entity.getClass()))
			{
				++i;
			}
		}

		return i;
	}

	public void addLoadedEntities(List par1List)
	{
		for (int i = 0; i < par1List.size(); ++i)
		{
			Entity entity = (Entity)par1List.get(i);
			if (!MinecraftForge.EVENT_BUS.post(new EntityJoinWorldEvent(entity, this)))
			{
				loadedEntityList.add(entity);
				this.onEntityAdded(entity);
			}
		}
	}

	public void unloadEntities(List par1List)
	{
		this.unloadedEntityList.addAll(par1List);
	}

	public boolean canPlaceEntityOnSide(Block p_147472_1_, int p_147472_2_, int p_147472_3_, int p_147472_4_, boolean p_147472_5_, int p_147472_6_, Entity p_147472_7_, ItemStack p_147472_8_)
	{
		Block block1 = this.getBlock(p_147472_2_, p_147472_3_, p_147472_4_);
		AxisAlignedBB axisalignedbb = p_147472_5_ ? null : p_147472_1_.getCollisionBoundingBoxFromPool(this, p_147472_2_, p_147472_3_, p_147472_4_);
		return axisalignedbb != null && !this.checkNoEntityCollision(axisalignedbb, p_147472_7_) ? false : (block1.getMaterial() == Material.circuits && p_147472_1_ == Blocks.anvil ? true : block1.isReplaceable(this, p_147472_2_, p_147472_3_, p_147472_4_) && p_147472_1_.canReplace(this, p_147472_2_, p_147472_3_, p_147472_4_, p_147472_6_, p_147472_8_));
	}

	public PathEntity getPathEntityToEntity(Entity par1Entity, Entity par2Entity, float par3, boolean par4, boolean par5, boolean par6, boolean par7)
	{
		this.theProfiler.startSection("pathfind");
		int i = MathHelper.floor_double(par1Entity.posX);
		int j = MathHelper.floor_double(par1Entity.posY + 1.0D);
		int k = MathHelper.floor_double(par1Entity.posZ);
		int l = (int)(par3 + 16.0F);
		int i1 = i - l;
		int j1 = j - l;
		int k1 = k - l;
		int l1 = i + l;
		int i2 = j + l;
		int j2 = k + l;
		ChunkCache chunkcache = new ChunkCache(this, i1, j1, k1, l1, i2, j2, 0);
		PathEntity pathentity = (new PathFinder(chunkcache, par4, par5, par6, par7)).createEntityPathTo(par1Entity, par2Entity, par3);
		this.theProfiler.endSection();
		return pathentity;
	}

	public PathEntity getEntityPathToXYZ(Entity par1Entity, int par2, int par3, int par4, float par5, boolean par6, boolean par7, boolean par8, boolean par9)
	{
		this.theProfiler.startSection("pathfind");
		int l = MathHelper.floor_double(par1Entity.posX);
		int i1 = MathHelper.floor_double(par1Entity.posY);
		int j1 = MathHelper.floor_double(par1Entity.posZ);
		int k1 = (int)(par5 + 8.0F);
		int l1 = l - k1;
		int i2 = i1 - k1;
		int j2 = j1 - k1;
		int k2 = l + k1;
		int l2 = i1 + k1;
		int i3 = j1 + k1;
		ChunkCache chunkcache = new ChunkCache(this, l1, i2, j2, k2, l2, i3, 0);
		PathEntity pathentity = (new PathFinder(chunkcache, par6, par7, par8, par9)).createEntityPathTo(par1Entity, par2, par3, par4, par5);
		this.theProfiler.endSection();
		return pathentity;
	}

	public int isBlockProvidingPowerTo(int par1, int par2, int par3, int par4)
	{
		return this.getBlock(par1, par2, par3).isProvidingStrongPower(this, par1, par2, par3, par4);
	}

	public int getBlockPowerInput(int par1, int par2, int par3)
	{
		byte b0 = 0;
		int l = Math.max(b0, this.isBlockProvidingPowerTo(par1, par2 - 1, par3, 0));

		if (l >= 15)
		{
			return l;
		}
		else
		{
			l = Math.max(l, this.isBlockProvidingPowerTo(par1, par2 + 1, par3, 1));

			if (l >= 15)
			{
				return l;
			}
			else
			{
				l = Math.max(l, this.isBlockProvidingPowerTo(par1, par2, par3 - 1, 2));

				if (l >= 15)
				{
					return l;
				}
				else
				{
					l = Math.max(l, this.isBlockProvidingPowerTo(par1, par2, par3 + 1, 3));

					if (l >= 15)
					{
						return l;
					}
					else
					{
						l = Math.max(l, this.isBlockProvidingPowerTo(par1 - 1, par2, par3, 4));

						if (l >= 15)
						{
							return l;
						}
						else
						{
							l = Math.max(l, this.isBlockProvidingPowerTo(par1 + 1, par2, par3, 5));
							return l >= 15 ? l : l;
						}
					}
				}
			}
		}
	}

	public boolean getIndirectPowerOutput(int par1, int par2, int par3, int par4)
	{
		return this.getIndirectPowerLevelTo(par1, par2, par3, par4) > 0;
	}

	public int getIndirectPowerLevelTo(int par1, int par2, int par3, int par4)
	{
		Block block = this.getBlock(par1, par2, par3);        
		return block.shouldCheckWeakPower(this, par1, par2, par3, par4) ? this.getBlockPowerInput(par1, par2, par3) : block.isProvidingWeakPower(this, par1, par2, par3, par4);
	}

	public boolean isBlockIndirectlyGettingPowered(int par1, int par2, int par3)
	{
		return this.getIndirectPowerLevelTo(par1, par2 - 1, par3, 0) > 0 ? true : (this.getIndirectPowerLevelTo(par1, par2 + 1, par3, 1) > 0 ? true : (this.getIndirectPowerLevelTo(par1, par2, par3 - 1, 2) > 0 ? true : (this.getIndirectPowerLevelTo(par1, par2, par3 + 1, 3) > 0 ? true : (this.getIndirectPowerLevelTo(par1 - 1, par2, par3, 4) > 0 ? true : this.getIndirectPowerLevelTo(par1 + 1, par2, par3, 5) > 0))));
	}

	public int getStrongestIndirectPower(int par1, int par2, int par3)
	{
		int l = 0;

		for (int i1 = 0; i1 < 6; ++i1)
		{
			int j1 = this.getIndirectPowerLevelTo(par1 + Facing.offsetsXForSide[i1], par2 + Facing.offsetsYForSide[i1], par3 + Facing.offsetsZForSide[i1], i1);

			if (j1 >= 15)
			{
				return 15;
			}

			if (j1 > l)
			{
				l = j1;
			}
		}

		return l;
	}

	public EntityPlayer getClosestPlayerToEntity(Entity par1Entity, double par2)
	{
		return this.getClosestPlayer(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par2);
	}

	public EntityPlayer getClosestPlayer(double par1, double par3, double par5, double par7)
	{
		double d4 = -1.0D;
		EntityPlayer entityplayer = null;

		for (int i = 0; i < this.playerEntities.size(); ++i)
		{
			EntityPlayer entityplayer1 = (EntityPlayer)this.playerEntities.get(i);
			double d5 = entityplayer1.getDistanceSq(par1, par3, par5);

			if ((par7 < 0.0D || d5 < par7 * par7) && (d4 == -1.0D || d5 < d4))
			{
				d4 = d5;
				entityplayer = entityplayer1;
			}
		}

		return entityplayer;
	}

	public EntityPlayer getClosestVulnerablePlayerToEntity(Entity par1Entity, double par2)
	{
		return this.getClosestVulnerablePlayer(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par2);
	}

	public EntityPlayer getClosestVulnerablePlayer(double par1, double par3, double par5, double par7)
	{
		double d4 = -1.0D;
		EntityPlayer entityplayer = null;

		for (int i = 0; i < this.playerEntities.size(); ++i)
		{
			EntityPlayer entityplayer1 = (EntityPlayer)this.playerEntities.get(i);

			if (!entityplayer1.capabilities.disableDamage && entityplayer1.isEntityAlive())
			{
				double d5 = entityplayer1.getDistanceSq(par1, par3, par5);
				double d6 = par7;

				if (entityplayer1.isSneaking())
				{
					d6 = par7 * 0.800000011920929D;
				}

				if (entityplayer1.isInvisible())
				{
					float f = entityplayer1.getArmorVisibility();

					if (f < 0.1F)
					{
						f = 0.1F;
					}

					d6 *= (double)(0.7F * f);
				}

				if ((par7 < 0.0D || d5 < d6 * d6) && (d4 == -1.0D || d5 < d4))
				{
					d4 = d5;
					entityplayer = entityplayer1;
				}
			}
		}

		return entityplayer;
	}

	public EntityPlayer getPlayerEntityByName(String par1Str)
	{
		for (int i = 0; i < this.playerEntities.size(); ++i)
		{
			if (par1Str.equals(((EntityPlayer)this.playerEntities.get(i)).getCommandSenderName()))
			{
				return (EntityPlayer)this.playerEntities.get(i);
			}
		}

		return null;
	}

	@SideOnly(Side.CLIENT)
	public void sendQuittingDisconnectingPacket() {}

	public void checkSessionLock() throws MinecraftException
	{
		this.saveHandler.checkSessionLock();
	}

	@SideOnly(Side.CLIENT)
	public void func_82738_a(long par1)
	{
		this.worldInfo.incrementTotalWorldTime(par1);
	}

	public long getSeed()
	{
		return provider.getSeed();
	}

	public long getTotalWorldTime()
	{
		return this.worldInfo.getWorldTotalTime();
	}

	public long getWorldTime()
	{
		return provider.getWorldTime();
	}

	public void setWorldTime(long par1)
	{
		provider.setWorldTime(par1);
	}

	public ChunkCoordinates getSpawnPoint()
	{
		return provider.getSpawnPoint();
	}

	public void setSpawnLocation(int par1, int par2, int par3)
	{
		provider.setSpawnPoint(par1, par2, par3);
	}

	@SideOnly(Side.CLIENT)
	public void joinEntityInSurroundings(Entity par1Entity)
	{
		int i = MathHelper.floor_double(par1Entity.posX / 16.0D);
		int j = MathHelper.floor_double(par1Entity.posZ / 16.0D);
		byte b0 = 2;

		for (int k = i - b0; k <= i + b0; ++k)
		{
			for (int l = j - b0; l <= j + b0; ++l)
			{
				this.getChunkFromChunkCoords(k, l);
			}
		}

		if (!this.loadedEntityList.contains(par1Entity))
		{
			if (!MinecraftForge.EVENT_BUS.post(new EntityJoinWorldEvent(par1Entity, this)))
			{
				this.loadedEntityList.add(par1Entity);
			}
		}
	}

	public boolean canMineBlock(EntityPlayer par1EntityPlayer, int par2, int par3, int par4)
	{
		return provider.canMineBlock(par1EntityPlayer, par2, par3, par4);
	}

	public boolean canMineBlockBody(EntityPlayer par1EntityPlayer, int par2, int par3, int par4)
	{
		return true;
	}

	public void setEntityState(Entity par1Entity, byte par2) {}

	public IChunkProvider getChunkProvider()
	{
		return this.chunkProvider;
	}

	public void addBlockEvent(int p_147452_1_, int p_147452_2_, int p_147452_3_, Block p_147452_4_, int p_147452_5_, int p_147452_6_)
	{
		p_147452_4_.onBlockEventReceived(this, p_147452_1_, p_147452_2_, p_147452_3_, p_147452_5_, p_147452_6_);
	}

	public ISaveHandler getSaveHandler()
	{
		return this.saveHandler;
	}

	public WorldInfo getWorldInfo()
	{
		return this.worldInfo;
	}

	public GameRules getGameRules()
	{
		return this.worldInfo.getGameRulesInstance();
	}

	public void updateAllPlayersSleepingFlag() {}

	public float getWeightedThunderStrength(float par1)
	{
		return (this.prevThunderingStrength + (this.thunderingStrength - this.prevThunderingStrength) * par1) * this.getRainStrength(par1);
	}

	@SideOnly(Side.CLIENT)
	public void setThunderStrength(float p_147442_1_)
	{
		this.prevThunderingStrength = p_147442_1_;
		this.thunderingStrength = p_147442_1_;
	}

	public float getRainStrength(float par1)
	{
		return this.prevRainingStrength + (this.rainingStrength - this.prevRainingStrength) * par1;
	}

	@SideOnly(Side.CLIENT)
	public void setRainStrength(float par1)
	{
		this.prevRainingStrength = par1;
		this.rainingStrength = par1;
	}

	public boolean isThundering()
	{
		return (double)this.getWeightedThunderStrength(1.0F) > 0.9D;
	}

	public boolean isRaining()
	{
		return (double)this.getRainStrength(1.0F) > 0.2D;
	}

	public boolean canLightningStrikeAt(int par1, int par2, int par3)
	{
		if (!this.isRaining())
		{
			return false;
		}
		else if (!this.canBlockSeeTheSky(par1, par2, par3))
		{
			return false;
		}
		else if (this.getPrecipitationHeight(par1, par3) > par2)
		{
			return false;
		}
		else
		{
			BiomeGenBase biomegenbase = this.getBiomeGenForCoords(par1, par3);
			return biomegenbase.getEnableSnow() ? false : (this.func_147478_e(par1, par2, par3, false) ? false : biomegenbase.canSpawnLightningBolt());
		}
	}

	public boolean isBlockHighHumidity(int par1, int par2, int par3)
	{
		return provider.isBlockHighHumidity(par1, par2, par3);
	}

	public void setItemData(String par1Str, WorldSavedData par2WorldSavedData)
	{
		this.mapStorage.setData(par1Str, par2WorldSavedData);
	}

	public WorldSavedData loadItemData(Class par1Class, String par2Str)
	{
		return this.mapStorage.loadData(par1Class, par2Str);
	}

	public int getUniqueDataId(String par1Str)
	{
		return this.mapStorage.getUniqueDataId(par1Str);
	}

	public void playBroadcastSound(int par1, int par2, int par3, int par4, int par5)
	{
		for (int j1 = 0; j1 < this.worldAccesses.size(); ++j1)
		{
			((IWorldAccess)this.worldAccesses.get(j1)).broadcastSound(par1, par2, par3, par4, par5);
		}
	}

	public void playAuxSFX(int par1, int par2, int par3, int par4, int par5)
	{
		this.playAuxSFXAtEntity((EntityPlayer)null, par1, par2, par3, par4, par5);
	}

	public void playAuxSFXAtEntity(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5, int par6)
	{
		try
		{
			for (int j1 = 0; j1 < this.worldAccesses.size(); ++j1)
			{
				((IWorldAccess)this.worldAccesses.get(j1)).playAuxSFX(par1EntityPlayer, par2, par3, par4, par5, par6);
			}
		}
		catch (Throwable throwable)
		{
			CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Playing level event");
			CrashReportCategory crashreportcategory = crashreport.makeCategory("Level event being played");
			crashreportcategory.addCrashSection("Block coordinates", CrashReportCategory.getLocationInfo(par3, par4, par5));
			crashreportcategory.addCrashSection("Event source", par1EntityPlayer);
			crashreportcategory.addCrashSection("Event type", Integer.valueOf(par2));
			crashreportcategory.addCrashSection("Event data", Integer.valueOf(par6));
			throw new ReportedException(crashreport);
		}
	}

	public int getHeight()
	{
		return provider.getHeight();
	}

	public int getActualHeight()
	{
		return provider.getActualHeight();
	}

	public Random setRandomSeed(int par1, int par2, int par3)
	{
		long l = (long)par1 * 341873128712L + (long)par2 * 132897987541L + this.getWorldInfo().getSeed() + (long)par3;
		this.rand.setSeed(l);
		return this.rand;
	}

	public ChunkPosition findClosestStructure(String p_147440_1_, int p_147440_2_, int p_147440_3_, int p_147440_4_)
	{
		return this.getChunkProvider().func_147416_a(this, p_147440_1_, p_147440_2_, p_147440_3_, p_147440_4_);
	}

	@SideOnly(Side.CLIENT)
	public boolean extendedLevelsInChunkCache()
	{
		return false;
	}

	@SideOnly(Side.CLIENT)
	public double getHorizon()
	{
		return provider.getHorizon();
	}

	public CrashReportCategory addWorldInfoToCrashReport(CrashReport par1CrashReport)
	{
		CrashReportCategory crashreportcategory = par1CrashReport.makeCategoryDepth("Affected level", 1);
		crashreportcategory.addCrashSection("Level name", this.worldInfo == null ? "????" : this.worldInfo.getWorldName());
		crashreportcategory.addCrashSectionCallable("All players", new Callable()
		{
			private static final String __OBFID = "CL_00000143";
			public String call()
			{
				return World.this.playerEntities.size() + " total; " + World.this.playerEntities.toString();
			}
		});
		crashreportcategory.addCrashSectionCallable("Chunk stats", new Callable()
		{
			private static final String __OBFID = "CL_00000144";
			public String call()
			{
				return World.this.chunkProvider.makeString();
			}
		});

		try
		{
			this.worldInfo.addToCrashReport(crashreportcategory);
		}
		catch (Throwable throwable)
		{
			crashreportcategory.addCrashSectionThrowable("Level Data Unobtainable", throwable);
		}

		return crashreportcategory;
	}

	public void destroyBlockInWorldPartially(int p_147443_1_, int p_147443_2_, int p_147443_3_, int p_147443_4_, int p_147443_5_)
	{
		for (int j1 = 0; j1 < this.worldAccesses.size(); ++j1)
		{
			IWorldAccess iworldaccess = (IWorldAccess)this.worldAccesses.get(j1);
			iworldaccess.destroyBlockPartially(p_147443_1_, p_147443_2_, p_147443_3_, p_147443_4_, p_147443_5_);
		}
	}

	@Deprecated /* gone in 1.7.10, use direct access to Vec3.createVectorHelper instead */
	public Vec3Pool getWorldVec3Pool()
	{
		return this.vecPool;
	}

	public Calendar getCurrentDate()
	{
		if (this.getTotalWorldTime() % 600L == 0L)
		{
			this.theCalendar.setTimeInMillis(MinecraftServer.getSystemTimeMillis());
		}

		return this.theCalendar;
	}

	@SideOnly(Side.CLIENT)
	public void makeFireworks(double par1, double par3, double par5, double par7, double par9, double par11, NBTTagCompound par13NBTTagCompound) {}

	public Scoreboard getScoreboard()
	{
		return this.worldScoreboard;
	}

	public void func_147453_f(int p_147453_1_, int p_147453_2_, int p_147453_3_, Block p_147453_4_)
	{
		for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
		{
			int i1 = p_147453_1_ + dir.offsetX;
			int y  = p_147453_2_ + dir.offsetY;
			int j1 = p_147453_3_ + dir.offsetZ;
			Block block1 = this.getBlock(i1, y, j1);

			block1.onNeighborChange(this, i1, y, j1, p_147453_1_, p_147453_2_, p_147453_3_);
			if (block1.isNormalCube(this, i1, p_147453_2_, j1))
			{
				i1 += dir.offsetX;
				y  += dir.offsetY;
				j1 += dir.offsetZ;
				Block block2 = this.getBlock(i1, y, j1);

				if (block2.getWeakChanges(this, i1, y, j1))
				{
					block2.onNeighborChange(this, i1, y, j1, p_147453_1_, p_147453_2_, p_147453_3_);
				}
			}
		}
	}

	public float func_147462_b(double p_147462_1_, double p_147462_3_, double p_147462_5_)
	{
		return this.func_147473_B(MathHelper.floor_double(p_147462_1_), MathHelper.floor_double(p_147462_3_), MathHelper.floor_double(p_147462_5_));
	}

	public float func_147473_B(int p_147473_1_, int p_147473_2_, int p_147473_3_)
	{
		float f = 0.0F;
		boolean flag = this.difficultySetting == EnumDifficulty.HARD;

		if (this.blockExists(p_147473_1_, p_147473_2_, p_147473_3_))
		{
			float f1 = this.getCurrentMoonPhaseFactor();
			f += MathHelper.clamp_float((float)this.getChunkFromBlockCoords(p_147473_1_, p_147473_3_).inhabitedTime / 3600000.0F, 0.0F, 1.0F) * (flag ? 1.0F : 0.75F);
			f += f1 * 0.25F;
		}

		if (this.difficultySetting == EnumDifficulty.EASY || this.difficultySetting == EnumDifficulty.PEACEFUL)
		{
			f *= (float)this.difficultySetting.getDifficultyId() / 2.0F;
		}

		return MathHelper.clamp_float(f, 0.0F, flag ? 1.5F : 1.0F);
	}

	public void func_147450_X()
	{
		Iterator iterator = this.worldAccesses.iterator();

		while (iterator.hasNext())
		{
			IWorldAccess iworldaccess = (IWorldAccess)iterator.next();
			iworldaccess.onStaticEntitiesChanged();
		}
	}


	/* ======================================== FORGE START =====================================*/
	/**
	 * Adds a single TileEntity to the world.
	 * @param entity The TileEntity to be added.
	 */
	public void addTileEntity(TileEntity entity)
	{
		List dest = field_147481_N ? addedTileEntityList : loadedTileEntityList;
		if(entity.canUpdate())
		{
			dest.add(entity);
		}
	}

	/**
	 * Determine if the given block is considered solid on the
	 * specified side.  Used by placement logic.
	 *
	 * @param x Block X Position
	 * @param y Block Y Position
	 * @param z Block Z Position
	 * @param side The Side in question
	 * @return True if the side is solid
	 */
	public boolean isSideSolid(int x, int y, int z, ForgeDirection side)
	{
		return isSideSolid(x, y, z, side, false);
	}

	/**
	 * Determine if the given block is considered solid on the
	 * specified side.  Used by placement logic.
	 *
	 * @param x Block X Position
	 * @param y Block Y Position
	 * @param z Block Z Position
	 * @param side The Side in question
	 * @param _default The default to return if the block doesn't exist.
	 * @return True if the side is solid
	 */
	@Override
	public boolean isSideSolid(int x, int y, int z, ForgeDirection side, boolean _default)
	{
		if (x < -30000000 || z < -30000000 || x >= 30000000 || z >= 30000000)
		{
			return _default;
		}

		Chunk chunk = this.chunkProvider.provideChunk(x >> 4, z >> 4);
		if (chunk == null || chunk.isEmpty())
		{
			return _default;
		}
		return getBlock(x, y, z).isSideSolid(this, x, y, z, side);
	}

	/**
	 * Get the persistent chunks for this world
	 *
	 * @return
	 */
	public ImmutableSetMultimap<ChunkCoordIntPair, Ticket> getPersistentChunks()
	{
		return ForgeChunkManager.getPersistentChunksFor(this);
	}

	/**
	 * Readded as it was removed, very useful helper function
	 *
	 * @param x X position
	 * @param y Y Position
	 * @param z Z Position
	 * @return The blocks light opacity
	 */
	public int getBlockLightOpacity(int x, int y, int z)
	{
		if (x < -30000000 || z < -30000000 || x >= 30000000 || z >= 30000000)
		{
			return 0;
		}

		if (y < 0 || y >= 256)
		{
			return 0;
		}

		return getChunkFromChunkCoords(x >> 4, z >> 4).func_150808_b(x & 15, y, z & 15);
	}

	/**
	 * Returns a count of entities that classify themselves as the specified creature type.
	 */
	public int countEntities(EnumCreatureType type, boolean forSpawnCount)
	{
		int count = 0;
		for (int x = 0; x < loadedEntityList.size(); x++)
		{
			if (((Entity)loadedEntityList.get(x)).isCreatureType(type, forSpawnCount))
			{
				count++;
			}
		}
		return count;
	}
}