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 }