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