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