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