001    package net.minecraft.entity.player;
002    
003    import cpw.mods.fml.common.FMLCommonHandler;
004    import cpw.mods.fml.common.network.FMLNetworkHandler;
005    import cpw.mods.fml.relauncher.Side;
006    import cpw.mods.fml.relauncher.SideOnly;
007    import java.util.Iterator;
008    import java.util.List;
009    import net.minecraft.block.Block;
010    import net.minecraft.block.BlockBed;
011    import net.minecraft.block.material.Material;
012    import net.minecraft.command.ICommandSender;
013    import net.minecraft.enchantment.EnchantmentHelper;
014    import net.minecraft.enchantment.EnchantmentThorns;
015    import net.minecraft.entity.Entity;
016    import net.minecraft.entity.EntityLiving;
017    import net.minecraft.entity.IMerchant;
018    import net.minecraft.entity.item.EntityBoat;
019    import net.minecraft.entity.item.EntityItem;
020    import net.minecraft.entity.item.EntityMinecart;
021    import net.minecraft.entity.monster.EntityCreeper;
022    import net.minecraft.entity.monster.EntityGhast;
023    import net.minecraft.entity.monster.EntityMob;
024    import net.minecraft.entity.monster.IMob;
025    import net.minecraft.entity.passive.EntityPig;
026    import net.minecraft.entity.passive.EntityWolf;
027    import net.minecraft.entity.projectile.EntityArrow;
028    import net.minecraft.entity.projectile.EntityFishHook;
029    import net.minecraft.inventory.Container;
030    import net.minecraft.inventory.ContainerPlayer;
031    import net.minecraft.inventory.IInventory;
032    import net.minecraft.inventory.InventoryEnderChest;
033    import net.minecraft.item.EnumAction;
034    import net.minecraft.item.Item;
035    import net.minecraft.item.ItemStack;
036    import net.minecraft.nbt.NBTTagCompound;
037    import net.minecraft.nbt.NBTTagList;
038    import net.minecraft.potion.Potion;
039    import net.minecraft.stats.AchievementList;
040    import net.minecraft.stats.StatBase;
041    import net.minecraft.stats.StatList;
042    import net.minecraft.tileentity.TileEntity;
043    import net.minecraft.tileentity.TileEntityBeacon;
044    import net.minecraft.tileentity.TileEntityBrewingStand;
045    import net.minecraft.tileentity.TileEntityDispenser;
046    import net.minecraft.tileentity.TileEntityFurnace;
047    import net.minecraft.util.AxisAlignedBB;
048    import net.minecraft.util.ChunkCoordinates;
049    import net.minecraft.util.DamageSource;
050    import net.minecraft.util.FoodStats;
051    import net.minecraft.util.MathHelper;
052    import net.minecraft.util.StringTranslate;
053    import net.minecraft.util.Vec3;
054    import net.minecraft.world.EnumGameType;
055    import net.minecraft.world.World;
056    import net.minecraft.world.chunk.IChunkProvider;
057    
058    import net.minecraftforge.common.ForgeHooks;
059    import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
060    import net.minecraftforge.common.MinecraftForge;
061    import net.minecraftforge.event.ForgeEventFactory;
062    import net.minecraftforge.event.entity.living.LivingHurtEvent;
063    import net.minecraftforge.event.entity.player.AttackEntityEvent;
064    import net.minecraftforge.event.entity.player.EntityInteractEvent;
065    import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
066    import net.minecraftforge.event.entity.player.PlayerDropsEvent;
067    import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
068    
069    public abstract class EntityPlayer extends EntityLiving implements ICommandSender
070    {
071        public static final String PERSISTED_NBT_TAG = "PlayerPersisted";
072    
073        /** Inventory of the player */
074        public InventoryPlayer inventory = new InventoryPlayer(this);
075        private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest();
076    
077        /**
078         * The Container for the player's inventory (which opens when they press E)
079         */
080        public Container inventoryContainer;
081    
082        /** The Container the player has open. */
083        public Container openContainer;
084    
085        /** The player's food stats. (See class FoodStats) */
086        protected FoodStats foodStats = new FoodStats();
087    
088        /**
089         * Used to tell if the player pressed jump twice. If this is at 0 and it's pressed (And they are allowed to fly, as
090         * defined in the player's movementInput) it sets this to 7. If it's pressed and it's greater than 0 enable fly.
091         */
092        protected int flyToggleTimer = 0;
093        public byte field_71098_bD = 0;
094        public float prevCameraYaw;
095        public float cameraYaw;
096        public String username;
097        @SideOnly(Side.CLIENT)
098        public String playerCloakUrl;
099    
100        /**
101         * Used by EntityPlayer to prevent too many xp orbs from getting absorbed at once.
102         */
103        public int xpCooldown = 0;
104        public double field_71091_bM;
105        public double field_71096_bN;
106        public double field_71097_bO;
107        public double field_71094_bP;
108        public double field_71095_bQ;
109        public double field_71085_bR;
110    
111        /** Boolean value indicating weather a player is sleeping or not */
112        protected boolean sleeping;
113    
114        /**
115         * The chunk coordinates of the bed the player is in (null if player isn't in a bed).
116         */
117        public ChunkCoordinates playerLocation;
118        private int sleepTimer;
119        public float field_71079_bU;
120        @SideOnly(Side.CLIENT)
121        public float field_71082_cx;
122        public float field_71089_bV;
123    
124        /**
125         * Holds the last coordinate to spawn based on last bed that the player sleep.
126         */
127        private ChunkCoordinates spawnChunk;
128    
129        /**
130         * Whether this player's spawn point is forced, preventing execution of bed checks.
131         */
132        private boolean spawnForced;
133    
134        /** Holds the coordinate of the player when enter a minecraft to ride. */
135        private ChunkCoordinates startMinecartRidingCoordinate;
136    
137        /** The player's capabilities. (See class PlayerCapabilities) */
138        public PlayerCapabilities capabilities = new PlayerCapabilities();
139    
140        /** The current experience level the player is on. */
141        public int experienceLevel;
142    
143        /**
144         * The total amount of experience the player has. This also includes the amount of experience within their
145         * Experience Bar.
146         */
147        public int experienceTotal;
148    
149        /**
150         * The current amount of experience the player has within their Experience Bar.
151         */
152        public float experience;
153    
154        /**
155         * This is the item that is in use when the player is holding down the useItemButton (e.g., bow, food, sword)
156         */
157        private ItemStack itemInUse;
158    
159        /**
160         * This field starts off equal to getMaxItemUseDuration and is decremented on each tick
161         */
162        private int itemInUseCount;
163        protected float speedOnGround = 0.1F;
164        protected float speedInAir = 0.02F;
165        private int field_82249_h = 0;
166    
167        /**
168         * An instance of a fishing rod's hook. If this isn't null, the icon image of the fishing rod is slightly different
169         */
170        public EntityFishHook fishEntity = null;
171    
172        public EntityPlayer(World par1World)
173        {
174            super(par1World);
175            this.inventoryContainer = new ContainerPlayer(this.inventory, !par1World.isRemote, this);
176            this.openContainer = this.inventoryContainer;
177            this.yOffset = 1.62F;
178            ChunkCoordinates var2 = par1World.getSpawnPoint();
179            this.setLocationAndAngles((double)var2.posX + 0.5D, (double)(var2.posY + 1), (double)var2.posZ + 0.5D, 0.0F, 0.0F);
180            this.entityType = "humanoid";
181            this.field_70741_aB = 180.0F;
182            this.fireResistance = 20;
183            this.texture = "/mob/char.png";
184        }
185    
186        public int getMaxHealth()
187        {
188            return 20;
189        }
190    
191        protected void entityInit()
192        {
193            super.entityInit();
194            this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
195            this.dataWatcher.addObject(17, Byte.valueOf((byte)0));
196            this.dataWatcher.addObject(18, Integer.valueOf(0));
197        }
198    
199        @SideOnly(Side.CLIENT)
200    
201        /**
202         * returns the ItemStack containing the itemInUse
203         */
204        public ItemStack getItemInUse()
205        {
206            return this.itemInUse;
207        }
208    
209        @SideOnly(Side.CLIENT)
210    
211        /**
212         * Returns the item in use count
213         */
214        public int getItemInUseCount()
215        {
216            return this.itemInUseCount;
217        }
218    
219        /**
220         * Checks if the entity is currently using an item (e.g., bow, food, sword) by holding down the useItemButton
221         */
222        public boolean isUsingItem()
223        {
224            return this.itemInUse != null;
225        }
226    
227        @SideOnly(Side.CLIENT)
228    
229        /**
230         * gets the duration for how long the current itemInUse has been in use
231         */
232        public int getItemInUseDuration()
233        {
234            return this.isUsingItem() ? this.itemInUse.getMaxItemUseDuration() - this.itemInUseCount : 0;
235        }
236    
237        public void stopUsingItem()
238        {
239            if (this.itemInUse != null)
240            {
241                this.itemInUse.onPlayerStoppedUsing(this.worldObj, this, this.itemInUseCount);
242            }
243    
244            this.clearItemInUse();
245        }
246    
247        public void clearItemInUse()
248        {
249            this.itemInUse = null;
250            this.itemInUseCount = 0;
251    
252            if (!this.worldObj.isRemote)
253            {
254                this.setEating(false);
255            }
256        }
257    
258        public boolean isBlocking()
259        {
260            return this.isUsingItem() && Item.itemsList[this.itemInUse.itemID].getItemUseAction(this.itemInUse) == EnumAction.block;
261        }
262    
263        /**
264         * Called to update the entity's position/logic.
265         */
266        public void onUpdate()
267        {
268            FMLCommonHandler.instance().onPlayerPreTick(this);
269            if (this.itemInUse != null)
270            {
271                ItemStack var1 = this.inventory.getCurrentItem();
272    
273                if (var1 == this.itemInUse)
274                {
275                    itemInUse.getItem().onUsingItemTick(itemInUse, this, itemInUseCount);
276                    if (this.itemInUseCount <= 25 && this.itemInUseCount % 4 == 0)
277                    {
278                        this.updateItemUse(var1, 5);
279                    }
280    
281                    if (--this.itemInUseCount == 0 && !this.worldObj.isRemote)
282                    {
283                        this.onItemUseFinish();
284                    }
285                }
286                else
287                {
288                    this.clearItemInUse();
289                }
290            }
291    
292            if (this.xpCooldown > 0)
293            {
294                --this.xpCooldown;
295            }
296    
297            if (this.isPlayerSleeping())
298            {
299                ++this.sleepTimer;
300    
301                if (this.sleepTimer > 100)
302                {
303                    this.sleepTimer = 100;
304                }
305    
306                if (!this.worldObj.isRemote)
307                {
308                    if (!this.isInBed())
309                    {
310                        this.wakeUpPlayer(true, true, false);
311                    }
312                    else if (this.worldObj.isDaytime())
313                    {
314                        this.wakeUpPlayer(false, true, true);
315                    }
316                }
317            }
318            else if (this.sleepTimer > 0)
319            {
320                ++this.sleepTimer;
321    
322                if (this.sleepTimer >= 110)
323                {
324                    this.sleepTimer = 0;
325                }
326            }
327    
328            super.onUpdate();
329    
330            if (!this.worldObj.isRemote && this.openContainer != null && !this.openContainer.canInteractWith(this))
331            {
332                this.closeScreen();
333                this.openContainer = this.inventoryContainer;
334            }
335    
336            if (this.isBurning() && this.capabilities.disableDamage)
337            {
338                this.extinguish();
339            }
340    
341            this.field_71091_bM = this.field_71094_bP;
342            this.field_71096_bN = this.field_71095_bQ;
343            this.field_71097_bO = this.field_71085_bR;
344            double var9 = this.posX - this.field_71094_bP;
345            double var3 = this.posY - this.field_71095_bQ;
346            double var5 = this.posZ - this.field_71085_bR;
347            double var7 = 10.0D;
348    
349            if (var9 > var7)
350            {
351                this.field_71091_bM = this.field_71094_bP = this.posX;
352            }
353    
354            if (var5 > var7)
355            {
356                this.field_71097_bO = this.field_71085_bR = this.posZ;
357            }
358    
359            if (var3 > var7)
360            {
361                this.field_71096_bN = this.field_71095_bQ = this.posY;
362            }
363    
364            if (var9 < -var7)
365            {
366                this.field_71091_bM = this.field_71094_bP = this.posX;
367            }
368    
369            if (var5 < -var7)
370            {
371                this.field_71097_bO = this.field_71085_bR = this.posZ;
372            }
373    
374            if (var3 < -var7)
375            {
376                this.field_71096_bN = this.field_71095_bQ = this.posY;
377            }
378    
379            this.field_71094_bP += var9 * 0.25D;
380            this.field_71085_bR += var5 * 0.25D;
381            this.field_71095_bQ += var3 * 0.25D;
382            this.addStat(StatList.minutesPlayedStat, 1);
383    
384            if (this.ridingEntity == null)
385            {
386                this.startMinecartRidingCoordinate = null;
387            }
388    
389            if (!this.worldObj.isRemote)
390            {
391                this.foodStats.onUpdate(this);
392            }
393            FMLCommonHandler.instance().onPlayerPostTick(this);
394        }
395    
396        /**
397         * Return the amount of time this entity should stay in a portal before being transported.
398         */
399        public int getMaxInPortalTime()
400        {
401            return this.capabilities.disableDamage ? 0 : 80;
402        }
403    
404        /**
405         * Return the amount of cooldown before this entity can use a portal again.
406         */
407        public int getPortalCooldown()
408        {
409            return 10;
410        }
411    
412        public void playSound(String par1Str, float par2, float par3)
413        {
414            this.worldObj.playSoundToNearExcept(this, par1Str, par2, par3);
415        }
416    
417        /**
418         * Plays sounds and makes particles for item in use state
419         */
420        protected void updateItemUse(ItemStack par1ItemStack, int par2)
421        {
422            if (par1ItemStack.getItemUseAction() == EnumAction.drink)
423            {
424                this.playSound("random.drink", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
425            }
426    
427            if (par1ItemStack.getItemUseAction() == EnumAction.eat)
428            {
429                for (int var3 = 0; var3 < par2; ++var3)
430                {
431                    Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
432                    var4.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
433                    var4.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
434                    Vec3 var5 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.3D, (double)(-this.rand.nextFloat()) * 0.6D - 0.3D, 0.6D);
435                    var5.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
436                    var5.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
437                    var5 = var5.addVector(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
438                    this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().itemID, var5.xCoord, var5.yCoord, var5.zCoord, var4.xCoord, var4.yCoord + 0.05D, var4.zCoord);
439                }
440    
441                this.playSound("random.eat", 0.5F + 0.5F * (float)this.rand.nextInt(2), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
442            }
443        }
444    
445        /**
446         * Used for when item use count runs out, ie: eating completed
447         */
448        protected void onItemUseFinish()
449        {
450            if (this.itemInUse != null)
451            {
452                this.updateItemUse(this.itemInUse, 16);
453                int var1 = this.itemInUse.stackSize;
454                ItemStack var2 = this.itemInUse.onFoodEaten(this.worldObj, this);
455    
456                if (var2 != this.itemInUse || var2 != null && var2.stackSize != var1)
457                {
458                    this.inventory.mainInventory[this.inventory.currentItem] = var2;
459    
460                    if (var2.stackSize == 0)
461                    {
462                        this.inventory.mainInventory[this.inventory.currentItem] = null;
463                    }
464                }
465    
466                this.clearItemInUse();
467            }
468        }
469    
470        @SideOnly(Side.CLIENT)
471        public void handleHealthUpdate(byte par1)
472        {
473            if (par1 == 9)
474            {
475                this.onItemUseFinish();
476            }
477            else
478            {
479                super.handleHealthUpdate(par1);
480            }
481        }
482    
483        /**
484         * Dead and sleeping entities cannot move
485         */
486        protected boolean isMovementBlocked()
487        {
488            return this.getHealth() <= 0 || this.isPlayerSleeping();
489        }
490    
491        /**
492         * sets current screen to null (used on escape buttons of GUIs)
493         */
494        public void closeScreen()
495        {
496            this.openContainer = this.inventoryContainer;
497        }
498    
499        /**
500         * Handles updating while being ridden by an entity
501         */
502        public void updateRidden()
503        {
504            double var1 = this.posX;
505            double var3 = this.posY;
506            double var5 = this.posZ;
507            float var7 = this.rotationYaw;
508            float var8 = this.rotationPitch;
509            super.updateRidden();
510            this.prevCameraYaw = this.cameraYaw;
511            this.cameraYaw = 0.0F;
512            this.addMountedMovementStat(this.posX - var1, this.posY - var3, this.posZ - var5);
513    
514            if (this.ridingEntity instanceof EntityLiving && ((EntityLiving)ridingEntity).shouldRiderFaceForward(this))
515            {
516                this.rotationPitch = var8;
517                this.rotationYaw = var7;
518                this.renderYawOffset = ((EntityLiving)this.ridingEntity).renderYawOffset;
519            }
520        }
521    
522        @SideOnly(Side.CLIENT)
523    
524        /**
525         * Keeps moving the entity up so it isn't colliding with blocks and other requirements for this entity to be spawned
526         * (only actually used on players though its also on Entity)
527         */
528        public void preparePlayerToSpawn()
529        {
530            this.yOffset = 1.62F;
531            this.setSize(0.6F, 1.8F);
532            super.preparePlayerToSpawn();
533            this.setEntityHealth(this.getMaxHealth());
534            this.deathTime = 0;
535        }
536    
537        protected void updateEntityActionState()
538        {
539            this.updateArmSwingProgress();
540        }
541    
542        /**
543         * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
544         * use this to react to sunlight and start to burn.
545         */
546        public void onLivingUpdate()
547        {
548            if (this.flyToggleTimer > 0)
549            {
550                --this.flyToggleTimer;
551            }
552    
553            if (this.worldObj.difficultySetting == 0 && this.getHealth() < this.getMaxHealth() && this.ticksExisted % 20 * 12 == 0)
554            {
555                this.heal(1);
556            }
557    
558            this.inventory.decrementAnimations();
559            this.prevCameraYaw = this.cameraYaw;
560            super.onLivingUpdate();
561            this.landMovementFactor = this.capabilities.getWalkSpeed();
562            this.jumpMovementFactor = this.speedInAir;
563    
564            if (this.isSprinting())
565            {
566                this.landMovementFactor = (float)((double)this.landMovementFactor + (double)this.capabilities.getWalkSpeed() * 0.3D);
567                this.jumpMovementFactor = (float)((double)this.jumpMovementFactor + (double)this.speedInAir * 0.3D);
568            }
569    
570            float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
571            float var2 = (float)Math.atan(-this.motionY * 0.20000000298023224D) * 15.0F;
572    
573            if (var1 > 0.1F)
574            {
575                var1 = 0.1F;
576            }
577    
578            if (!this.onGround || this.getHealth() <= 0)
579            {
580                var1 = 0.0F;
581            }
582    
583            if (this.onGround || this.getHealth() <= 0)
584            {
585                var2 = 0.0F;
586            }
587    
588            this.cameraYaw += (var1 - this.cameraYaw) * 0.4F;
589            this.cameraPitch += (var2 - this.cameraPitch) * 0.8F;
590    
591            if (this.getHealth() > 0)
592            {
593                List var3 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(1.0D, 0.5D, 1.0D));
594    
595                if (var3 != null)
596                {
597                    for (int var4 = 0; var4 < var3.size(); ++var4)
598                    {
599                        Entity var5 = (Entity)var3.get(var4);
600    
601                        if (!var5.isDead)
602                        {
603                            this.collideWithPlayer(var5);
604                        }
605                    }
606                }
607            }
608        }
609    
610        private void collideWithPlayer(Entity par1Entity)
611        {
612            par1Entity.onCollideWithPlayer(this);
613        }
614    
615        public int getScore()
616        {
617            return this.dataWatcher.getWatchableObjectInt(18);
618        }
619    
620        /**
621         * Set player's score
622         */
623        public void setScore(int par1)
624        {
625            this.dataWatcher.updateObject(18, Integer.valueOf(par1));
626        }
627    
628        /**
629         * Add to player's score
630         */
631        public void addScore(int par1)
632        {
633            int var2 = this.getScore();
634            this.dataWatcher.updateObject(18, Integer.valueOf(var2 + par1));
635        }
636    
637        /**
638         * Called when the mob's health reaches 0.
639         */
640        public void onDeath(DamageSource par1DamageSource)
641        {
642            super.onDeath(par1DamageSource);
643            this.setSize(0.2F, 0.2F);
644            this.setPosition(this.posX, this.posY, this.posZ);
645            this.motionY = 0.10000000149011612D;
646    
647            captureDrops = true;
648            capturedDrops.clear();
649    
650            if (this.username.equals("Notch"))
651            {
652                this.dropPlayerItemWithRandomChoice(new ItemStack(Item.appleRed, 1), true);
653            }
654    
655            if (!this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
656            {
657                this.inventory.dropAllItems();
658            }
659    
660            captureDrops = false;
661    
662            if (!worldObj.isRemote)
663            {
664                PlayerDropsEvent event = new PlayerDropsEvent(this, par1DamageSource, capturedDrops, recentlyHit > 0);
665                if (!MinecraftForge.EVENT_BUS.post(event))
666                {
667                    for (EntityItem item : capturedDrops)
668                    {
669                        joinEntityItemWithWorld(item);
670                    }
671                }
672            }
673    
674            if (par1DamageSource != null)
675            {
676                this.motionX = (double)(-MathHelper.cos((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F);
677                this.motionZ = (double)(-MathHelper.sin((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F);
678            }
679            else
680            {
681                this.motionX = this.motionZ = 0.0D;
682            }
683    
684            this.yOffset = 0.1F;
685            this.addStat(StatList.deathsStat, 1);
686        }
687    
688        /**
689         * Adds a value to the player score. Currently not actually used and the entity passed in does nothing. Args:
690         * entity, scoreToAdd
691         */
692        public void addToPlayerScore(Entity par1Entity, int par2)
693        {
694            this.addScore(par2);
695    
696            if (par1Entity instanceof EntityPlayer)
697            {
698                this.addStat(StatList.playerKillsStat, 1);
699            }
700            else
701            {
702                this.addStat(StatList.mobKillsStat, 1);
703            }
704        }
705    
706        /**
707         * Called when player presses the drop item key
708         */
709        public EntityItem dropOneItem(boolean par1)
710        {
711            ItemStack stack = inventory.getCurrentItem();
712    
713            if (stack == null)
714            {
715                return null;
716            }
717    
718            if (stack.getItem().onDroppedByPlayer(stack, this))
719            {
720                int count = par1 && this.inventory.getCurrentItem() != null ? this.inventory.getCurrentItem().stackSize : 1;
721                return ForgeHooks.onPlayerTossEvent(this, inventory.decrStackSize(inventory.currentItem, count));
722            }
723    
724            return null;
725        }
726    
727        /**
728         * Args: itemstack - called when player drops an item stack that's not in his inventory (like items still placed in
729         * a workbench while the workbench'es GUI gets closed)
730         */
731        public EntityItem dropPlayerItem(ItemStack par1ItemStack)
732        {
733            return ForgeHooks.onPlayerTossEvent(this, par1ItemStack);
734        }
735    
736        /**
737         * Args: itemstack, flag
738         */
739        public EntityItem dropPlayerItemWithRandomChoice(ItemStack par1ItemStack, boolean par2)
740        {
741            if (par1ItemStack == null)
742            {
743                return null;
744            }
745            else
746            {
747                EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY - 0.30000001192092896D + (double)this.getEyeHeight(), this.posZ, par1ItemStack);
748                var3.delayBeforeCanPickup = 40;
749                float var4 = 0.1F;
750                float var5;
751    
752                if (par2)
753                {
754                    var5 = this.rand.nextFloat() * 0.5F;
755                    float var6 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
756                    var3.motionX = (double)(-MathHelper.sin(var6) * var5);
757                    var3.motionZ = (double)(MathHelper.cos(var6) * var5);
758                    var3.motionY = 0.20000000298023224D;
759                }
760                else
761                {
762                    var4 = 0.3F;
763                    var3.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4);
764                    var3.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4);
765                    var3.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI) * var4 + 0.1F);
766                    var4 = 0.02F;
767                    var5 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
768                    var4 *= this.rand.nextFloat();
769                    var3.motionX += Math.cos((double)var5) * (double)var4;
770                    var3.motionY += (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
771                    var3.motionZ += Math.sin((double)var5) * (double)var4;
772                }
773    
774                this.joinEntityItemWithWorld(var3);
775                this.addStat(StatList.dropStat, 1);
776                return var3;
777            }
778        }
779    
780        /**
781         * Joins the passed in entity item with the world. Args: entityItem
782         */
783        public void joinEntityItemWithWorld(EntityItem par1EntityItem)
784        {
785            if (captureDrops)
786            {
787                capturedDrops.add(par1EntityItem);
788            }
789            else
790            {
791                this.worldObj.spawnEntityInWorld(par1EntityItem);
792            }
793        }
794    
795        /**
796         * Returns how strong the player is against the specified block at this moment
797         * Deprecated in favor of the more sensitive version
798         */
799        @Deprecated
800        public float getCurrentPlayerStrVsBlock(Block par1Block)
801        {
802            return getCurrentPlayerStrVsBlock(par1Block, 0);
803        }
804    
805        public float getCurrentPlayerStrVsBlock(Block par1Block, int meta)
806        {
807            ItemStack stack = inventory.getCurrentItem();
808            float var2 = (stack == null ? 1.0F : stack.getItem().getStrVsBlock(stack, par1Block, meta));
809            int var3 = EnchantmentHelper.getEfficiencyModifier(this);
810            ItemStack var4 = this.inventory.getCurrentItem();
811    
812            if (var3 > 0 && var4 != null)
813            {
814                float var5 = (float)(var3 * var3 + 1);
815                boolean canHarvest = ForgeHooks.canToolHarvestBlock(par1Block, meta, var4);
816    
817                if (!canHarvest && var2 <= 1.0F)
818                {
819                    var2 += var5 * 0.08F;
820                }
821                else
822                {
823                    var2 += var5;
824                }
825            }
826    
827            if (this.isPotionActive(Potion.digSpeed))
828            {
829                var2 *= 1.0F + (float)(this.getActivePotionEffect(Potion.digSpeed).getAmplifier() + 1) * 0.2F;
830            }
831    
832            if (this.isPotionActive(Potion.digSlowdown))
833            {
834                var2 *= 1.0F - (float)(this.getActivePotionEffect(Potion.digSlowdown).getAmplifier() + 1) * 0.2F;
835            }
836    
837            if (this.isInsideOfMaterial(Material.water) && !EnchantmentHelper.getAquaAffinityModifier(this))
838            {
839                var2 /= 5.0F;
840            }
841    
842            if (!this.onGround)
843            {
844                var2 /= 5.0F;
845            }
846    
847            var2 = ForgeEventFactory.getBreakSpeed(this, par1Block, meta, var2);
848            return (var2 < 0 ? 0 : var2);
849        }
850    
851        /**
852         * Checks if the player has the ability to harvest a block (checks current inventory item for a tool if necessary)
853         */
854        public boolean canHarvestBlock(Block par1Block)
855        {
856            return ForgeEventFactory.doPlayerHarvestCheck(this, par1Block, inventory.canHarvestBlock(par1Block));
857        }
858    
859        /**
860         * (abstract) Protected helper method to read subclass entity data from NBT.
861         */
862        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
863        {
864            super.readEntityFromNBT(par1NBTTagCompound);
865            NBTTagList var2 = par1NBTTagCompound.getTagList("Inventory");
866            this.inventory.readFromNBT(var2);
867            this.inventory.currentItem = par1NBTTagCompound.getInteger("SelectedItemSlot");
868            this.sleeping = par1NBTTagCompound.getBoolean("Sleeping");
869            this.sleepTimer = par1NBTTagCompound.getShort("SleepTimer");
870            this.experience = par1NBTTagCompound.getFloat("XpP");
871            this.experienceLevel = par1NBTTagCompound.getInteger("XpLevel");
872            this.experienceTotal = par1NBTTagCompound.getInteger("XpTotal");
873            this.setScore(par1NBTTagCompound.getInteger("Score"));
874    
875            if (this.sleeping)
876            {
877                this.playerLocation = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
878                this.wakeUpPlayer(true, true, false);
879            }
880    
881            if (par1NBTTagCompound.hasKey("SpawnX") && par1NBTTagCompound.hasKey("SpawnY") && par1NBTTagCompound.hasKey("SpawnZ"))
882            {
883                this.spawnChunk = new ChunkCoordinates(par1NBTTagCompound.getInteger("SpawnX"), par1NBTTagCompound.getInteger("SpawnY"), par1NBTTagCompound.getInteger("SpawnZ"));
884                this.spawnForced = par1NBTTagCompound.getBoolean("SpawnForced");
885            }
886    
887            this.foodStats.readNBT(par1NBTTagCompound);
888            this.capabilities.readCapabilitiesFromNBT(par1NBTTagCompound);
889    
890            if (par1NBTTagCompound.hasKey("EnderItems"))
891            {
892                NBTTagList var3 = par1NBTTagCompound.getTagList("EnderItems");
893                this.theInventoryEnderChest.loadInventoryFromNBT(var3);
894            }
895        }
896    
897        /**
898         * (abstract) Protected helper method to write subclass entity data to NBT.
899         */
900        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
901        {
902            super.writeEntityToNBT(par1NBTTagCompound);
903            par1NBTTagCompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList()));
904            par1NBTTagCompound.setInteger("SelectedItemSlot", this.inventory.currentItem);
905            par1NBTTagCompound.setBoolean("Sleeping", this.sleeping);
906            par1NBTTagCompound.setShort("SleepTimer", (short)this.sleepTimer);
907            par1NBTTagCompound.setFloat("XpP", this.experience);
908            par1NBTTagCompound.setInteger("XpLevel", this.experienceLevel);
909            par1NBTTagCompound.setInteger("XpTotal", this.experienceTotal);
910            par1NBTTagCompound.setInteger("Score", this.getScore());
911    
912            if (this.spawnChunk != null)
913            {
914                par1NBTTagCompound.setInteger("SpawnX", this.spawnChunk.posX);
915                par1NBTTagCompound.setInteger("SpawnY", this.spawnChunk.posY);
916                par1NBTTagCompound.setInteger("SpawnZ", this.spawnChunk.posZ);
917                par1NBTTagCompound.setBoolean("SpawnForced", this.spawnForced);
918            }
919    
920            this.foodStats.writeNBT(par1NBTTagCompound);
921            this.capabilities.writeCapabilitiesToNBT(par1NBTTagCompound);
922            par1NBTTagCompound.setTag("EnderItems", this.theInventoryEnderChest.saveInventoryToNBT());
923        }
924    
925        /**
926         * Displays the GUI for interacting with a chest inventory. Args: chestInventory
927         */
928        public void displayGUIChest(IInventory par1IInventory) {}
929    
930        public void displayGUIEnchantment(int par1, int par2, int par3) {}
931    
932        /**
933         * Displays the GUI for interacting with an anvil.
934         */
935        public void displayGUIAnvil(int par1, int par2, int par3) {}
936    
937        /**
938         * Displays the crafting GUI for a workbench.
939         */
940        public void displayGUIWorkbench(int par1, int par2, int par3) {}
941    
942        public float getEyeHeight()
943        {
944            return 0.12F;
945        }
946    
947        /**
948         * sets the players height back to normal after doing things like sleeping and dieing
949         */
950        protected void resetHeight()
951        {
952            this.yOffset = 1.62F;
953        }
954    
955        /**
956         * Called when the entity is attacked.
957         */
958        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
959        {
960            if (this.isEntityInvulnerable())
961            {
962                return false;
963            }
964            else if (this.capabilities.disableDamage && !par1DamageSource.canHarmInCreative())
965            {
966                return false;
967            }
968            else
969            {
970                this.entityAge = 0;
971    
972                if (this.getHealth() <= 0)
973                {
974                    return false;
975                }
976                else
977                {
978                    if (this.isPlayerSleeping() && !this.worldObj.isRemote)
979                    {
980                        this.wakeUpPlayer(true, true, false);
981                    }
982    
983                    if (par1DamageSource.isDifficultyScaled())
984                    {
985                        if (this.worldObj.difficultySetting == 0)
986                        {
987                            par2 = 0;
988                        }
989    
990                        if (this.worldObj.difficultySetting == 1)
991                        {
992                            par2 = par2 / 2 + 1;
993                        }
994    
995                        if (this.worldObj.difficultySetting == 3)
996                        {
997                            par2 = par2 * 3 / 2;
998                        }
999                    }
1000    
1001                    if (par2 == 0)
1002                    {
1003                        return false;
1004                    }
1005                    else
1006                    {
1007                        Entity var3 = par1DamageSource.getEntity();
1008    
1009                        if (var3 instanceof EntityArrow && ((EntityArrow)var3).shootingEntity != null)
1010                        {
1011                            var3 = ((EntityArrow)var3).shootingEntity;
1012                        }
1013    
1014                        if (var3 instanceof EntityLiving)
1015                        {
1016                            this.alertWolves((EntityLiving)var3, false);
1017                        }
1018    
1019                        this.addStat(StatList.damageTakenStat, par2);
1020                        return super.attackEntityFrom(par1DamageSource, par2);
1021                    }
1022                }
1023            }
1024        }
1025    
1026        /**
1027         * Reduces damage, depending on potions
1028         */
1029        protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2)
1030        {
1031            int var3 = super.applyPotionDamageCalculations(par1DamageSource, par2);
1032    
1033            if (var3 <= 0)
1034            {
1035                return 0;
1036            }
1037            else
1038            {
1039                int var4 = EnchantmentHelper.getEnchantmentModifierDamage(this.inventory.armorInventory, par1DamageSource);
1040    
1041                if (var4 > 20)
1042                {
1043                    var4 = 20;
1044                }
1045    
1046                if (var4 > 0 && var4 <= 20)
1047                {
1048                    int var5 = 25 - var4;
1049                    int var6 = var3 * var5 + this.carryoverDamage;
1050                    var3 = var6 / 25;
1051                    this.carryoverDamage = var6 % 25;
1052                }
1053    
1054                return var3;
1055            }
1056        }
1057    
1058        /**
1059         * returns if pvp is enabled or not
1060         */
1061        protected boolean isPVPEnabled()
1062        {
1063            return false;
1064        }
1065    
1066        /**
1067         * Called when the player attack or gets attacked, it's alert all wolves in the area that are owned by the player to
1068         * join the attack or defend the player.
1069         */
1070        protected void alertWolves(EntityLiving par1EntityLiving, boolean par2)
1071        {
1072            if (!(par1EntityLiving instanceof EntityCreeper) && !(par1EntityLiving instanceof EntityGhast))
1073            {
1074                if (par1EntityLiving instanceof EntityWolf)
1075                {
1076                    EntityWolf var3 = (EntityWolf)par1EntityLiving;
1077    
1078                    if (var3.isTamed() && this.username.equals(var3.getOwnerName()))
1079                    {
1080                        return;
1081                    }
1082                }
1083    
1084                if (!(par1EntityLiving instanceof EntityPlayer) || this.isPVPEnabled())
1085                {
1086                    List var6 = this.worldObj.getEntitiesWithinAABB(EntityWolf.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(this.posX, this.posY, this.posZ, this.posX + 1.0D, this.posY + 1.0D, this.posZ + 1.0D).expand(16.0D, 4.0D, 16.0D));
1087                    Iterator var4 = var6.iterator();
1088    
1089                    while (var4.hasNext())
1090                    {
1091                        EntityWolf var5 = (EntityWolf)var4.next();
1092    
1093                        if (var5.isTamed() && var5.getEntityToAttack() == null && this.username.equals(var5.getOwnerName()) && (!par2 || !var5.isSitting()))
1094                        {
1095                            var5.setSitting(false);
1096                            var5.setTarget(par1EntityLiving);
1097                        }
1098                    }
1099                }
1100            }
1101        }
1102    
1103        protected void damageArmor(int par1)
1104        {
1105            this.inventory.damageArmor(par1);
1106        }
1107    
1108        /**
1109         * Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue
1110         */
1111        public int getTotalArmorValue()
1112        {
1113            return this.inventory.getTotalArmorValue();
1114        }
1115    
1116        public float func_82243_bO()
1117        {
1118            int var1 = 0;
1119            ItemStack[] var2 = this.inventory.armorInventory;
1120            int var3 = var2.length;
1121    
1122            for (int var4 = 0; var4 < var3; ++var4)
1123            {
1124                ItemStack var5 = var2[var4];
1125    
1126                if (var5 != null)
1127                {
1128                    ++var1;
1129                }
1130            }
1131    
1132            return (float)var1 / (float)this.inventory.armorInventory.length;
1133        }
1134    
1135        /**
1136         * Deals damage to the entity. If its a EntityPlayer then will take damage from the armor first and then health
1137         * second with the reduced value. Args: damageAmount
1138         */
1139        protected void damageEntity(DamageSource par1DamageSource, int par2)
1140        {
1141            if (!this.isEntityInvulnerable())
1142            {
1143                par2 = ForgeHooks.onLivingHurt(this, par1DamageSource, par2);
1144                if (par2 <= 0)
1145                {
1146                    return;
1147                }
1148    
1149                if (!par1DamageSource.isUnblockable() && this.isBlocking())
1150                {
1151                    par2 = 1 + par2 >> 1;
1152                }
1153    
1154                par2 = ArmorProperties.ApplyArmor(this, inventory.armorInventory, par1DamageSource, par2);
1155                if (par2 <= 0)
1156                {
1157                    return;
1158                }
1159                par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
1160                this.addExhaustion(par1DamageSource.getHungerDamage());
1161                this.health -= par2;
1162            }
1163        }
1164    
1165        /**
1166         * Displays the furnace GUI for the passed in furnace entity. Args: tileEntityFurnace
1167         */
1168        public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) {}
1169    
1170        /**
1171         * Displays the dipsenser GUI for the passed in dispenser entity. Args: TileEntityDispenser
1172         */
1173        public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) {}
1174    
1175        /**
1176         * Displays the GUI for editing a sign. Args: tileEntitySign
1177         */
1178        public void displayGUIEditSign(TileEntity par1TileEntity) {}
1179    
1180        /**
1181         * Displays the GUI for interacting with a brewing stand.
1182         */
1183        public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) {}
1184    
1185        /**
1186         * Displays the GUI for interacting with a beacon.
1187         */
1188        public void displayGUIBeacon(TileEntityBeacon par1TileEntityBeacon) {}
1189    
1190        public void displayGUIMerchant(IMerchant par1IMerchant) {}
1191    
1192        /**
1193         * Displays the GUI for interacting with a book.
1194         */
1195        public void displayGUIBook(ItemStack par1ItemStack) {}
1196    
1197        public boolean interactWith(Entity par1Entity)
1198        {
1199            if (MinecraftForge.EVENT_BUS.post(new EntityInteractEvent(this, par1Entity)))
1200            {
1201                return false;
1202            }
1203            if (par1Entity.interact(this))
1204            {
1205                return true;
1206            }
1207            else
1208            {
1209                ItemStack var2 = this.getCurrentEquippedItem();
1210    
1211                if (var2 != null && par1Entity instanceof EntityLiving)
1212                {
1213                    if (this.capabilities.isCreativeMode)
1214                    {
1215                        var2 = var2.copy();
1216                    }
1217    
1218                    if (var2.interactWith((EntityLiving)par1Entity))
1219                    {
1220                        if (var2.stackSize <= 0 && !this.capabilities.isCreativeMode)
1221                        {
1222                            this.destroyCurrentEquippedItem();
1223                        }
1224    
1225                        return true;
1226                    }
1227                }
1228    
1229                return false;
1230            }
1231        }
1232    
1233        /**
1234         * Returns the currently being used item by the player.
1235         */
1236        public ItemStack getCurrentEquippedItem()
1237        {
1238            return this.inventory.getCurrentItem();
1239        }
1240    
1241        /**
1242         * Destroys the currently equipped item from the player's inventory.
1243         */
1244        public void destroyCurrentEquippedItem()
1245        {
1246            ItemStack orig = getCurrentEquippedItem();
1247            this.inventory.setInventorySlotContents(this.inventory.currentItem, (ItemStack)null);
1248            MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(this, orig));
1249        }
1250    
1251        /**
1252         * Returns the Y Offset of this entity.
1253         */
1254        public double getYOffset()
1255        {
1256            return (double)(this.yOffset - 0.5F);
1257        }
1258    
1259        /**
1260         * Attacks for the player the targeted entity with the currently equipped item.  The equipped item has hitEntity
1261         * called on it. Args: targetEntity
1262         */
1263        public void attackTargetEntityWithCurrentItem(Entity par1Entity)
1264        {
1265            if (MinecraftForge.EVENT_BUS.post(new AttackEntityEvent(this, par1Entity)))
1266            {
1267                return;
1268            }
1269            ItemStack stack = getCurrentEquippedItem();
1270            if (stack != null && stack.getItem().onLeftClickEntity(stack, this, par1Entity))
1271            {
1272                return;
1273            }
1274            if (par1Entity.canAttackWithItem())
1275            {
1276                if (!par1Entity.func_85031_j(this))
1277                {
1278                    int var2 = this.inventory.getDamageVsEntity(par1Entity);
1279    
1280                    if (this.isPotionActive(Potion.damageBoost))
1281                    {
1282                        var2 += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier();
1283                    }
1284    
1285                    if (this.isPotionActive(Potion.weakness))
1286                    {
1287                        var2 -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier();
1288                    }
1289    
1290                    int var3 = 0;
1291                    int var4 = 0;
1292    
1293                    if (par1Entity instanceof EntityLiving)
1294                    {
1295                        var4 = EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving)par1Entity);
1296                        var3 += EnchantmentHelper.getKnockbackModifier(this, (EntityLiving)par1Entity);
1297                    }
1298    
1299                    if (this.isSprinting())
1300                    {
1301                        ++var3;
1302                    }
1303    
1304                    if (var2 > 0 || var4 > 0)
1305                    {
1306                        boolean var5 = this.fallDistance > 0.0F && !this.onGround && !this.isOnLadder() && !this.isInWater() && !this.isPotionActive(Potion.blindness) && this.ridingEntity == null && par1Entity instanceof EntityLiving;
1307    
1308                        if (var5)
1309                        {
1310                            var2 += this.rand.nextInt(var2 / 2 + 2);
1311                        }
1312    
1313                        var2 += var4;
1314                        boolean var6 = false;
1315                        int var7 = EnchantmentHelper.getFireAspectModifier(this);
1316    
1317                        if (par1Entity instanceof EntityLiving && var7 > 0 && !par1Entity.isBurning())
1318                        {
1319                            var6 = true;
1320                            par1Entity.setFire(1);
1321                        }
1322    
1323                        boolean var8 = par1Entity.attackEntityFrom(DamageSource.causePlayerDamage(this), var2);
1324    
1325                        if (var8)
1326                        {
1327                            if (var3 > 0)
1328                            {
1329                                par1Entity.addVelocity((double)(-MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F) * (float)var3 * 0.5F), 0.1D, (double)(MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F) * (float)var3 * 0.5F));
1330                                this.motionX *= 0.6D;
1331                                this.motionZ *= 0.6D;
1332                                this.setSprinting(false);
1333                            }
1334    
1335                            if (var5)
1336                            {
1337                                this.onCriticalHit(par1Entity);
1338                            }
1339    
1340                            if (var4 > 0)
1341                            {
1342                                this.onEnchantmentCritical(par1Entity);
1343                            }
1344    
1345                            if (var2 >= 18)
1346                            {
1347                                this.triggerAchievement(AchievementList.overkill);
1348                            }
1349    
1350                            this.setLastAttackingEntity(par1Entity);
1351    
1352                            if (par1Entity instanceof EntityLiving)
1353                            {
1354                                EnchantmentThorns.func_92044_a(this, (EntityLiving)par1Entity, this.rand);
1355                            }
1356                        }
1357    
1358                        ItemStack var9 = this.getCurrentEquippedItem();
1359    
1360                        if (var9 != null && par1Entity instanceof EntityLiving)
1361                        {
1362                            var9.hitEntity((EntityLiving)par1Entity, this);
1363    
1364                            if (var9.stackSize <= 0)
1365                            {
1366                                this.destroyCurrentEquippedItem();
1367                            }
1368                        }
1369    
1370                        if (par1Entity instanceof EntityLiving)
1371                        {
1372                            if (par1Entity.isEntityAlive())
1373                            {
1374                                this.alertWolves((EntityLiving)par1Entity, true);
1375                            }
1376    
1377                            this.addStat(StatList.damageDealtStat, var2);
1378    
1379                            if (var7 > 0 && var8)
1380                            {
1381                                par1Entity.setFire(var7 * 4);
1382                            }
1383                            else if (var6)
1384                            {
1385                                par1Entity.extinguish();
1386                            }
1387                        }
1388    
1389                        this.addExhaustion(0.3F);
1390                    }
1391                }
1392            }
1393        }
1394    
1395        /**
1396         * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically
1397         */
1398        public void onCriticalHit(Entity par1Entity) {}
1399    
1400        public void onEnchantmentCritical(Entity par1Entity) {}
1401    
1402        @SideOnly(Side.CLIENT)
1403        public void respawnPlayer() {}
1404    
1405        /**
1406         * Will get destroyed next tick.
1407         */
1408        public void setDead()
1409        {
1410            super.setDead();
1411            this.inventoryContainer.onCraftGuiClosed(this);
1412    
1413            if (this.openContainer != null)
1414            {
1415                this.openContainer.onCraftGuiClosed(this);
1416            }
1417        }
1418    
1419        /**
1420         * Checks if this entity is inside of an opaque block
1421         */
1422        public boolean isEntityInsideOpaqueBlock()
1423        {
1424            return !this.sleeping && super.isEntityInsideOpaqueBlock();
1425        }
1426    
1427        public boolean func_71066_bF()
1428        {
1429            return false;
1430        }
1431    
1432        /**
1433         * Attempts to have the player sleep in a bed at the specified location.
1434         */
1435        public EnumStatus sleepInBedAt(int par1, int par2, int par3)
1436        {
1437            PlayerSleepInBedEvent event = new PlayerSleepInBedEvent(this, par1, par2, par3);
1438            MinecraftForge.EVENT_BUS.post(event);
1439            if (event.result != null)
1440            {
1441                return event.result;
1442            }
1443            if (!this.worldObj.isRemote)
1444            {
1445                if (this.isPlayerSleeping() || !this.isEntityAlive())
1446                {
1447                    return EnumStatus.OTHER_PROBLEM;
1448                }
1449    
1450                if (!this.worldObj.provider.isSurfaceWorld())
1451                {
1452                    return EnumStatus.NOT_POSSIBLE_HERE;
1453                }
1454    
1455                if (this.worldObj.isDaytime())
1456                {
1457                    return EnumStatus.NOT_POSSIBLE_NOW;
1458                }
1459    
1460                if (Math.abs(this.posX - (double)par1) > 3.0D || Math.abs(this.posY - (double)par2) > 2.0D || Math.abs(this.posZ - (double)par3) > 3.0D)
1461                {
1462                    return EnumStatus.TOO_FAR_AWAY;
1463                }
1464    
1465                double var4 = 8.0D;
1466                double var6 = 5.0D;
1467                List var8 = this.worldObj.getEntitiesWithinAABB(EntityMob.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par1 - var4, (double)par2 - var6, (double)par3 - var4, (double)par1 + var4, (double)par2 + var6, (double)par3 + var4));
1468    
1469                if (!var8.isEmpty())
1470                {
1471                    return EnumStatus.NOT_SAFE;
1472                }
1473            }
1474    
1475            this.setSize(0.2F, 0.2F);
1476            this.yOffset = 0.2F;
1477    
1478            if (this.worldObj.blockExists(par1, par2, par3))
1479            {
1480                int var9 = this.worldObj.getBlockMetadata(par1, par2, par3);
1481                int var5 = BlockBed.getDirection(var9);
1482                Block block = Block.blocksList[worldObj.getBlockId(par1, par2, par3)];
1483                if (block != null)
1484                {
1485                    var5 = block.getBedDirection(worldObj, par1, par2, par3);
1486                }
1487                float var10 = 0.5F;
1488                float var7 = 0.5F;
1489    
1490                switch (var5)
1491                {
1492                    case 0:
1493                        var7 = 0.9F;
1494                        break;
1495                    case 1:
1496                        var10 = 0.1F;
1497                        break;
1498                    case 2:
1499                        var7 = 0.1F;
1500                        break;
1501                    case 3:
1502                        var10 = 0.9F;
1503                }
1504    
1505                this.func_71013_b(var5);
1506                this.setPosition((double)((float)par1 + var10), (double)((float)par2 + 0.9375F), (double)((float)par3 + var7));
1507            }
1508            else
1509            {
1510                this.setPosition((double)((float)par1 + 0.5F), (double)((float)par2 + 0.9375F), (double)((float)par3 + 0.5F));
1511            }
1512    
1513            this.sleeping = true;
1514            this.sleepTimer = 0;
1515            this.playerLocation = new ChunkCoordinates(par1, par2, par3);
1516            this.motionX = this.motionZ = this.motionY = 0.0D;
1517    
1518            if (!this.worldObj.isRemote)
1519            {
1520                this.worldObj.updateAllPlayersSleepingFlag();
1521            }
1522    
1523            return EnumStatus.OK;
1524        }
1525    
1526        private void func_71013_b(int par1)
1527        {
1528            this.field_71079_bU = 0.0F;
1529            this.field_71089_bV = 0.0F;
1530    
1531            switch (par1)
1532            {
1533                case 0:
1534                    this.field_71089_bV = -1.8F;
1535                    break;
1536                case 1:
1537                    this.field_71079_bU = 1.8F;
1538                    break;
1539                case 2:
1540                    this.field_71089_bV = 1.8F;
1541                    break;
1542                case 3:
1543                    this.field_71079_bU = -1.8F;
1544            }
1545        }
1546    
1547        /**
1548         * Wake up the player if they're sleeping.
1549         */
1550        public void wakeUpPlayer(boolean par1, boolean par2, boolean par3)
1551        {
1552            this.setSize(0.6F, 1.8F);
1553            this.resetHeight();
1554            ChunkCoordinates var4 = this.playerLocation;
1555            ChunkCoordinates var5 = this.playerLocation;
1556    
1557            Block block = (var4 == null ? null : Block.blocksList[worldObj.getBlockId(var4.posX, var4.posY, var4.posZ)]);
1558    
1559            if (var4 != null && block != null && block.isBed(worldObj, var4.posX, var4.posY, var4.posZ, this))
1560            {
1561                block.setBedOccupied(this.worldObj, var4.posX, var4.posY, var4.posZ, this, false);
1562                var5 = block.getBedSpawnPosition(worldObj, var4.posX, var4.posY, var4.posZ, this);
1563    
1564                if (var5 == null)
1565                {
1566                    var5 = new ChunkCoordinates(var4.posX, var4.posY + 1, var4.posZ);
1567                }
1568    
1569                this.setPosition((double)((float)var5.posX + 0.5F), (double)((float)var5.posY + this.yOffset + 0.1F), (double)((float)var5.posZ + 0.5F));
1570            }
1571    
1572            this.sleeping = false;
1573    
1574            if (!this.worldObj.isRemote && par2)
1575            {
1576                this.worldObj.updateAllPlayersSleepingFlag();
1577            }
1578    
1579            if (par1)
1580            {
1581                this.sleepTimer = 0;
1582            }
1583            else
1584            {
1585                this.sleepTimer = 100;
1586            }
1587    
1588            if (par3)
1589            {
1590                this.setSpawnChunk(this.playerLocation, false);
1591            }
1592        }
1593    
1594        /**
1595         * Checks if the player is currently in a bed
1596         */
1597        private boolean isInBed()
1598        {
1599            ChunkCoordinates c = playerLocation;
1600            int blockID = worldObj.getBlockId(c.posX, c.posY, c.posZ);
1601            return Block.blocksList[blockID] != null && Block.blocksList[blockID].isBed(worldObj, c.posX, c.posY, c.posZ, this);
1602        }
1603    
1604        /**
1605         * Ensure that a block enabling respawning exists at the specified coordinates and find an empty space nearby to
1606         * spawn.
1607         */
1608        public static ChunkCoordinates verifyRespawnCoordinates(World par0World, ChunkCoordinates par1ChunkCoordinates, boolean par2)
1609        {
1610            IChunkProvider var3 = par0World.getChunkProvider();
1611            var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
1612            var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
1613            var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
1614            var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
1615    
1616            ChunkCoordinates c = par1ChunkCoordinates;
1617            Block block = Block.blocksList[par0World.getBlockId(c.posX, c.posY, c.posZ)];
1618    
1619            if (block != null && block.isBed(par0World, c.posX, c.posY, c.posZ, null))
1620            {
1621                ChunkCoordinates var8 = block.getBedSpawnPosition(par0World, c.posX, c.posY, c.posZ, null);
1622                return var8;
1623            }
1624            else
1625            {
1626                Material var4 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY, par1ChunkCoordinates.posZ);
1627                Material var5 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY + 1, par1ChunkCoordinates.posZ);
1628                boolean var6 = !var4.isSolid() && !var4.isLiquid();
1629                boolean var7 = !var5.isSolid() && !var5.isLiquid();
1630                return par2 && var6 && var7 ? par1ChunkCoordinates : null;
1631            }
1632        }
1633    
1634        @SideOnly(Side.CLIENT)
1635    
1636        /**
1637         * Returns the orientation of the bed in degrees.
1638         */
1639        public float getBedOrientationInDegrees()
1640        {
1641            if (this.playerLocation != null)
1642            {
1643                int x = playerLocation.posX;
1644                int y = playerLocation.posY;
1645                int z = playerLocation.posZ;
1646                Block block = Block.blocksList[worldObj.getBlockId(x, y, z)];
1647                int var2 = (block == null ? 0 : block.getBedDirection(worldObj, x, y, z));
1648    
1649                switch (var2)
1650                {
1651                    case 0:
1652                        return 90.0F;
1653                    case 1:
1654                        return 0.0F;
1655                    case 2:
1656                        return 270.0F;
1657                    case 3:
1658                        return 180.0F;
1659                }
1660            }
1661    
1662            return 0.0F;
1663        }
1664    
1665        /**
1666         * Returns whether player is sleeping or not
1667         */
1668        public boolean isPlayerSleeping()
1669        {
1670            return this.sleeping;
1671        }
1672    
1673        /**
1674         * Returns whether or not the player is asleep and the screen has fully faded.
1675         */
1676        public boolean isPlayerFullyAsleep()
1677        {
1678            return this.sleeping && this.sleepTimer >= 100;
1679        }
1680    
1681        @SideOnly(Side.CLIENT)
1682        public int getSleepTimer()
1683        {
1684            return this.sleepTimer;
1685        }
1686    
1687        @SideOnly(Side.CLIENT)
1688        protected boolean getHideCape(int par1)
1689        {
1690            return (this.dataWatcher.getWatchableObjectByte(16) & 1 << par1) != 0;
1691        }
1692    
1693        protected void setHideCape(int par1, boolean par2)
1694        {
1695            byte var3 = this.dataWatcher.getWatchableObjectByte(16);
1696    
1697            if (par2)
1698            {
1699                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 | 1 << par1)));
1700            }
1701            else
1702            {
1703                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 & ~(1 << par1))));
1704            }
1705        }
1706    
1707        /**
1708         * Add a chat message to the player
1709         */
1710        public void addChatMessage(String par1Str) {}
1711    
1712        /**
1713         * Returns the location of the bed the player will respawn at, or null if the player has not slept in a bed.
1714         */
1715        public ChunkCoordinates getBedLocation()
1716        {
1717            return this.spawnChunk;
1718        }
1719    
1720        public boolean isSpawnForced()
1721        {
1722            return this.spawnForced;
1723        }
1724    
1725        /**
1726         * Defines a spawn coordinate to player spawn. Used by bed after the player sleep on it.
1727         */
1728        public void setSpawnChunk(ChunkCoordinates par1ChunkCoordinates, boolean par2)
1729        {
1730            if (par1ChunkCoordinates != null)
1731            {
1732                this.spawnChunk = new ChunkCoordinates(par1ChunkCoordinates);
1733                this.spawnForced = par2;
1734            }
1735            else
1736            {
1737                this.spawnChunk = null;
1738                this.spawnForced = false;
1739            }
1740        }
1741    
1742        /**
1743         * Will trigger the specified trigger.
1744         */
1745        public void triggerAchievement(StatBase par1StatBase)
1746        {
1747            this.addStat(par1StatBase, 1);
1748        }
1749    
1750        /**
1751         * Adds a value to a statistic field.
1752         */
1753        public void addStat(StatBase par1StatBase, int par2) {}
1754    
1755        /**
1756         * Causes this entity to do an upwards motion (jumping).
1757         */
1758        protected void jump()
1759        {
1760            super.jump();
1761            this.addStat(StatList.jumpStat, 1);
1762    
1763            if (this.isSprinting())
1764            {
1765                this.addExhaustion(0.8F);
1766            }
1767            else
1768            {
1769                this.addExhaustion(0.2F);
1770            }
1771        }
1772    
1773        /**
1774         * Moves the entity based on the specified heading.  Args: strafe, forward
1775         */
1776        public void moveEntityWithHeading(float par1, float par2)
1777        {
1778            double var3 = this.posX;
1779            double var5 = this.posY;
1780            double var7 = this.posZ;
1781    
1782            if (this.capabilities.isFlying && this.ridingEntity == null)
1783            {
1784                double var9 = this.motionY;
1785                float var11 = this.jumpMovementFactor;
1786                this.jumpMovementFactor = this.capabilities.getFlySpeed();
1787                super.moveEntityWithHeading(par1, par2);
1788                this.motionY = var9 * 0.6D;
1789                this.jumpMovementFactor = var11;
1790            }
1791            else
1792            {
1793                super.moveEntityWithHeading(par1, par2);
1794            }
1795    
1796            this.addMovementStat(this.posX - var3, this.posY - var5, this.posZ - var7);
1797        }
1798    
1799        /**
1800         * Adds a value to a movement statistic field - like run, walk, swin or climb.
1801         */
1802        public void addMovementStat(double par1, double par3, double par5)
1803        {
1804            if (this.ridingEntity == null)
1805            {
1806                int var7;
1807    
1808                if (this.isInsideOfMaterial(Material.water))
1809                {
1810                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
1811    
1812                    if (var7 > 0)
1813                    {
1814                        this.addStat(StatList.distanceDoveStat, var7);
1815                        this.addExhaustion(0.015F * (float)var7 * 0.01F);
1816                    }
1817                }
1818                else if (this.isInWater())
1819                {
1820                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
1821    
1822                    if (var7 > 0)
1823                    {
1824                        this.addStat(StatList.distanceSwumStat, var7);
1825                        this.addExhaustion(0.015F * (float)var7 * 0.01F);
1826                    }
1827                }
1828                else if (this.isOnLadder())
1829                {
1830                    if (par3 > 0.0D)
1831                    {
1832                        this.addStat(StatList.distanceClimbedStat, (int)Math.round(par3 * 100.0D));
1833                    }
1834                }
1835                else if (this.onGround)
1836                {
1837                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
1838    
1839                    if (var7 > 0)
1840                    {
1841                        this.addStat(StatList.distanceWalkedStat, var7);
1842    
1843                        if (this.isSprinting())
1844                        {
1845                            this.addExhaustion(0.099999994F * (float)var7 * 0.01F);
1846                        }
1847                        else
1848                        {
1849                            this.addExhaustion(0.01F * (float)var7 * 0.01F);
1850                        }
1851                    }
1852                }
1853                else
1854                {
1855                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
1856    
1857                    if (var7 > 25)
1858                    {
1859                        this.addStat(StatList.distanceFlownStat, var7);
1860                    }
1861                }
1862            }
1863        }
1864    
1865        /**
1866         * Adds a value to a mounted movement statistic field - by minecart, boat, or pig.
1867         */
1868        private void addMountedMovementStat(double par1, double par3, double par5)
1869        {
1870            if (this.ridingEntity != null)
1871            {
1872                int var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
1873    
1874                if (var7 > 0)
1875                {
1876                    if (this.ridingEntity instanceof EntityMinecart)
1877                    {
1878                        this.addStat(StatList.distanceByMinecartStat, var7);
1879    
1880                        if (this.startMinecartRidingCoordinate == null)
1881                        {
1882                            this.startMinecartRidingCoordinate = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
1883                        }
1884                        else if ((double)this.startMinecartRidingCoordinate.getDistanceSquared(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) >= 1000000.0D)
1885                        {
1886                            this.addStat(AchievementList.onARail, 1);
1887                        }
1888                    }
1889                    else if (this.ridingEntity instanceof EntityBoat)
1890                    {
1891                        this.addStat(StatList.distanceByBoatStat, var7);
1892                    }
1893                    else if (this.ridingEntity instanceof EntityPig)
1894                    {
1895                        this.addStat(StatList.distanceByPigStat, var7);
1896                    }
1897                }
1898            }
1899        }
1900    
1901        /**
1902         * Called when the mob is falling. Calculates and applies fall damage.
1903         */
1904        protected void fall(float par1)
1905        {
1906            if (!this.capabilities.allowFlying)
1907            {
1908                if (par1 >= 2.0F)
1909                {
1910                    this.addStat(StatList.distanceFallenStat, (int)Math.round((double)par1 * 100.0D));
1911                }
1912    
1913                super.fall(par1);
1914            }
1915        }
1916    
1917        /**
1918         * This method gets called when the entity kills another one.
1919         */
1920        public void onKillEntity(EntityLiving par1EntityLiving)
1921        {
1922            if (par1EntityLiving instanceof IMob)
1923            {
1924                this.triggerAchievement(AchievementList.killEnemy);
1925            }
1926        }
1927    
1928        /**
1929         * Sets the Entity inside a web block.
1930         */
1931        public void setInWeb()
1932        {
1933            if (!this.capabilities.isFlying)
1934            {
1935                super.setInWeb();
1936            }
1937        }
1938    
1939        @SideOnly(Side.CLIENT)
1940    
1941        /**
1942         * Gets the Icon Index of the item currently held
1943         */
1944        public int getItemIcon(ItemStack par1ItemStack, int par2)
1945        {
1946            int var3 = super.getItemIcon(par1ItemStack, par2);
1947    
1948            if (par1ItemStack.itemID == Item.fishingRod.itemID && this.fishEntity != null)
1949            {
1950                var3 = par1ItemStack.getIconIndex() + 16;
1951            }
1952            else
1953            {
1954                if (par1ItemStack.getItem().requiresMultipleRenderPasses())
1955                {
1956                    return par1ItemStack.getItem().getIconIndex(par1ItemStack, par2);
1957                }
1958    
1959                if (this.itemInUse != null && par1ItemStack.itemID == Item.bow.itemID)
1960                {
1961                    int var4 = par1ItemStack.getMaxItemUseDuration() - this.itemInUseCount;
1962    
1963                    if (var4 >= 18)
1964                    {
1965                        return 133;
1966                    }
1967    
1968                    if (var4 > 13)
1969                    {
1970                        return 117;
1971                    }
1972    
1973                    if (var4 > 0)
1974                    {
1975                        return 101;
1976                    }
1977                }
1978                var3 = par1ItemStack.getItem().getIconIndex(par1ItemStack, par2, this, itemInUse, itemInUseCount);
1979            }
1980    
1981            return var3;
1982        }
1983    
1984        public ItemStack getCurrentArmor(int par1)
1985        {
1986            return this.inventory.armorItemInSlot(par1);
1987        }
1988    
1989        protected void func_82164_bB() {}
1990    
1991        protected void func_82162_bC() {}
1992    
1993        /**
1994         * This method increases the player's current amount of experience.
1995         */
1996        public void addExperience(int par1)
1997        {
1998            this.addScore(par1);
1999            int var2 = Integer.MAX_VALUE - this.experienceTotal;
2000    
2001            if (par1 > var2)
2002            {
2003                par1 = var2;
2004            }
2005    
2006            this.experience += (float)par1 / (float)this.xpBarCap();
2007    
2008            for (this.experienceTotal += par1; this.experience >= 1.0F; this.experience /= (float)this.xpBarCap())
2009            {
2010                this.experience = (this.experience - 1.0F) * (float)this.xpBarCap();
2011                this.addExperienceLevel(1);
2012            }
2013        }
2014    
2015        /**
2016         * Add experience levels to this player.
2017         */
2018        public void addExperienceLevel(int par1)
2019        {
2020            this.experienceLevel += par1;
2021    
2022            if (this.experienceLevel < 0)
2023            {
2024                this.experienceLevel = 0;
2025                this.experience = 0.0F;
2026                this.experienceTotal = 0;
2027            }
2028    
2029            if (par1 > 0 && this.experienceLevel % 5 == 0 && (float)this.field_82249_h < (float)this.ticksExisted - 100.0F)
2030            {
2031                float var2 = this.experienceLevel > 30 ? 1.0F : (float)this.experienceLevel / 30.0F;
2032                this.worldObj.playSoundAtEntity(this, "random.levelup", var2 * 0.75F, 1.0F);
2033                this.field_82249_h = this.ticksExisted;
2034            }
2035        }
2036    
2037        /**
2038         * This method returns the cap amount of experience that the experience bar can hold. With each level, the
2039         * experience cap on the player's experience bar is raised by 10.
2040         */
2041        public int xpBarCap()
2042        {
2043            return this.experienceLevel >= 30 ? 62 + (this.experienceLevel - 30) * 7 : (this.experienceLevel >= 15 ? 17 + (this.experienceLevel - 15) * 3 : 17);
2044        }
2045    
2046        /**
2047         * increases exhaustion level by supplied amount
2048         */
2049        public void addExhaustion(float par1)
2050        {
2051            if (!this.capabilities.disableDamage)
2052            {
2053                if (!this.worldObj.isRemote)
2054                {
2055                    this.foodStats.addExhaustion(par1);
2056                }
2057            }
2058        }
2059    
2060        /**
2061         * Returns the player's FoodStats object.
2062         */
2063        public FoodStats getFoodStats()
2064        {
2065            return this.foodStats;
2066        }
2067    
2068        public boolean canEat(boolean par1)
2069        {
2070            return (par1 || this.foodStats.needFood()) && !this.capabilities.disableDamage;
2071        }
2072    
2073        /**
2074         * Checks if the player's health is not full and not zero.
2075         */
2076        public boolean shouldHeal()
2077        {
2078            return this.getHealth() > 0 && this.getHealth() < this.getMaxHealth();
2079        }
2080    
2081        /**
2082         * sets the itemInUse when the use item button is clicked. Args: itemstack, int maxItemUseDuration
2083         */
2084        public void setItemInUse(ItemStack par1ItemStack, int par2)
2085        {
2086            if (par1ItemStack != this.itemInUse)
2087            {
2088                this.itemInUse = par1ItemStack;
2089                this.itemInUseCount = par2;
2090    
2091                if (!this.worldObj.isRemote)
2092                {
2093                    this.setEating(true);
2094                }
2095            }
2096        }
2097    
2098        /**
2099         * Returns true if the item the player is holding can harvest the block at the given coords. Args: x, y, z.
2100         */
2101        public boolean canCurrentToolHarvestBlock(int par1, int par2, int par3)
2102        {
2103            if (this.capabilities.allowEdit)
2104            {
2105                return true;
2106            }
2107            else
2108            {
2109                int var4 = this.worldObj.getBlockId(par1, par2, par3);
2110    
2111                if (var4 > 0)
2112                {
2113                    Block var5 = Block.blocksList[var4];
2114    
2115                    if (var5.blockMaterial.func_85157_q())
2116                    {
2117                        return true;
2118                    }
2119    
2120                    if (this.getCurrentEquippedItem() != null)
2121                    {
2122                        ItemStack var6 = this.getCurrentEquippedItem();
2123    
2124                        if (var6.canHarvestBlock(var5) || var6.getStrVsBlock(var5) > 1.0F)
2125                        {
2126                            return true;
2127                        }
2128                    }
2129                }
2130    
2131                return false;
2132            }
2133        }
2134    
2135        public boolean canPlayerEdit(int par1, int par2, int par3, int par4, ItemStack par5ItemStack)
2136        {
2137            return this.capabilities.allowEdit ? true : (par5ItemStack != null ? par5ItemStack.func_82835_x() : false);
2138        }
2139    
2140        /**
2141         * Get the experience points the entity currently has.
2142         */
2143        protected int getExperiencePoints(EntityPlayer par1EntityPlayer)
2144        {
2145            if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
2146            {
2147                return 0;
2148            }
2149            else
2150            {
2151                int var2 = this.experienceLevel * 7;
2152                return var2 > 100 ? 100 : var2;
2153            }
2154        }
2155    
2156        /**
2157         * Only use is to identify if class is an instance of player for experience dropping
2158         */
2159        protected boolean isPlayer()
2160        {
2161            return true;
2162        }
2163    
2164        /**
2165         * Gets the username of the entity.
2166         */
2167        public String getEntityName()
2168        {
2169            return this.username;
2170        }
2171    
2172        /**
2173         * Copies the values from the given player into this player if boolean par2 is true. Always clones Ender Chest
2174         * Inventory.
2175         */
2176        public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2)
2177        {
2178            if (par2)
2179            {
2180                this.inventory.copyInventory(par1EntityPlayer.inventory);
2181                this.health = par1EntityPlayer.health;
2182                this.foodStats = par1EntityPlayer.foodStats;
2183                this.experienceLevel = par1EntityPlayer.experienceLevel;
2184                this.experienceTotal = par1EntityPlayer.experienceTotal;
2185                this.experience = par1EntityPlayer.experience;
2186                this.setScore(par1EntityPlayer.getScore());
2187                this.field_82152_aq = par1EntityPlayer.field_82152_aq;
2188            }
2189            else if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
2190            {
2191                this.inventory.copyInventory(par1EntityPlayer.inventory);
2192                this.experienceLevel = par1EntityPlayer.experienceLevel;
2193                this.experienceTotal = par1EntityPlayer.experienceTotal;
2194                this.experience = par1EntityPlayer.experience;
2195                this.setScore(par1EntityPlayer.getScore());
2196            }
2197    
2198            this.theInventoryEnderChest = par1EntityPlayer.theInventoryEnderChest;
2199    
2200            //Copy over a section of the Entity Data from the old player.
2201            //Allows mods to specify data that persists after players respawn.
2202            NBTTagCompound old = par1EntityPlayer.getEntityData();
2203            if (old.hasKey(PERSISTED_NBT_TAG))
2204            {
2205                getEntityData().setCompoundTag(PERSISTED_NBT_TAG, old.getCompoundTag(PERSISTED_NBT_TAG));
2206            }
2207        }
2208    
2209        /**
2210         * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
2211         * prevent them from trampling crops
2212         */
2213        protected boolean canTriggerWalking()
2214        {
2215            return !this.capabilities.isFlying;
2216        }
2217    
2218        /**
2219         * Sends the player's abilities to the server (if there is one).
2220         */
2221        public void sendPlayerAbilities() {}
2222    
2223        /**
2224         * Sets the player's game mode and sends it to them.
2225         */
2226        public void setGameType(EnumGameType par1EnumGameType) {}
2227    
2228        /**
2229         * Gets the name of this command sender (usually username, but possibly "Rcon")
2230         */
2231        public String getCommandSenderName()
2232        {
2233            return this.username;
2234        }
2235    
2236        public StringTranslate getTranslator()
2237        {
2238            return StringTranslate.getInstance();
2239        }
2240    
2241        /**
2242         * Translates and formats the given string key with the given arguments.
2243         */
2244        public String translateString(String par1Str, Object ... par2ArrayOfObj)
2245        {
2246            return this.getTranslator().translateKeyFormat(par1Str, par2ArrayOfObj);
2247        }
2248    
2249        /**
2250         * Returns the InventoryEnderChest of this player.
2251         */
2252        public InventoryEnderChest getInventoryEnderChest()
2253        {
2254            return this.theInventoryEnderChest;
2255        }
2256    
2257        /**
2258         * 0 = item, 1-n is armor
2259         */
2260        public ItemStack getCurrentItemOrArmor(int par1)
2261        {
2262            return par1 == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[par1 - 1];
2263        }
2264    
2265        /**
2266         * Returns the item that this EntityLiving is holding, if any.
2267         */
2268        public ItemStack getHeldItem()
2269        {
2270            return this.inventory.getCurrentItem();
2271        }
2272    
2273        /**
2274         * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
2275         */
2276        public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
2277        {
2278            this.inventory.armorInventory[par1] = par2ItemStack;
2279        }
2280    
2281        public ItemStack[] getLastActiveItems()
2282        {
2283            return this.inventory.armorInventory;
2284        }
2285    
2286        @SideOnly(Side.CLIENT)
2287        public boolean getHideCape()
2288        {
2289            return this.getHideCape(1);
2290        }
2291    
2292        public void openGui(Object mod, int modGuiId, World world, int x, int y, int z)
2293        {
2294            FMLNetworkHandler.openGui(this, mod, modGuiId, world, x, y, z);
2295        }
2296    }