package net.minecraft.entity.player;

import java.util.Collection;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;

import com.google.common.base.Charsets;
import com.google.common.collect.Lists;

import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBed;
import net.minecraft.block.BlockDirectional;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.server.CommandBlockLogic;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityMultiPart;
import net.minecraft.entity.IMerchant;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.boss.EntityDragonPart;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.passive.EntityPig;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.event.ClickEvent;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ContainerPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryEnderChest;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.potion.Potion;
import net.minecraft.scoreboard.IScoreObjectiveCriteria;
import net.minecraft.scoreboard.Score;
import net.minecraft.scoreboard.ScoreObjective;
import net.minecraft.scoreboard.ScorePlayerTeam;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.Team;
import net.minecraft.stats.AchievementList;
import net.minecraft.stats.StatBase;
import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntitySign;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.FoodStats;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.LockCode;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings;

public abstract class EntityPlayer extends EntityLivingBase implements ICommandSender {
	/**+
	 * Inventory of the player
	 */
	public InventoryPlayer inventory = new InventoryPlayer(this);
	private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest();
	public Container inventoryContainer;
	public Container openContainer;
	/**+
	 * The food object of the player, the general hunger logic.
	 */
	protected FoodStats foodStats = new FoodStats();
	protected int flyToggleTimer;
	public float prevCameraYaw;
	public float cameraYaw;
	public int xpCooldown;
	public double prevChasingPosX;
	public double prevChasingPosY;
	public double prevChasingPosZ;
	public double chasingPosX;
	public double chasingPosY;
	public double chasingPosZ;
	protected boolean sleeping;
	public BlockPos playerLocation;
	private int sleepTimer;
	public float renderOffsetX;
	public float renderOffsetY;
	public float renderOffsetZ;
	private BlockPos spawnChunk;
	private boolean spawnForced;
	private BlockPos startMinecartRidingCoordinate;
	/**+
	 * The player's capabilities. (See class PlayerCapabilities)
	 */
	public PlayerCapabilities capabilities = new PlayerCapabilities();
	public int experienceLevel;
	public int experienceTotal;
	public float experience;
	private int xpSeed;
	private ItemStack itemInUse;
	private int itemInUseCount;
	protected float speedOnGround = 0.1F;
	protected float speedInAir = 0.02F;
	private int lastXPSound;
	private final GameProfile gameProfile;
	private boolean hasReducedDebug = false;
	public EntityFishHook fishEntity;

	public EntityPlayer(World worldIn, GameProfile gameProfileIn) {
		super(worldIn);
		this.entityUniqueID = getUUID(gameProfileIn);
		this.gameProfile = gameProfileIn;
		this.inventoryContainer = new ContainerPlayer(this.inventory, false, this);
		this.openContainer = this.inventoryContainer;
		BlockPos blockpos = worldIn.getSpawnPoint();
		this.setLocationAndAngles((double) blockpos.getX() + 0.5D, (double) (blockpos.getY() + 1),
				(double) blockpos.getZ() + 0.5D, 0.0F, 0.0F);
		this.field_70741_aB = 180.0F;
		this.fireResistance = 20;
	}

