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