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