	protected void applyEntityAttributes() {
		super.applyEntityAttributes();
		this.getAttributeMap().registerAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(1.0D);
		this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.10000000149011612D);
	}

	protected void entityInit() {
		super.entityInit();
		this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
		this.dataWatcher.addObject(17, Float.valueOf(0.0F));
		this.dataWatcher.addObject(18, Integer.valueOf(0));
		this.dataWatcher.addObject(10, Byte.valueOf((byte) 0));
	}

	/**+
	 * returns the ItemStack containing the itemInUse
	 */
	public ItemStack getItemInUse() {
		return this.itemInUse;
	}

	/**+
	 * Returns the item in use count
	 */
	public int getItemInUseCount() {
		return this.itemInUseCount;
	}

	/**+
	 * Checks if the entity is currently using an item (e.g., bow,
	 * food, sword) by holding down the useItemButton
	 */
	public boolean isUsingItem() {
		return this.itemInUse != null;
	}

	/**+
	 * gets the duration for how long the current itemInUse has been
	 * in use
	 */
	public int getItemInUseDuration() {
		return this.isUsingItem() ? this.itemInUse.getMaxItemUseDuration() - this.itemInUseCount : 0;
	}

	public void stopUsingItem() {
		if (this.itemInUse != null) {
			this.itemInUse.onPlayerStoppedUsing(this.worldObj, this, this.itemInUseCount);
		}

		this.clearItemInUse();
	}

	public void clearItemInUse() {
		this.itemInUse = null;
		this.itemInUseCount = 0;
	}

	public boolean isBlocking() {
		return this.isUsingItem() && this.itemInUse.getItem().getItemUseAction(this.itemInUse) == EnumAction.BLOCK;
	}

	/**+
	 * Called to update the entity's position/logic.
	 */
	public void onUpdate() {
		this.noClip = this.isSpectator();
		if (this.isSpectator()) {
			this.onGround = false;
		}

		if (this.itemInUse != null) {
			ItemStack itemstack = this.inventory.getCurrentItem();
			if (itemstack == this.itemInUse) {
				if (this.itemInUseCount <= 25 && this.itemInUseCount % 4 == 0) {
					this.updateItemUse(itemstack, 5);
				}

				--this.itemInUseCount;
			} else {
				this.clearItemInUse();
			}
		}

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

		if (this.isPlayerSleeping()) {
			++this.sleepTimer;
			if (this.sleepTimer > 100) {
				this.sleepTimer = 100;
			}
		} else if (this.sleepTimer > 0) {
			++this.sleepTimer;
			if (this.sleepTimer >= 110) {
				this.sleepTimer = 0;
			}
		}

		super.onUpdate();

		if (this.isBurning() && this.capabilities.disableDamage) {
			this.extinguish();
		}

		this.prevChasingPosX = this.chasingPosX;
		this.prevChasingPosY = this.chasingPosY;
		this.prevChasingPosZ = this.chasingPosZ;
		double d5 = this.posX - this.chasingPosX;
		double d0 = this.posY - this.chasingPosY;
		double d1 = this.posZ - this.chasingPosZ;
		double d2 = 10.0D;
		if (d5 > d2) {
			this.prevChasingPosX = this.chasingPosX = this.posX;
		}

		if (d1 > d2) {
			this.prevChasingPosZ = this.chasingPosZ = this.posZ;
		}

		if (d0 > d2) {
			this.prevChasingPosY = this.chasingPosY = this.posY;
		}

		if (d5 < -d2) {
			this.prevChasingPosX = this.chasingPosX = this.posX;
		}

		if (d1 < -d2) {
			this.prevChasingPosZ = this.chasingPosZ = this.posZ;
		}

		if (d0 < -d2) {
			this.prevChasingPosY = this.chasingPosY = this.posY;
		}

		this.chasingPosX += d5 * 0.25D;
		this.chasingPosZ += d1 * 0.25D;
		this.chasingPosY += d0 * 0.25D;
		if (this.ridingEntity == null) {
			this.startMinecartRidingCoordinate = null;
		}

		int i = 29999999;
		double d3 = MathHelper.clamp_double(this.posX, -2.9999999E7D, 2.9999999E7D);
		double d4 = MathHelper.clamp_double(this.posZ, -2.9999999E7D, 2.9999999E7D);
		if (d3 != this.posX || d4 != this.posZ) {
			this.setPosition(d3, this.posY, d4);
		}

	}

	/**+
	 * Return the amount of time this entity should stay in a portal
	 * before being transported.
	 */
	public int getMaxInPortalTime() {
		return this.capabilities.disableDamage ? 0 : 80;
	}

	protected String getSwimSound() {
		return "game.player.swim";
	}

	protected String getSplashSound() {
		return "game.player.swim.splash";
	}

	/**+
	 * Return the amount of cooldown before this entity can use a
	 * portal again.
	 */
	public int getPortalCooldown() {
		return 10;
	}

	public void playSound(String s, float f, float f1) {
		this.worldObj.playSoundToNearExcept(this, s, f, f1);
	}

	/**+
	 * Plays sounds and makes particles for item in use state
	 */
	protected void updateItemUse(ItemStack itemStackIn, int parInt1) {
		if (itemStackIn.getItemUseAction() == EnumAction.DRINK) {
			this.playSound("random.drink", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
		}

		if (itemStackIn.getItemUseAction() == EnumAction.EAT) {
			for (int i = 0; i < parInt1; ++i) {
				Vec3 vec3 = new Vec3(((double) this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
				vec3 = vec3.rotatePitch(-this.rotationPitch * 3.1415927F / 180.0F);
				vec3 = vec3.rotateYaw(-this.rotationYaw * 3.1415927F / 180.0F);
				double d0 = (double) (-this.rand.nextFloat()) * 0.6D - 0.3D;
				Vec3 vec31 = new Vec3(((double) this.rand.nextFloat() - 0.5D) * 0.3D, d0, 0.6D);
				vec31 = vec31.rotatePitch(-this.rotationPitch * 3.1415927F / 180.0F);
				vec31 = vec31.rotateYaw(-this.rotationYaw * 3.1415927F / 180.0F);
				vec31 = vec31.addVector(this.posX, this.posY + (double) this.getEyeHeight(), this.posZ);
				if (itemStackIn.getHasSubtypes()) {
					this.worldObj.spawnParticle(EnumParticleTypes.ITEM_CRACK, vec31.xCoord, vec31.yCoord, vec31.zCoord,
							vec3.xCoord, vec3.yCoord + 0.05D, vec3.zCoord,
							new int[] { Item.getIdFromItem(itemStackIn.getItem()), itemStackIn.getMetadata() });
				} else {
					this.worldObj.spawnParticle(EnumParticleTypes.ITEM_CRACK, vec31.xCoord, vec31.yCoord, vec31.zCoord,
							vec3.xCoord, vec3.yCoord + 0.05D, vec3.zCoord,
							new int[] { Item.getIdFromItem(itemStackIn.getItem()) });
				}
			}

			this.playSound("random.eat", 0.5F + 0.5F * (float) this.rand.nextInt(2),
					(this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
		}

	}

	/**+
	 * Used for when item use count runs out, ie: eating completed
	 */
	protected void onItemUseFinish() {
		if (this.itemInUse != null) {
			this.updateItemUse(this.itemInUse, 16);
			int i = this.itemInUse.stackSize;
			ItemStack itemstack = this.itemInUse.onItemUseFinish(this.worldObj, this);
			if (itemstack != this.itemInUse || itemstack != null && itemstack.stackSize != i) {
				this.inventory.mainInventory[this.inventory.currentItem] = itemstack;
				if (itemstack.stackSize == 0) {
					this.inventory.mainInventory[this.inventory.currentItem] = null;
				}
			}

			this.clearItemInUse();
		}

	}

	public void handleStatusUpdate(byte b0) {
		if (b0 == 9) {
			this.onItemUseFinish();
		} else if (b0 == 23) {
			this.hasReducedDebug = false;
		} else if (b0 == 22) {
			this.hasReducedDebug = true;
		} else {
			super.handleStatusUpdate(b0);
		}

	}

	/**+
	 * Dead and sleeping entities cannot move
	 */
	protected boolean isMovementBlocked() {
		return this.getHealth() <= 0.0F || this.isPlayerSleeping();
	}

	/**+
	 * set current crafting inventory back to the 2x2 square
	 */
	protected void closeScreen() {
		this.openContainer = this.inventoryContainer;
	}

	/**+
	 * Handles updating while being ridden by an entity
	 */
	public void updateRidden() {
		double d0 = this.posX;
		double d1 = this.posY;
		double d2 = this.posZ;
		float f = this.rotationYaw;
		float f1 = this.rotationPitch;
		super.updateRidden();
		this.prevCameraYaw = this.cameraYaw;
		this.cameraYaw = 0.0F;
		this.addMountedMovementStat(this.posX - d0, this.posY - d1, this.posZ - d2);
		if (this.ridingEntity instanceof EntityPig) {
			this.rotationPitch = f1;
			this.rotationYaw = f;
			this.renderYawOffset = ((EntityPig) this.ridingEntity).renderYawOffset;
		}
	}

	/**+
	 * Keeps moving the entity up so it isn't colliding with blocks
	 * and other requirements for this entity to be spawned (only
	 * actually used on players though its also on Entity)
	 */
	public void preparePlayerToSpawn() {
		this.setSize(0.6F, 1.8F);
		super.preparePlayerToSpawn();
		this.setHealth(this.getMaxHealth());
		this.deathTime = 0;
	}

	protected void updateEntityActionState() {
		super.updateEntityActionState();
		this.updateArmSwingProgress();
		this.rotationYawHead = this.rotationYaw;
	}

	/**+
	 * Called frequently so the entity can update its state every
	 * tick as required. For example, zombies and skeletons use this
	 * to react to sunlight and start to burn.
	 */
	public void onLivingUpdate() {
		if (this.flyToggleTimer > 0) {
			--this.flyToggleTimer;
		}

		if (this.worldObj.getDifficulty() == EnumDifficulty.PEACEFUL
				&& this.worldObj.getGameRules().getBoolean("naturalRegeneration")) {
			if (this.getHealth() < this.getMaxHealth() && this.ticksExisted % 20 == 0) {
				this.heal(1.0F);
			}

			if (this.foodStats.needFood() && this.ticksExisted % 10 == 0) {
				this.foodStats.setFoodLevel(this.foodStats.getFoodLevel() + 1);
			}
		}

		this.inventory.decrementAnimations();
		this.prevCameraYaw = this.cameraYaw;
		super.onLivingUpdate();
		IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.movementSpeed);

		this.jumpMovementFactor = this.speedInAir;
		if (this.isSprinting()) {
			this.jumpMovementFactor = (float) ((double) this.jumpMovementFactor + (double) this.speedInAir * 0.3D);
		}

		this.setAIMoveSpeed((float) iattributeinstance.getAttributeValue());
		float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
		float f1 = (float) (Math.atan(-this.motionY * 0.20000000298023224D) * 15.0D);
		if (f > 0.1F) {
			f = 0.1F;
		}

		if (!this.onGround || this.getHealth() <= 0.0F) {
			f = 0.0F;
		}

		if (this.onGround || this.getHealth() <= 0.0F) {
			f1 = 0.0F;
		}

		this.cameraYaw += (f - this.cameraYaw) * 0.4F;
		this.cameraPitch += (f1 - this.cameraPitch) * 0.8F;
		if (this.getHealth() > 0.0F && !this.isSpectator()) {
			AxisAlignedBB axisalignedbb = null;
			if (this.ridingEntity != null && !this.ridingEntity.isDead) {
				axisalignedbb = this.getEntityBoundingBox().union(this.ridingEntity.getEntityBoundingBox()).expand(1.0D,
						0.0D, 1.0D);
			} else {
				axisalignedbb = this.getEntityBoundingBox().expand(1.0D, 0.5D, 1.0D);
			}

			List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, axisalignedbb);

			for (int i = 0; i < list.size(); ++i) {
				Entity entity = (Entity) list.get(i);
				if (!entity.isDead) {
					this.collideWithPlayer(entity);
				}
			}
		}

	}

	private void collideWithPlayer(Entity parEntity) {
		parEntity.onCollideWithPlayer(this);
	}

	public int getScore() {
		return this.dataWatcher.getWatchableObjectInt(18);
	}

	/**+
	 * Set player's score
	 */
	public void setScore(int parInt1) {
		this.dataWatcher.updateObject(18, Integer.valueOf(parInt1));
	}

	/**+
	 * Add to player's score
	 */
	public void addScore(int parInt1) {
		int i = this.getScore();
		this.dataWatcher.updateObject(18, Integer.valueOf(i + parInt1));
	}

	/**+
	 * Called when the mob's health reaches 0.
	 */
	public void onDeath(DamageSource damagesource) {
		super.onDeath(damagesource);
		this.setSize(0.2F, 0.2F);
		this.setPosition(this.posX, this.posY, this.posZ);
		this.motionY = 0.10000000149011612D;
		if (this.getName().equals("Notch")) {
			this.dropItem(new ItemStack(Items.apple, 1), true, false);
		}

		if (!this.worldObj.getGameRules().getBoolean("keepInventory")) {
			this.inventory.dropAllItems();
		}

		if (damagesource != null) {
			this.motionX = (double) (-MathHelper.cos((this.attackedAtYaw + this.rotationYaw) * 3.1415927F / 180.0F)
					* 0.1F);
			this.motionZ = (double) (-MathHelper.sin((this.attackedAtYaw + this.rotationYaw) * 3.1415927F / 180.0F)
					* 0.1F);
		} else {
			this.motionX = this.motionZ = 0.0D;
		}

		this.triggerAchievement(StatList.deathsStat);
		this.func_175145_a(StatList.timeSinceDeathStat);
	}

	/**+
	 * Returns the sound this mob makes when it is hurt.
	 */
	protected String getHurtSound() {
		return "game.player.hurt";
	}

	/**+
	 * Returns the sound this mob makes on death.
	 */
	protected String getDeathSound() {
		return "game.player.die";
	}

	/**+
	 * Adds a value to the player score. Currently not actually used
	 * and the entity passed in does nothing. Args: entity,
	 * scoreToAdd
	 */
	public void addToPlayerScore(Entity entity, int i) {
		this.addScore(i);
		Collection collection = this.getWorldScoreboard()
				.getObjectivesFromCriteria(IScoreObjectiveCriteria.totalKillCount);
		if (entity instanceof EntityPlayer) {
			this.triggerAchievement(StatList.playerKillsStat);
			collection.addAll(
					this.getWorldScoreboard().getObjectivesFromCriteria(IScoreObjectiveCriteria.playerKillCount));
			collection.addAll(this.func_175137_e(entity));
		} else {
			this.triggerAchievement(StatList.mobKillsStat);
		}

		for (ScoreObjective scoreobjective : (Collection<ScoreObjective>) collection) {
			Score score = this.getWorldScoreboard().getValueFromObjective(this.getName(), scoreobjective);
			score.func_96648_a();
		}

	}

	private Collection<ScoreObjective> func_175137_e(Entity parEntity) {
		ScorePlayerTeam scoreplayerteam = this.getWorldScoreboard().getPlayersTeam(this.getName());
		if (scoreplayerteam != null) {
			int i = scoreplayerteam.getChatFormat().getColorIndex();
			if (i >= 0 && i < IScoreObjectiveCriteria.field_178793_i.length) {
				for (ScoreObjective scoreobjective : this.getWorldScoreboard()
						.getObjectivesFromCriteria(IScoreObjectiveCriteria.field_178793_i[i])) {
					Score score = this.getWorldScoreboard().getValueFromObjective(parEntity.getName(), scoreobjective);
					score.func_96648_a();
				}
			}
		}

		ScorePlayerTeam scoreplayerteam1 = this.getWorldScoreboard().getPlayersTeam(parEntity.getName());
		if (scoreplayerteam1 != null) {
			int j = scoreplayerteam1.getChatFormat().getColorIndex();
			if (j >= 0 && j < IScoreObjectiveCriteria.field_178792_h.length) {
				return this.getWorldScoreboard().getObjectivesFromCriteria(IScoreObjectiveCriteria.field_178792_h[j]);
			}
		}

		return Lists.newArrayList();
	}

	/**+
	 * Called when player presses the drop item key
	 */
	public EntityItem dropOneItem(boolean flag) {
		return this.dropItem(this.inventory.decrStackSize(this.inventory.currentItem,
				flag && this.inventory.getCurrentItem() != null ? this.inventory.getCurrentItem().stackSize : 1), false,
				true);
	}

	/**+
	 * Args: itemstack, flag
	 */
	public EntityItem dropPlayerItemWithRandomChoice(ItemStack itemStackIn, boolean unused) {
		return this.dropItem(itemStackIn, false, false);
	}

	public EntityItem dropItem(ItemStack droppedItem, boolean dropAround, boolean traceItem) {
		if (droppedItem == null) {
			return null;
		} else if (droppedItem.stackSize == 0) {
			return null;
		} else {
			double d0 = this.posY - 0.30000001192092896D + (double) this.getEyeHeight();
			EntityItem entityitem = new EntityItem(this.worldObj, this.posX, d0, this.posZ, droppedItem);
			entityitem.setPickupDelay(40);
			if (traceItem) {
				entityitem.setThrower(this.getName());
			}

			if (dropAround) {
				float f = this.rand.nextFloat() * 0.5F;
				float f1 = this.rand.nextFloat() * 3.1415927F * 2.0F;
				entityitem.motionX = (double) (-MathHelper.sin(f1) * f);
				entityitem.motionZ = (double) (MathHelper.cos(f1) * f);
				entityitem.motionY = 0.20000000298023224D;
			} else {
				float f2 = 0.3F;
				entityitem.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * 3.1415927F)
						* MathHelper.cos(this.rotationPitch / 180.0F * 3.1415927F) * f2);
				entityitem.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * 3.1415927F)
						* MathHelper.cos(this.rotationPitch / 180.0F * 3.1415927F) * f2);
				entityitem.motionY = (double) (-MathHelper.sin(this.rotationPitch / 180.0F * 3.1415927F) * f2 + 0.1F);
				float f3 = this.rand.nextFloat() * 3.1415927F * 2.0F;
				f2 = 0.02F * this.rand.nextFloat();
				entityitem.motionX += Math.cos((double) f3) * (double) f2;
				entityitem.motionY += (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
				entityitem.motionZ += Math.sin((double) f3) * (double) f2;
			}

			this.joinEntityItemWithWorld(entityitem);
			if (traceItem) {
				this.triggerAchievement(StatList.dropStat);
			}

			return entityitem;
		}
	}

	/**+
	 * Joins the passed in entity item with the world. Args:
	 * entityItem
	 */
	protected void joinEntityItemWithWorld(EntityItem entityitem) {
		this.worldObj.spawnEntityInWorld(entityitem);
	}

	/**+
	 * Block hardness will be further counted in
	 * net/minecraft/block/Block.getPlayerRelativeBlockHardness
	 */
	public float getToolDigEfficiency(Block parBlock) {
		float f = this.inventory.getStrVsBlock(parBlock);
		if (f > 1.0F) {
			int i = EnchantmentHelper.getEfficiencyModifier(this);
			ItemStack itemstack = this.inventory.getCurrentItem();
			if (i > 0 && itemstack != null) {
				f += (float) (i * i + 1);
			}
		}

		if (this.isPotionActive(Potion.digSpeed)) {
			f *= 1.0F + (float) (this.getActivePotionEffect(Potion.digSpeed).getAmplifier() + 1) * 0.2F;
		}

		if (this.isPotionActive(Potion.digSlowdown)) {
			float f1 = 1.0F;
			switch (this.getActivePotionEffect(Potion.digSlowdown).getAmplifier()) {
			case 0:
				f1 = 0.3F;
				break;
			case 1:
				f1 = 0.09F;
				break;
			case 2:
				f1 = 0.0027F;
				break;
			case 3:
			default:
				f1 = 8.1E-4F;
			}

			f *= f1;
		}

		if (this.isInsideOfMaterial(Material.water) && !EnchantmentHelper.getAquaAffinityModifier(this)) {
			f /= 5.0F;
		}

		if (!this.onGround) {
			f /= 5.0F;
		}

		return f;
	}

	/**+
	 * Checks if the player has the ability to harvest a block
	 * (checks current inventory item for a tool if necessary)
	 */
	public boolean canHarvestBlock(Block blockToHarvest) {
		return this.inventory.canHeldItemHarvest(blockToHarvest);
	}

	/**+
	 * (abstract) Protected helper method to read subclass entity
	 * data from NBT.
	 */
	public void readEntityFromNBT(NBTTagCompound nbttagcompound) {
		super.readEntityFromNBT(nbttagcompound);
		this.entityUniqueID = getUUID(this.gameProfile);
		NBTTagList nbttaglist = nbttagcompound.getTagList("Inventory", 10);
		this.inventory.readFromNBT(nbttaglist);
		this.inventory.currentItem = nbttagcompound.getInteger("SelectedItemSlot");
		this.sleeping = nbttagcompound.getBoolean("Sleeping");
		this.sleepTimer = nbttagcompound.getShort("SleepTimer");
		this.experience = nbttagcompound.getFloat("XpP");
		this.experienceLevel = nbttagcompound.getInteger("XpLevel");
		this.experienceTotal = nbttagcompound.getInteger("XpTotal");
		this.xpSeed = nbttagcompound.getInteger("XpSeed");
		if (this.xpSeed == 0) {
			this.xpSeed = this.rand.nextInt();
		}

		this.setScore(nbttagcompound.getInteger("Score"));
		if (this.sleeping) {
			this.playerLocation = new BlockPos(this);
			this.wakeUpPlayer(true, true, false);
		}

		if (nbttagcompound.hasKey("SpawnX", 99) && nbttagcompound.hasKey("SpawnY", 99)
				&& nbttagcompound.hasKey("SpawnZ", 99)) {
			this.spawnChunk = new BlockPos(nbttagcompound.getInteger("SpawnX"), nbttagcompound.getInteger("SpawnY"),
					nbttagcompound.getInteger("SpawnZ"));
			this.spawnForced = nbttagcompound.getBoolean("SpawnForced");
		}

		this.foodStats.readNBT(nbttagcompound);
		this.capabilities.readCapabilitiesFromNBT(nbttagcompound);
		if (nbttagcompound.hasKey("EnderItems", 9)) {
			NBTTagList nbttaglist1 = nbttagcompound.getTagList("EnderItems", 10);
			this.theInventoryEnderChest.loadInventoryFromNBT(nbttaglist1);
		}

	}

	/**+
	 * (abstract) Protected helper method to write subclass entity
	 * data to NBT.
	 */
	public void writeEntityToNBT(NBTTagCompound nbttagcompound) {
		super.writeEntityToNBT(nbttagcompound);
		nbttagcompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList()));
		nbttagcompound.setInteger("SelectedItemSlot", this.inventory.currentItem);
		nbttagcompound.setBoolean("Sleeping", this.sleeping);
		nbttagcompound.setShort("SleepTimer", (short) this.sleepTimer);
		nbttagcompound.setFloat("XpP", this.experience);
		nbttagcompound.setInteger("XpLevel", this.experienceLevel);
		nbttagcompound.setInteger("XpTotal", this.experienceTotal);
		nbttagcompound.setInteger("XpSeed", this.xpSeed);
		nbttagcompound.setInteger("Score", this.getScore());
		if (this.spawnChunk != null) {
			nbttagcompound.setInteger("SpawnX", this.spawnChunk.getX());
			nbttagcompound.setInteger("SpawnY", this.spawnChunk.getY());
			nbttagcompound.setInteger("SpawnZ", this.spawnChunk.getZ());
			nbttagcompound.setBoolean("SpawnForced", this.spawnForced);
		}

		this.foodStats.writeNBT(nbttagcompound);
		this.capabilities.writeCapabilitiesToNBT(nbttagcompound);
		nbttagcompound.setTag("EnderItems", this.theInventoryEnderChest.saveInventoryToNBT());
		ItemStack itemstack = this.inventory.getCurrentItem();
		if (itemstack != null && itemstack.getItem() != null) {
			nbttagcompound.setTag("SelectedItem", itemstack.writeToNBT(new NBTTagCompound()));
		}

	}

	/**+
	 * Called when the entity is attacked.
	 */
	public boolean attackEntityFrom(DamageSource damagesource, float f) {
		if (this.isEntityInvulnerable(damagesource)) {
			return false;
		} else if (this.capabilities.disableDamage && !damagesource.canHarmInCreative()) {
			return false;
		} else {
			this.entityAge = 0;
			if (this.getHealth() <= 0.0F) {
				return false;
			} else {
				if (damagesource.isDifficultyScaled()) {
					if (this.worldObj.getDifficulty() == EnumDifficulty.PEACEFUL) {
						f = 0.0F;
					}

					if (this.worldObj.getDifficulty() == EnumDifficulty.EASY) {
						f = f / 2.0F + 1.0F;
					}

					if (this.worldObj.getDifficulty() == EnumDifficulty.HARD) {
						f = f * 3.0F / 2.0F;
					}
				}

				if (f == 0.0F) {
					return false;
				} else {
					Entity entity = damagesource.getEntity();
					if (entity instanceof EntityArrow && ((EntityArrow) entity).shootingEntity != null) {
						entity = ((EntityArrow) entity).shootingEntity;
					}

					return super.attackEntityFrom(damagesource, f);
				}
			}
		}
	}

	public boolean canAttackPlayer(EntityPlayer entityplayer) {
		Team team = this.getTeam();
		Team team1 = entityplayer.getTeam();
		return team == null ? true : (!team.isSameTeam(team1) ? true : team.getAllowFriendlyFire());
	}

	protected void damageArmor(float f) {
		this.inventory.damageArmor(f);
	}

	/**+
	 * Returns the current armor value as determined by a call to
	 * InventoryPlayer.getTotalArmorValue
	 */
	public int getTotalArmorValue() {
		return this.inventory.getTotalArmorValue();
	}

	/**+
	 * When searching for vulnerable players, if a player is
	 * invisible, the return value of this is the chance of seeing
	 * them anyway.
	 */
	public float getArmorVisibility() {
		int i = 0;

		for (ItemStack itemstack : this.inventory.armorInventory) {
			if (itemstack != null) {
				++i;
			}
		}

		return (float) i / (float) this.inventory.armorInventory.length;
	}

	/**+
	 * Deals damage to the entity. If its a EntityPlayer then will
	 * take damage from the armor first and then health second with
	 * the reduced value. Args: damageAmount
	 */
	protected void damageEntity(DamageSource damagesource, float f) {
		if (!this.isEntityInvulnerable(damagesource)) {
			if (!damagesource.isUnblockable() && this.isBlocking() && f > 0.0F) {
				f = (1.0F + f) * 0.5F;
			}

			f = this.applyArmorCalculations(damagesource, f);
			f = this.applyPotionDamageCalculations(damagesource, f);
			float f1 = f;
			f = Math.max(f - this.getAbsorptionAmount(), 0.0F);
			this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f));
			if (f != 0.0F) {
				this.addExhaustion(damagesource.getHungerDamage());
				float f2 = this.getHealth();
				this.setHealth(this.getHealth() - f);
				this.getCombatTracker().trackDamage(damagesource, f2, f);
				if (f < 3.4028235E37F) {
					this.addStat(StatList.damageTakenStat, Math.round(f * 10.0F));
				}

			}
		}
	}

	public void openEditSign(TileEntitySign var1) {
	}

	public void openEditCommandBlock(CommandBlockLogic var1) {
	}

	public void displayVillagerTradeGui(IMerchant var1) {
	}

	/**+
	 * Displays the GUI for interacting with a chest inventory.
	 * Args: chestInventory
	 */
	public void displayGUIChest(IInventory var1) {
	}

	public void displayGUIHorse(EntityHorse var1, IInventory var2) {
	}

	public void displayGui(IInteractionObject var1) {
	}

	/**+
	 * Displays the GUI for interacting with a book.
	 */
	public void displayGUIBook(ItemStack var1) {
	}

	public boolean interactWith(Entity parEntity) {
		if (this.isSpectator()) {
			if (parEntity instanceof IInventory) {
				this.displayGUIChest((IInventory) parEntity);
			}

			return false;
		} else {
			ItemStack itemstack = this.getCurrentEquippedItem();
			ItemStack itemstack1 = itemstack != null ? itemstack.copy() : null;
			if (!parEntity.interactFirst(this)) {
				if (itemstack != null && parEntity instanceof EntityLivingBase) {
					if (this.capabilities.isCreativeMode) {
						itemstack = itemstack1;
					}

					if (itemstack.interactWithEntity(this, (EntityLivingBase) parEntity)) {
						if (itemstack.stackSize <= 0 && !this.capabilities.isCreativeMode) {
							this.destroyCurrentEquippedItem();
						}

						return true;
					}
				}

				return false;
			} else {
				if (itemstack != null && itemstack == this.getCurrentEquippedItem()) {
					if (itemstack.stackSize <= 0 && !this.capabilities.isCreativeMode) {
						this.destroyCurrentEquippedItem();
					} else if (itemstack.stackSize < itemstack1.stackSize && this.capabilities.isCreativeMode) {
						itemstack.stackSize = itemstack1.stackSize;
					}
				}

				return true;
			}
		}
	}

	/**+
	 * Returns the currently being used item by the player.
	 */
	public ItemStack getCurrentEquippedItem() {
		return this.inventory.getCurrentItem();
	}

	/**+
	 * Destroys the currently equipped item from the player's
	 * inventory.
	 */
	public void destroyCurrentEquippedItem() {
		this.inventory.setInventorySlotContents(this.inventory.currentItem, (ItemStack) null);
	}

	/**+
	 * Returns the Y Offset of this entity.
	 */
	public double getYOffset() {
		return -0.35D;
	}

	/**+
	 * Attacks for the player the targeted entity with the currently
	 * equipped item. The equipped item has hitEntity called on it.
	 * Args: targetEntity
	 */
	public void attackTargetEntityWithCurrentItem(Entity entity) {
		if (entity.canAttackWithItem()) {
			if (!entity.hitByEntity(this)) {
				float f = (float) this.getEntityAttribute(SharedMonsterAttributes.attackDamage).getAttributeValue();
				int i = 0;
				float f1 = 0.0F;
				if (entity instanceof EntityLivingBase) {
					f1 = EnchantmentHelper.func_152377_a(this.getHeldItem(),
							((EntityLivingBase) entity).getCreatureAttribute());
				} else {
					f1 = EnchantmentHelper.func_152377_a(this.getHeldItem(), EnumCreatureAttribute.UNDEFINED);
				}

				i = i + EnchantmentHelper.getKnockbackModifier(this);
				if (this.isSprinting()) {
					++i;
				}

				if (f > 0.0F || f1 > 0.0F) {
					boolean flag = this.fallDistance > 0.0F && !this.onGround && !this.isOnLadder() && !this.isInWater()
							&& !this.isPotionActive(Potion.blindness) && this.ridingEntity == null
							&& entity instanceof EntityLivingBase;
					if (flag && f > 0.0F) {
						f *= 1.5F;
					}

					f = f + f1;
					boolean flag1 = false;
					int j = EnchantmentHelper.getFireAspectModifier(this);
					if (entity instanceof EntityLivingBase && j > 0 && !entity.isBurning()) {
						flag1 = true;
						entity.setFire(1);
					}

					double d0 = entity.motionX;
					double d1 = entity.motionY;
					double d2 = entity.motionZ;
					boolean flag2 = entity.attackEntityFrom(DamageSource.causePlayerDamage(this), f);
					if (flag2) {
						if (i > 0) {
							entity.addVelocity(
									(double) (-MathHelper.sin(this.rotationYaw * 3.1415927F / 180.0F) * (float) i
											* 0.5F),
									0.1D, (double) (MathHelper.cos(this.rotationYaw * 3.1415927F / 180.0F) * (float) i
											* 0.5F));
							this.motionX *= 0.6D;
							this.motionZ *= 0.6D;
							this.setSprinting(false);
						}

						if (flag) {
							this.onCriticalHit(entity);
						}

						if (f1 > 0.0F) {
							this.onEnchantmentCritical(entity);
						}

						if (f >= 18.0F) {
							this.triggerAchievement(AchievementList.overkill);
						}

						this.setLastAttacker(entity);
						if (entity instanceof EntityLivingBase) {
							EnchantmentHelper.applyThornEnchantments((EntityLivingBase) entity, this);
						}

						EnchantmentHelper.applyArthropodEnchantments(this, entity);
						ItemStack itemstack = this.getCurrentEquippedItem();
						Object object = entity;
						if (entity instanceof EntityDragonPart) {
							IEntityMultiPart ientitymultipart = ((EntityDragonPart) entity).entityDragonObj;
							if (ientitymultipart instanceof EntityLivingBase) {
								object = (EntityLivingBase) ientitymultipart;
							}
						}

						if (itemstack != null && object instanceof EntityLivingBase) {
							itemstack.hitEntity((EntityLivingBase) object, this);
							if (itemstack.stackSize <= 0) {
								this.destroyCurrentEquippedItem();
							}
						}

						if (entity instanceof EntityLivingBase) {
							this.addStat(StatList.damageDealtStat, Math.round(f * 10.0F));
							if (j > 0) {
								entity.setFire(j * 4);
							}
						}

						this.addExhaustion(0.3F);
					} else if (flag1) {
						entity.extinguish();
					}
				}

			}
		}
	}

	/**+
	 * Called when the player performs a critical hit on the Entity.
	 * Args: entity that was hit critically
	 */
	public void onCriticalHit(Entity var1) {
	}

	public void onEnchantmentCritical(Entity var1) {
	}

	public void respawnPlayer() {
	}

	/**+
	 * Will get destroyed next tick.
	 */
	public void setDead() {
		super.setDead();
		this.inventoryContainer.onContainerClosed(this);
		if (this.openContainer != null) {
			this.openContainer.onContainerClosed(this);
		}

	}

	/**+
	 * Checks if this entity is inside of an opaque block
	 */
	public boolean isEntityInsideOpaqueBlock() {
		return !this.sleeping && super.isEntityInsideOpaqueBlock();
	}

	/**+
	 * returns true if this is an EntityPlayerSP, or the logged in
	 * player.
	 */
	public boolean isUser() {
		return false;
	}

	/**+
	 * Returns the GameProfile for this player
	 */
	public GameProfile getGameProfile() {
		return this.gameProfile;
	}

	public EntityPlayer.EnumStatus trySleep(BlockPos blockpos) {

		if (this.isRiding()) {
			this.mountEntity((Entity) null);
		}

		this.setSize(0.2F, 0.2F);
		if (this.worldObj.isBlockLoaded(blockpos)) {
			EnumFacing enumfacing = (EnumFacing) this.worldObj.getBlockState(blockpos)
					.getValue(BlockDirectional.FACING);
			float f = 0.5F;
			float f1 = 0.5F;
			switch (enumfacing) {
			case SOUTH:
				f1 = 0.9F;
				break;
			case NORTH:
				f1 = 0.1F;
				break;
			case WEST:
				f = 0.1F;
				break;
			case EAST:
				f = 0.9F;
			}

			this.func_175139_a(enumfacing);
			this.setPosition((double) ((float) blockpos.getX() + f), (double) ((float) blockpos.getY() + 0.6875F),
					(double) ((float) blockpos.getZ() + f1));
		} else {
			this.setPosition((double) ((float) blockpos.getX() + 0.5F), (double) ((float) blockpos.getY() + 0.6875F),
					(double) ((float) blockpos.getZ() + 0.5F));
		}

		this.sleeping = true;
		this.sleepTimer = 0;
		this.playerLocation = blockpos;
		this.motionX = this.motionZ = this.motionY = 0.0D;

		return EntityPlayer.EnumStatus.OK;
	}

	private void func_175139_a(EnumFacing parEnumFacing) {
		this.renderOffsetX = 0.0F;
		this.renderOffsetZ = 0.0F;
		switch (parEnumFacing) {
		case SOUTH:
			this.renderOffsetZ = -1.8F;
			break;
		case NORTH:
			this.renderOffsetZ = 1.8F;
			break;
		case WEST:
			this.renderOffsetX = 1.8F;
			break;
		case EAST:
			this.renderOffsetX = -1.8F;
		}

	}

	/**+
	 * Wake up the player if they're sleeping.
	 */
	public void wakeUpPlayer(boolean flag, boolean flag1, boolean flag2) {
		this.setSize(0.6F, 1.8F);
		IBlockState iblockstate = this.worldObj.getBlockState(this.playerLocation);
		if (this.playerLocation != null && iblockstate.getBlock() == Blocks.bed) {
			this.worldObj.setBlockState(this.playerLocation,
					iblockstate.withProperty(BlockBed.OCCUPIED, Boolean.valueOf(false)), 4);
			BlockPos blockpos = BlockBed.getSafeExitLocation(this.worldObj, this.playerLocation, 0);
			if (blockpos == null) {
				blockpos = this.playerLocation.up();
			}

			this.setPosition((double) ((float) blockpos.getX() + 0.5F), (double) ((float) blockpos.getY() + 0.1F),
					(double) ((float) blockpos.getZ() + 0.5F));
		}

		this.sleeping = false;

		this.sleepTimer = flag ? 0 : 100;
		if (flag2) {
			this.setSpawnPoint(this.playerLocation, false);
		}

	}

	private boolean isInBed() {
		return this.worldObj.getBlockState(this.playerLocation).getBlock() == Blocks.bed;
	}

	/**+
	 * Return null if bed is invalid
	 */
	public static BlockPos getBedSpawnLocation(World worldIn, BlockPos bedLocation, boolean forceSpawn) {
		Block block = worldIn.getBlockState(bedLocation).getBlock();
		if (block != Blocks.bed) {
			if (!forceSpawn) {
				return null;
			} else {
				boolean flag = block.func_181623_g();
				boolean flag1 = worldIn.getBlockState(bedLocation.up()).getBlock().func_181623_g();
				return flag && flag1 ? bedLocation : null;
			}
		} else {
			return BlockBed.getSafeExitLocation(worldIn, bedLocation, 0);
		}
	}

	/**+
	 * Returns the orientation of the bed in degrees.
	 */
	public float getBedOrientationInDegrees() {
		if (this.playerLocation != null) {
			EnumFacing enumfacing = (EnumFacing) this.worldObj.getBlockState(this.playerLocation)
					.getValue(BlockDirectional.FACING);
			switch (enumfacing) {
			case SOUTH:
				return 90.0F;
			case NORTH:
				return 270.0F;
			case WEST:
				return 0.0F;
			case EAST:
				return 180.0F;
			}
		}

		return 0.0F;
	}

	/**+
	 * Returns whether player is sleeping or not
	 */
	public boolean isPlayerSleeping() {
		return this.sleeping;
	}

	/**+
	 * Returns whether or not the player is asleep and the screen
	 * has fully faded.
	 */
	public boolean isPlayerFullyAsleep() {
		return this.sleeping && this.sleepTimer >= 100;
	}

	public int getSleepTimer() {
		return this.sleepTimer;
	}

	public void addChatComponentMessage(IChatComponent var1) {
	}

	public BlockPos getBedLocation() {
		return this.spawnChunk;
	}

	public boolean isSpawnForced() {
		return this.spawnForced;
	}

	public void setSpawnPoint(BlockPos pos, boolean forced) {
		if (pos != null) {
			this.spawnChunk = pos;
			this.spawnForced = forced;
		} else {
			this.spawnChunk = null;
			this.spawnForced = false;
		}

	}

	/**+
	 * Will trigger the specified trigger.
	 */
	public void triggerAchievement(StatBase achievementIn) {
		this.addStat(achievementIn, 1);
	}

	/**+
	 * Adds a value to a statistic field.
	 */
	public void addStat(StatBase var1, int var2) {
	}

	public void func_175145_a(StatBase var1) {
	}

	/**+
	 * Causes this entity to do an upwards motion (jumping).
	 */
	public void jump() {
		super.jump();
		this.triggerAchievement(StatList.jumpStat);
		if (this.isSprinting()) {
			this.addExhaustion(0.8F);
		} else {
			this.addExhaustion(0.2F);
		}

	}

	/**+
	 * Moves the entity based on the specified heading. Args:
	 * strafe, forward
	 */
	public void moveEntityWithHeading(float f, float f1) {
		double d0 = this.posX;
		double d1 = this.posY;
		double d2 = this.posZ;
		if (this.capabilities.isFlying && this.ridingEntity == null) {
			double d3 = this.motionY;
			float f2 = this.jumpMovementFactor;
			this.jumpMovementFactor = this.capabilities.getFlySpeed() * (float) (this.isSprinting() ? 2 : 1);
			super.moveEntityWithHeading(f, f1);
			this.motionY = d3 * 0.6D;
			this.jumpMovementFactor = f2;
		} else {
			super.moveEntityWithHeading(f, f1);
		}

		this.addMovementStat(this.posX - d0, this.posY - d1, this.posZ - d2);
	}

	/**+
	 * the movespeed used for the new AI system
	 */
	public float getAIMoveSpeed() {
		return (float) this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue();
	}

	/**+
	 * Adds a value to a movement statistic field - like run, walk,
	 * swin or climb.
	 */
	public void addMovementStat(double parDouble1, double parDouble2, double parDouble3) {
		if (this.ridingEntity == null) {
			if (this.isInsideOfMaterial(Material.water)) {
				int i = Math.round(MathHelper.sqrt_double(
						parDouble1 * parDouble1 + parDouble2 * parDouble2 + parDouble3 * parDouble3) * 100.0F);
				if (i > 0) {
					this.addStat(StatList.distanceDoveStat, i);
					this.addExhaustion(0.015F * (float) i * 0.01F);
				}
			} else if (this.isInWater()) {
				int j = Math.round(MathHelper.sqrt_double(parDouble1 * parDouble1 + parDouble3 * parDouble3) * 100.0F);
				if (j > 0) {
					this.addStat(StatList.distanceSwumStat, j);
					this.addExhaustion(0.015F * (float) j * 0.01F);
				}
			} else if (this.isOnLadder()) {
				if (parDouble2 > 0.0D) {
					this.addStat(StatList.distanceClimbedStat, (int) Math.round(parDouble2 * 100.0D));
				}
			} else if (this.onGround) {
				int k = Math.round(MathHelper.sqrt_double(parDouble1 * parDouble1 + parDouble3 * parDouble3) * 100.0F);
				if (k > 0) {
					this.addStat(StatList.distanceWalkedStat, k);
					if (this.isSprinting()) {
						this.addStat(StatList.distanceSprintedStat, k);
						this.addExhaustion(0.099999994F * (float) k * 0.01F);
					} else {
						if (this.isSneaking()) {
							this.addStat(StatList.distanceCrouchedStat, k);
						}

						this.addExhaustion(0.01F * (float) k * 0.01F);
					}
				}
			} else {
				int l = Math.round(MathHelper.sqrt_double(parDouble1 * parDouble1 + parDouble3 * parDouble3) * 100.0F);
				if (l > 25) {
					this.addStat(StatList.distanceFlownStat, l);
				}
			}

		}
	}

	/**+
	 * Adds a value to a mounted movement statistic field - by
	 * minecart, boat, or pig.
	 */
	private void addMountedMovementStat(double parDouble1, double parDouble2, double parDouble3) {
		if (this.ridingEntity != null) {
			int i = Math.round(
					MathHelper.sqrt_double(parDouble1 * parDouble1 + parDouble2 * parDouble2 + parDouble3 * parDouble3)
							* 100.0F);
			if (i > 0) {
				if (this.ridingEntity instanceof EntityMinecart) {
					this.addStat(StatList.distanceByMinecartStat, i);
					if (this.startMinecartRidingCoordinate == null) {
						this.startMinecartRidingCoordinate = new BlockPos(this);
					} else if (this.startMinecartRidingCoordinate.distanceSq(
							(double) MathHelper.floor_double(this.posX), (double) MathHelper.floor_double(this.posY),
							(double) MathHelper.floor_double(this.posZ)) >= 1000000.0D) {
						this.triggerAchievement(AchievementList.onARail);
					}
				} else if (this.ridingEntity instanceof EntityBoat) {
					this.addStat(StatList.distanceByBoatStat, i);
				} else if (this.ridingEntity instanceof EntityPig) {
					this.addStat(StatList.distanceByPigStat, i);
				} else if (this.ridingEntity instanceof EntityHorse) {
					this.addStat(StatList.distanceByHorseStat, i);
				}
			}
		}

	}

	public void fall(float f, float f1) {
		if (!this.capabilities.allowFlying) {
			if (f >= 2.0F) {
				this.addStat(StatList.distanceFallenStat, (int) Math.round((double) f * 100.0D));
			}

			super.fall(f, f1);
		}
	}

	/**+
	 * sets the players height back to normal after doing things
	 * like sleeping and dieing
	 */
	protected void resetHeight() {
		if (!this.isSpectator()) {
			super.resetHeight();
		}

	}

	protected String getFallSoundString(int i) {
		return i > 4 ? "game.player.hurt.fall.big" : "game.player.hurt.fall.small";
	}

	/**+
	 * This method gets called when the entity kills another one.
	 */
	public void onKillEntity(EntityLivingBase entitylivingbase) {
		if (entitylivingbase instanceof IMob) {
			this.triggerAchievement(AchievementList.killEnemy);
		}

		EntityList.EntityEggInfo entitylist$entityegginfo = (EntityList.EntityEggInfo) EntityList.entityEggs
				.get(Integer.valueOf(EntityList.getEntityID(entitylivingbase)));
		if (entitylist$entityegginfo != null) {
			this.triggerAchievement(entitylist$entityegginfo.field_151512_d);
		}

	}

	/**+
	 * Sets the Entity inside a web block.
	 */
	public void setInWeb() {
		if (!this.capabilities.isFlying) {
			super.setInWeb();
		}

	}

	public ItemStack getCurrentArmor(int i) {
		return this.inventory.armorItemInSlot(i);
	}

	/**+
	 * Add experience points to player.
	 */
	public void addExperience(int amount) {
		this.addScore(amount);
		int i = Integer.MAX_VALUE - this.experienceTotal;
		if (amount > i) {
			amount = i;
		}

		this.experience += (float) amount / (float) this.xpBarCap();

		for (this.experienceTotal += amount; this.experience >= 1.0F; this.experience /= (float) this.xpBarCap()) {
			this.experience = (this.experience - 1.0F) * (float) this.xpBarCap();
			this.addExperienceLevel(1);
		}

	}

	public int getXPSeed() {
		return this.xpSeed;
	}

	public void removeExperienceLevel(int i) {
		this.experienceLevel -= i;
		if (this.experienceLevel < 0) {
			this.experienceLevel = 0;
			this.experience = 0.0F;
			this.experienceTotal = 0;
		}

		this.xpSeed = this.rand.nextInt();
	}

	/**+
	 * Add experience levels to this player.
	 */
	public void addExperienceLevel(int i) {
		this.experienceLevel += i;
		if (this.experienceLevel < 0) {
			this.experienceLevel = 0;
			this.experience = 0.0F;
			this.experienceTotal = 0;
		}

		if (i > 0 && this.experienceLevel % 5 == 0 && (float) this.lastXPSound < (float) this.ticksExisted - 100.0F) {
			float f = this.experienceLevel > 30 ? 1.0F : (float) this.experienceLevel / 30.0F;
			this.worldObj.playSoundAtEntity(this, "random.levelup", f * 0.75F, 1.0F);
			this.lastXPSound = this.ticksExisted;
		}

	}

	/**+
	 * This method returns the cap amount of experience that the
	 * experience bar can hold. With each level, the experience cap
	 * on the player's experience bar is raised by 10.
	 */
	public int xpBarCap() {
		return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9
				: (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
	}

	/**+
	 * increases exhaustion level by supplied amount
	 */
	public void addExhaustion(float parFloat1) {

	}

	/**+
	 * Returns the player's FoodStats object.
	 */
	public FoodStats getFoodStats() {
		return this.foodStats;
	}

	public boolean canEat(boolean ignoreHunger) {
		return (ignoreHunger || this.foodStats.needFood()) && !this.capabilities.disableDamage;
	}

	/**+
	 * Checks if the player's health is not full and not zero.
	 */
	public boolean shouldHeal() {
		return this.getHealth() > 0.0F && this.getHealth() < this.getMaxHealth();
	}

	/**+
	 * sets the itemInUse when the use item button is clicked. Args:
	 * itemstack, int maxItemUseDuration
	 */
	public void setItemInUse(ItemStack itemstack, int i) {
		if (itemstack != this.itemInUse) {
			this.itemInUse = itemstack;
			this.itemInUseCount = i;
		}
	}

	public boolean isAllowEdit() {
		return this.capabilities.allowEdit;
	}

	public boolean canPlayerEdit(BlockPos parBlockPos, EnumFacing parEnumFacing, ItemStack parItemStack) {
		if (this.capabilities.allowEdit) {
			return true;
		} else if (parItemStack == null) {
			return false;
		} else {
			BlockPos blockpos = parBlockPos.offset(parEnumFacing.getOpposite());
			Block block = this.worldObj.getBlockState(blockpos).getBlock();
			return parItemStack.canPlaceOn(block) || parItemStack.canEditBlocks();
		}
	}

	/**+
	 * Get the experience points the entity currently has.
	 */
	protected int getExperiencePoints(EntityPlayer var1) {
		if (this.worldObj.getGameRules().getBoolean("keepInventory")) {
			return 0;
		} else {
			int i = this.experienceLevel * 7;
			return i > 100 ? 100 : i;
		}
	}

	/**+
	 * Only use is to identify if class is an instance of player for
	 * experience dropping
	 */
	protected boolean isPlayer() {
		return true;
	}

	public boolean getAlwaysRenderNameTagForRender() {
		return true;
	}

	/**+
	 * Copies the values from the given player into this player if
	 * boolean par2 is true. Always clones Ender Chest Inventory.
	 */
	public void clonePlayer(EntityPlayer entityplayer, boolean flag) {
		if (flag) {
			this.inventory.copyInventory(entityplayer.inventory);
			this.setHealth(entityplayer.getHealth());
			this.foodStats = entityplayer.foodStats;
			this.experienceLevel = entityplayer.experienceLevel;
			this.experienceTotal = entityplayer.experienceTotal;
			this.experience = entityplayer.experience;
			this.setScore(entityplayer.getScore());
			this.field_181016_an = entityplayer.field_181016_an;
			this.field_181017_ao = entityplayer.field_181017_ao;
			this.field_181018_ap = entityplayer.field_181018_ap;
		} else if (this.worldObj.getGameRules().getBoolean("keepInventory")) {
			this.inventory.copyInventory(entityplayer.inventory);
			this.experienceLevel = entityplayer.experienceLevel;
			this.experienceTotal = entityplayer.experienceTotal;
			this.experience = entityplayer.experience;
			this.setScore(entityplayer.getScore());
		}

		this.xpSeed = entityplayer.xpSeed;
		this.theInventoryEnderChest = entityplayer.theInventoryEnderChest;
		this.getDataWatcher().updateObject(10, Byte.valueOf(entityplayer.getDataWatcher().getWatchableObjectByte(10)));
	}

	/**+
	 * returns if this entity triggers Block.onEntityWalking on the
	 * blocks they walk on. used for spiders and wolves to prevent
	 * them from trampling crops
	 */
	protected boolean canTriggerWalking() {
		return !this.capabilities.isFlying;
	}

	/**+
	 * Sends the player's abilities to the server (if there is one).
	 */
	public void sendPlayerAbilities() {
	}

	/**+
	 * Sets the player's game mode and sends it to them.
	 */
	public void setGameType(WorldSettings.GameType var1) {
	}

	/**+
	 * Gets the name of this command sender (usually username, but
	 * possibly "Rcon")
	 */
	public String getName() {
		return this.gameProfile.getName();
	}

	/**+
	 * Returns the InventoryEnderChest of this player.
	 */
	public InventoryEnderChest getInventoryEnderChest() {
		return this.theInventoryEnderChest;
	}

	/**+
	 * 0: Tool in Hand; 1-4: Armor
	 */
	public ItemStack getEquipmentInSlot(int i) {
		return i == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[i - 1];
	}

	/**+
	 * Returns the item that this EntityLiving is holding, if any.
	 */
	public ItemStack getHeldItem() {
		return this.inventory.getCurrentItem();
	}

	/**+
	 * Sets the held item, or an armor slot. Slot 0 is held item.
	 * Slot 1-4 is armor. Params: Item, slot
	 */
	public void setCurrentItemOrArmor(int i, ItemStack itemstack) {
		this.inventory.armorInventory[i] = itemstack;
	}

	/**+
	 * Only used by renderer in EntityLivingBase
	 * subclasses.\nDetermines if an entity is visible or not to a
	 * specfic player, if the entity is normally invisible.\nFor
	 * EntityLivingBase subclasses, returning false when invisible
	 * will render the entity semitransparent.
	 */
	public boolean isInvisibleToPlayer(EntityPlayer entityplayer) {
		if (!this.isInvisible()) {
			return false;
		} else if (entityplayer.isSpectator()) {
			return false;
		} else {
			Team team = this.getTeam();
			return team == null || entityplayer == null || entityplayer.getTeam() != team
					|| !team.getSeeFriendlyInvisiblesEnabled();
		}
	}

	public abstract boolean isSpectator();

	/**+
	 * returns the inventory of this entity (only used in
	 * EntityPlayerMP it seems)
	 */
	public ItemStack[] getInventory() {
		return this.inventory.armorInventory;
	}

	public boolean isPushedByWater() {
		return !this.capabilities.isFlying;
	}

	public Scoreboard getWorldScoreboard() {
		return this.worldObj.getScoreboard();
	}

	public Team getTeam() {
		return this.getWorldScoreboard().getPlayersTeam(this.getName());
	}

	/**+
	 * Get the formatted ChatComponent that will be used for the
	 * sender's username in chat
	 */
	public IChatComponent getDisplayName() {
		ChatComponentText chatcomponenttext = new ChatComponentText(
				ScorePlayerTeam.formatPlayerName(this.getTeam(), this.getName()));
		chatcomponenttext.getChatStyle()
				.setChatClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/msg " + this.getName() + " "));
		chatcomponenttext.getChatStyle().setChatHoverEvent(this.getHoverEvent());
		chatcomponenttext.getChatStyle().setInsertion(this.getName());
		return chatcomponenttext;
	}

	public float getEyeHeight() {
		float f = 1.62F;
		if (this.isPlayerSleeping()) {
			f = 0.2F;
		}

		if (this.isSneaking()) {
			f -= 0.08F;
		}

		return f;
	}

	public void setAbsorptionAmount(float f) {
		if (f < 0.0F) {
			f = 0.0F;
		}

		this.getDataWatcher().updateObject(17, Float.valueOf(f));
	}

	public float getAbsorptionAmount() {
		return this.getDataWatcher().getWatchableObjectFloat(17);
	}

	/**+
	 * Gets a players UUID given their GameProfie
	 */
	public static EaglercraftUUID getUUID(GameProfile profile) {
		EaglercraftUUID uuid = profile.getId();
		if (uuid == null) {
			uuid = getOfflineUUID(profile.getName());
		}

		return uuid;
	}

	public static EaglercraftUUID getOfflineUUID(String username) {
		return EaglercraftUUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(Charsets.UTF_8));
	}

	/**+
	 * Check whether this player can open an inventory locked with
	 * the given LockCode.
	 */
	public boolean canOpen(LockCode code) {
		if (code.isEmpty()) {
			return true;
		} else {
			ItemStack itemstack = this.getCurrentEquippedItem();
			return itemstack != null && itemstack.hasDisplayName() ? itemstack.getDisplayName().equals(code.getLock())
					: false;
		}
	}

	public boolean isWearing(EnumPlayerModelParts parEnumPlayerModelParts) {
		return (this.getDataWatcher().getWatchableObjectByte(10)
				& parEnumPlayerModelParts.getPartMask()) == parEnumPlayerModelParts.getPartMask();
	}

	/**+
	 * Returns true if the command sender should be sent feedback
	 * about executed commands
	 */
	public boolean sendCommandFeedback() {
		return true;
	}

	public boolean replaceItemInInventory(int i, ItemStack itemstack) {
		if (i >= 0 && i < this.inventory.mainInventory.length) {
			this.inventory.setInventorySlotContents(i, itemstack);
			return true;
		} else {
			int j = i - 100;
			if (j >= 0 && j < this.inventory.armorInventory.length) {
				int l = j + 1;
				if (itemstack != null && itemstack.getItem() != null) {
					if (itemstack.getItem() instanceof ItemArmor) {
						if (EntityLiving.getArmorPosition(itemstack) != l) {
							return false;
						}
					} else if (l != 4
							|| itemstack.getItem() != Items.skull && !(itemstack.getItem() instanceof ItemBlock)) {
						return false;
					}
				}

				this.inventory.setInventorySlotContents(j + this.inventory.mainInventory.length, itemstack);
				return true;
			} else {
				int k = i - 200;
				if (k >= 0 && k < this.theInventoryEnderChest.getSizeInventory()) {
					this.theInventoryEnderChest.setInventorySlotContents(k, itemstack);
					return true;
				} else {
					return false;
				}
			}
		}
	}

	/**+
	 * Whether the "reducedDebugInfo" option is active for this
	 * player.
	 */
	public boolean hasReducedDebug() {
		return this.hasReducedDebug;
	}

	public void setReducedDebug(boolean reducedDebug) {
		this.hasReducedDebug = reducedDebug;
	}

	public static enum EnumChatVisibility {
		FULL(0, "options.chat.visibility.full"), SYSTEM(1, "options.chat.visibility.system"),
		HIDDEN(2, "options.chat.visibility.hidden");

		private static final EntityPlayer.EnumChatVisibility[] ID_LOOKUP = new EntityPlayer.EnumChatVisibility[values().length];
		private final int chatVisibility;
		private final String resourceKey;

		private EnumChatVisibility(int id, String resourceKey) {
			this.chatVisibility = id;
			this.resourceKey = resourceKey;
		}

		public int getChatVisibility() {
			return this.chatVisibility;
		}

		public static EntityPlayer.EnumChatVisibility getEnumChatVisibility(int id) {
			return ID_LOOKUP[id % ID_LOOKUP.length];
		}

		public String getResourceKey() {
			return this.resourceKey;
		}

		static {
			for (EntityPlayer.EnumChatVisibility entityplayer$enumchatvisibility : values()) {
				ID_LOOKUP[entityplayer$enumchatvisibility.chatVisibility] = entityplayer$enumchatvisibility;
			}

		}
	}

	public static enum EnumStatus {
		OK, NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW, TOO_FAR_AWAY, OTHER_PROBLEM, NOT_SAFE;
	}
}