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