001 package net.minecraft.client.entity; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import net.minecraft.client.Minecraft; 006 import net.minecraft.client.gui.GuiCommandBlock; 007 import net.minecraft.client.gui.GuiEnchantment; 008 import net.minecraft.client.gui.GuiMerchant; 009 import net.minecraft.client.gui.GuiRepair; 010 import net.minecraft.client.gui.GuiScreen; 011 import net.minecraft.client.gui.GuiScreenBook; 012 import net.minecraft.client.gui.inventory.GuiBeacon; 013 import net.minecraft.client.gui.inventory.GuiBrewingStand; 014 import net.minecraft.client.gui.inventory.GuiChest; 015 import net.minecraft.client.gui.inventory.GuiCrafting; 016 import net.minecraft.client.gui.inventory.GuiDispenser; 017 import net.minecraft.client.gui.inventory.GuiEditSign; 018 import net.minecraft.client.gui.inventory.GuiFurnace; 019 import net.minecraft.client.particle.EntityCrit2FX; 020 import net.minecraft.client.particle.EntityPickupFX; 021 import net.minecraft.entity.Entity; 022 import net.minecraft.entity.IMerchant; 023 import net.minecraft.entity.player.EntityPlayer; 024 import net.minecraft.inventory.IInventory; 025 import net.minecraft.item.Item; 026 import net.minecraft.item.ItemStack; 027 import net.minecraft.potion.Potion; 028 import net.minecraft.stats.Achievement; 029 import net.minecraft.stats.AchievementList; 030 import net.minecraft.stats.StatBase; 031 import net.minecraft.tileentity.TileEntity; 032 import net.minecraft.tileentity.TileEntityBeacon; 033 import net.minecraft.tileentity.TileEntityBrewingStand; 034 import net.minecraft.tileentity.TileEntityCommandBlock; 035 import net.minecraft.tileentity.TileEntityDispenser; 036 import net.minecraft.tileentity.TileEntityFurnace; 037 import net.minecraft.tileentity.TileEntitySign; 038 import net.minecraft.util.ChunkCoordinates; 039 import net.minecraft.util.DamageSource; 040 import net.minecraft.util.MathHelper; 041 import net.minecraft.util.MouseFilter; 042 import net.minecraft.util.MovementInput; 043 import net.minecraft.util.Session; 044 import net.minecraft.util.StringUtils; 045 import net.minecraft.world.World; 046 047 @SideOnly(Side.CLIENT) 048 public class EntityPlayerSP extends EntityPlayer 049 { 050 public MovementInput movementInput; 051 protected Minecraft mc; 052 053 /** 054 * Used to tell if the player pressed forward twice. If this is at 0 and it's pressed (And they are allowed to 055 * sprint, aka enough food on the ground etc) it sets this to 7. If it's pressed and it's greater than 0 enable 056 * sprinting. 057 */ 058 protected int sprintToggleTimer = 0; 059 060 /** Ticks left before sprinting is disabled. */ 061 public int sprintingTicksLeft = 0; 062 public float renderArmYaw; 063 public float renderArmPitch; 064 public float prevRenderArmYaw; 065 public float prevRenderArmPitch; 066 private MouseFilter field_71162_ch = new MouseFilter(); 067 private MouseFilter field_71160_ci = new MouseFilter(); 068 private MouseFilter field_71161_cj = new MouseFilter(); 069 070 /** The amount of time an entity has been in a Portal */ 071 public float timeInPortal; 072 073 /** The amount of time an entity has been in a Portal the previous tick */ 074 public float prevTimeInPortal; 075 076 public EntityPlayerSP(Minecraft par1Minecraft, World par2World, Session par3Session, int par4) 077 { 078 super(par2World); 079 this.mc = par1Minecraft; 080 this.dimension = par4; 081 082 if (par3Session != null && par3Session.username != null && par3Session.username.length() > 0) 083 { 084 this.skinUrl = "http://skins.minecraft.net/MinecraftSkins/" + StringUtils.stripControlCodes(par3Session.username) + ".png"; 085 } 086 087 this.username = par3Session.username; 088 } 089 090 /** 091 * Tries to moves the entity by the passed in displacement. Args: x, y, z 092 */ 093 public void moveEntity(double par1, double par3, double par5) 094 { 095 super.moveEntity(par1, par3, par5); 096 } 097 098 public void updateEntityActionState() 099 { 100 super.updateEntityActionState(); 101 this.moveStrafing = this.movementInput.moveStrafe; 102 this.moveForward = this.movementInput.moveForward; 103 this.isJumping = this.movementInput.jump; 104 this.prevRenderArmYaw = this.renderArmYaw; 105 this.prevRenderArmPitch = this.renderArmPitch; 106 this.renderArmPitch = (float)((double)this.renderArmPitch + (double)(this.rotationPitch - this.renderArmPitch) * 0.5D); 107 this.renderArmYaw = (float)((double)this.renderArmYaw + (double)(this.rotationYaw - this.renderArmYaw) * 0.5D); 108 } 109 110 /** 111 * Returns whether the entity is in a local (client) world 112 */ 113 protected boolean isClientWorld() 114 { 115 return true; 116 } 117 118 /** 119 * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons 120 * use this to react to sunlight and start to burn. 121 */ 122 public void onLivingUpdate() 123 { 124 if (this.sprintingTicksLeft > 0) 125 { 126 --this.sprintingTicksLeft; 127 128 if (this.sprintingTicksLeft == 0) 129 { 130 this.setSprinting(false); 131 } 132 } 133 134 if (this.sprintToggleTimer > 0) 135 { 136 --this.sprintToggleTimer; 137 } 138 139 if (this.mc.playerController.func_78747_a()) 140 { 141 this.posX = this.posZ = 0.5D; 142 this.posX = 0.0D; 143 this.posZ = 0.0D; 144 this.rotationYaw = (float)this.ticksExisted / 12.0F; 145 this.rotationPitch = 10.0F; 146 this.posY = 68.5D; 147 } 148 else 149 { 150 if (!this.mc.statFileWriter.hasAchievementUnlocked(AchievementList.openInventory)) 151 { 152 this.mc.guiAchievement.queueAchievementInformation(AchievementList.openInventory); 153 } 154 155 this.prevTimeInPortal = this.timeInPortal; 156 157 if (this.inPortal) 158 { 159 if (this.mc.currentScreen != null) 160 { 161 this.mc.displayGuiScreen((GuiScreen)null); 162 } 163 164 if (this.timeInPortal == 0.0F) 165 { 166 this.mc.sndManager.playSoundFX("portal.trigger", 1.0F, this.rand.nextFloat() * 0.4F + 0.8F); 167 } 168 169 this.timeInPortal += 0.0125F; 170 171 if (this.timeInPortal >= 1.0F) 172 { 173 this.timeInPortal = 1.0F; 174 } 175 176 this.inPortal = false; 177 } 178 else if (this.isPotionActive(Potion.confusion) && this.getActivePotionEffect(Potion.confusion).getDuration() > 60) 179 { 180 this.timeInPortal += 0.006666667F; 181 182 if (this.timeInPortal > 1.0F) 183 { 184 this.timeInPortal = 1.0F; 185 } 186 } 187 else 188 { 189 if (this.timeInPortal > 0.0F) 190 { 191 this.timeInPortal -= 0.05F; 192 } 193 194 if (this.timeInPortal < 0.0F) 195 { 196 this.timeInPortal = 0.0F; 197 } 198 } 199 200 if (this.timeUntilPortal > 0) 201 { 202 --this.timeUntilPortal; 203 } 204 205 boolean var1 = this.movementInput.jump; 206 float var2 = 0.8F; 207 boolean var3 = this.movementInput.moveForward >= var2; 208 this.movementInput.updatePlayerMoveState(); 209 210 if (this.isUsingItem()) 211 { 212 this.movementInput.moveStrafe *= 0.2F; 213 this.movementInput.moveForward *= 0.2F; 214 this.sprintToggleTimer = 0; 215 } 216 217 if (this.movementInput.sneak && this.ySize < 0.2F) 218 { 219 this.ySize = 0.2F; 220 } 221 222 this.pushOutOfBlocks(this.posX - (double)this.width * 0.35D, this.boundingBox.minY + 0.5D, this.posZ + (double)this.width * 0.35D); 223 this.pushOutOfBlocks(this.posX - (double)this.width * 0.35D, this.boundingBox.minY + 0.5D, this.posZ - (double)this.width * 0.35D); 224 this.pushOutOfBlocks(this.posX + (double)this.width * 0.35D, this.boundingBox.minY + 0.5D, this.posZ - (double)this.width * 0.35D); 225 this.pushOutOfBlocks(this.posX + (double)this.width * 0.35D, this.boundingBox.minY + 0.5D, this.posZ + (double)this.width * 0.35D); 226 boolean var4 = (float)this.getFoodStats().getFoodLevel() > 6.0F || this.capabilities.allowFlying; 227 228 if (this.onGround && !var3 && this.movementInput.moveForward >= var2 && !this.isSprinting() && var4 && !this.isUsingItem() && !this.isPotionActive(Potion.blindness)) 229 { 230 if (this.sprintToggleTimer == 0) 231 { 232 this.sprintToggleTimer = 7; 233 } 234 else 235 { 236 this.setSprinting(true); 237 this.sprintToggleTimer = 0; 238 } 239 } 240 241 if (this.isSneaking()) 242 { 243 this.sprintToggleTimer = 0; 244 } 245 246 if (this.isSprinting() && (this.movementInput.moveForward < var2 || this.isCollidedHorizontally || !var4)) 247 { 248 this.setSprinting(false); 249 } 250 251 if (this.capabilities.allowFlying && !var1 && this.movementInput.jump) 252 { 253 if (this.flyToggleTimer == 0) 254 { 255 this.flyToggleTimer = 7; 256 } 257 else 258 { 259 this.capabilities.isFlying = !this.capabilities.isFlying; 260 this.sendPlayerAbilities(); 261 this.flyToggleTimer = 0; 262 } 263 } 264 265 if (this.capabilities.isFlying) 266 { 267 if (this.movementInput.sneak) 268 { 269 this.motionY -= 0.15D; 270 } 271 272 if (this.movementInput.jump) 273 { 274 this.motionY += 0.15D; 275 } 276 } 277 278 super.onLivingUpdate(); 279 280 if (this.onGround && this.capabilities.isFlying) 281 { 282 this.capabilities.isFlying = false; 283 this.sendPlayerAbilities(); 284 } 285 } 286 } 287 288 /** 289 * Gets the player's field of view multiplier. (ex. when flying) 290 */ 291 public float getFOVMultiplier() 292 { 293 float var1 = 1.0F; 294 295 if (this.capabilities.isFlying) 296 { 297 var1 *= 1.1F; 298 } 299 300 var1 *= (this.landMovementFactor * this.getSpeedModifier() / this.speedOnGround + 1.0F) / 2.0F; 301 302 if (this.isUsingItem() && this.getItemInUse().itemID == Item.bow.itemID) 303 { 304 int var2 = this.getItemInUseDuration(); 305 float var3 = (float)var2 / 20.0F; 306 307 if (var3 > 1.0F) 308 { 309 var3 = 1.0F; 310 } 311 else 312 { 313 var3 *= var3; 314 } 315 316 var1 *= 1.0F - var3 * 0.15F; 317 } 318 319 return var1; 320 } 321 322 public void updateCloak() 323 { 324 this.playerCloakUrl = "http://skins.minecraft.net/MinecraftCloaks/" + StringUtils.stripControlCodes(this.username) + ".png"; 325 this.cloakUrl = this.playerCloakUrl; 326 } 327 328 /** 329 * sets current screen to null (used on escape buttons of GUIs) 330 */ 331 public void closeScreen() 332 { 333 super.closeScreen(); 334 this.mc.displayGuiScreen((GuiScreen)null); 335 } 336 337 /** 338 * Displays the GUI for editing a sign. Args: tileEntitySign 339 */ 340 public void displayGUIEditSign(TileEntity par1TileEntity) 341 { 342 if (par1TileEntity instanceof TileEntitySign) 343 { 344 this.mc.displayGuiScreen(new GuiEditSign((TileEntitySign)par1TileEntity)); 345 } 346 else if (par1TileEntity instanceof TileEntityCommandBlock) 347 { 348 this.mc.displayGuiScreen(new GuiCommandBlock((TileEntityCommandBlock)par1TileEntity)); 349 } 350 } 351 352 /** 353 * Displays the GUI for interacting with a book. 354 */ 355 public void displayGUIBook(ItemStack par1ItemStack) 356 { 357 Item var2 = par1ItemStack.getItem(); 358 359 if (var2 == Item.writtenBook) 360 { 361 this.mc.displayGuiScreen(new GuiScreenBook(this, par1ItemStack, false)); 362 } 363 else if (var2 == Item.writableBook) 364 { 365 this.mc.displayGuiScreen(new GuiScreenBook(this, par1ItemStack, true)); 366 } 367 } 368 369 /** 370 * Displays the GUI for interacting with a chest inventory. Args: chestInventory 371 */ 372 public void displayGUIChest(IInventory par1IInventory) 373 { 374 this.mc.displayGuiScreen(new GuiChest(this.inventory, par1IInventory)); 375 } 376 377 /** 378 * Displays the crafting GUI for a workbench. 379 */ 380 public void displayGUIWorkbench(int par1, int par2, int par3) 381 { 382 this.mc.displayGuiScreen(new GuiCrafting(this.inventory, this.worldObj, par1, par2, par3)); 383 } 384 385 public void displayGUIEnchantment(int par1, int par2, int par3) 386 { 387 this.mc.displayGuiScreen(new GuiEnchantment(this.inventory, this.worldObj, par1, par2, par3)); 388 } 389 390 /** 391 * Displays the GUI for interacting with an anvil. 392 */ 393 public void displayGUIAnvil(int par1, int par2, int par3) 394 { 395 this.mc.displayGuiScreen(new GuiRepair(this.inventory, this.worldObj, par1, par2, par3)); 396 } 397 398 /** 399 * Displays the furnace GUI for the passed in furnace entity. Args: tileEntityFurnace 400 */ 401 public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) 402 { 403 this.mc.displayGuiScreen(new GuiFurnace(this.inventory, par1TileEntityFurnace)); 404 } 405 406 /** 407 * Displays the GUI for interacting with a brewing stand. 408 */ 409 public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) 410 { 411 this.mc.displayGuiScreen(new GuiBrewingStand(this.inventory, par1TileEntityBrewingStand)); 412 } 413 414 /** 415 * Displays the GUI for interacting with a beacon. 416 */ 417 public void displayGUIBeacon(TileEntityBeacon par1TileEntityBeacon) 418 { 419 this.mc.displayGuiScreen(new GuiBeacon(this.inventory, par1TileEntityBeacon)); 420 } 421 422 /** 423 * Displays the dipsenser GUI for the passed in dispenser entity. Args: TileEntityDispenser 424 */ 425 public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) 426 { 427 this.mc.displayGuiScreen(new GuiDispenser(this.inventory, par1TileEntityDispenser)); 428 } 429 430 public void displayGUIMerchant(IMerchant par1IMerchant) 431 { 432 this.mc.displayGuiScreen(new GuiMerchant(this.inventory, par1IMerchant, this.worldObj)); 433 } 434 435 /** 436 * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically 437 */ 438 public void onCriticalHit(Entity par1Entity) 439 { 440 this.mc.effectRenderer.addEffect(new EntityCrit2FX(this.mc.theWorld, par1Entity)); 441 } 442 443 public void onEnchantmentCritical(Entity par1Entity) 444 { 445 EntityCrit2FX var2 = new EntityCrit2FX(this.mc.theWorld, par1Entity, "magicCrit"); 446 this.mc.effectRenderer.addEffect(var2); 447 } 448 449 /** 450 * Called whenever an item is picked up from walking over it. Args: pickedUpEntity, stackSize 451 */ 452 public void onItemPickup(Entity par1Entity, int par2) 453 { 454 this.mc.effectRenderer.addEffect(new EntityPickupFX(this.mc.theWorld, par1Entity, this, -0.5F)); 455 } 456 457 /** 458 * Returns if this entity is sneaking. 459 */ 460 public boolean isSneaking() 461 { 462 return this.movementInput.sneak && !this.sleeping; 463 } 464 465 /** 466 * Updates health locally. 467 */ 468 public void setHealth(int par1) 469 { 470 int var2 = this.getHealth() - par1; 471 472 if (var2 <= 0) 473 { 474 this.setEntityHealth(par1); 475 476 if (var2 < 0) 477 { 478 this.hurtResistantTime = this.maxHurtResistantTime / 2; 479 } 480 } 481 else 482 { 483 this.lastDamage = var2; 484 this.setEntityHealth(this.getHealth()); 485 this.hurtResistantTime = this.maxHurtResistantTime; 486 this.damageEntity(DamageSource.generic, var2); 487 this.hurtTime = this.maxHurtTime = 10; 488 } 489 } 490 491 /** 492 * Add a chat message to the player 493 */ 494 public void addChatMessage(String par1Str) 495 { 496 this.mc.ingameGUI.getChatGUI().addTranslatedMessage(par1Str, new Object[0]); 497 } 498 499 /** 500 * Adds a value to a statistic field. 501 */ 502 public void addStat(StatBase par1StatBase, int par2) 503 { 504 if (par1StatBase != null) 505 { 506 if (par1StatBase.isAchievement()) 507 { 508 Achievement var3 = (Achievement)par1StatBase; 509 510 if (var3.parentAchievement == null || this.mc.statFileWriter.hasAchievementUnlocked(var3.parentAchievement)) 511 { 512 if (!this.mc.statFileWriter.hasAchievementUnlocked(var3)) 513 { 514 this.mc.guiAchievement.queueTakenAchievement(var3); 515 } 516 517 this.mc.statFileWriter.readStat(par1StatBase, par2); 518 } 519 } 520 else 521 { 522 this.mc.statFileWriter.readStat(par1StatBase, par2); 523 } 524 } 525 } 526 527 private boolean isBlockTranslucent(int par1, int par2, int par3) 528 { 529 return this.worldObj.isBlockNormalCube(par1, par2, par3); 530 } 531 532 /** 533 * Adds velocity to push the entity out of blocks at the specified x, y, z position Args: x, y, z 534 */ 535 protected boolean pushOutOfBlocks(double par1, double par3, double par5) 536 { 537 int var7 = MathHelper.floor_double(par1); 538 int var8 = MathHelper.floor_double(par3); 539 int var9 = MathHelper.floor_double(par5); 540 double var10 = par1 - (double)var7; 541 double var12 = par5 - (double)var9; 542 543 if (this.isBlockTranslucent(var7, var8, var9) || this.isBlockTranslucent(var7, var8 + 1, var9)) 544 { 545 boolean var14 = !this.isBlockTranslucent(var7 - 1, var8, var9) && !this.isBlockTranslucent(var7 - 1, var8 + 1, var9); 546 boolean var15 = !this.isBlockTranslucent(var7 + 1, var8, var9) && !this.isBlockTranslucent(var7 + 1, var8 + 1, var9); 547 boolean var16 = !this.isBlockTranslucent(var7, var8, var9 - 1) && !this.isBlockTranslucent(var7, var8 + 1, var9 - 1); 548 boolean var17 = !this.isBlockTranslucent(var7, var8, var9 + 1) && !this.isBlockTranslucent(var7, var8 + 1, var9 + 1); 549 byte var18 = -1; 550 double var19 = 9999.0D; 551 552 if (var14 && var10 < var19) 553 { 554 var19 = var10; 555 var18 = 0; 556 } 557 558 if (var15 && 1.0D - var10 < var19) 559 { 560 var19 = 1.0D - var10; 561 var18 = 1; 562 } 563 564 if (var16 && var12 < var19) 565 { 566 var19 = var12; 567 var18 = 4; 568 } 569 570 if (var17 && 1.0D - var12 < var19) 571 { 572 var19 = 1.0D - var12; 573 var18 = 5; 574 } 575 576 float var21 = 0.1F; 577 578 if (var18 == 0) 579 { 580 this.motionX = (double)(-var21); 581 } 582 583 if (var18 == 1) 584 { 585 this.motionX = (double)var21; 586 } 587 588 if (var18 == 4) 589 { 590 this.motionZ = (double)(-var21); 591 } 592 593 if (var18 == 5) 594 { 595 this.motionZ = (double)var21; 596 } 597 } 598 599 return false; 600 } 601 602 /** 603 * Set sprinting switch for Entity. 604 */ 605 public void setSprinting(boolean par1) 606 { 607 super.setSprinting(par1); 608 this.sprintingTicksLeft = par1 ? 600 : 0; 609 } 610 611 /** 612 * Sets the current XP, total XP, and level number. 613 */ 614 public void setXPStats(float par1, int par2, int par3) 615 { 616 this.experience = par1; 617 this.experienceTotal = par2; 618 this.experienceLevel = par3; 619 } 620 621 public void sendChatToPlayer(String par1Str) 622 { 623 this.mc.ingameGUI.getChatGUI().printChatMessage(par1Str); 624 } 625 626 /** 627 * Returns true if the command sender is allowed to use the given command. 628 */ 629 public boolean canCommandSenderUseCommand(int par1, String par2Str) 630 { 631 return par1 <= 0; 632 } 633 634 /** 635 * Return the coordinates for this player as ChunkCoordinates. 636 */ 637 public ChunkCoordinates getPlayerCoordinates() 638 { 639 return new ChunkCoordinates(MathHelper.floor_double(this.posX + 0.5D), MathHelper.floor_double(this.posY + 0.5D), MathHelper.floor_double(this.posZ + 0.5D)); 640 } 641 642 /** 643 * Returns the item that this EntityLiving is holding, if any. 644 */ 645 public ItemStack getHeldItem() 646 { 647 return this.inventory.getCurrentItem(); 648 } 649 650 public void playSound(String par1Str, float par2, float par3) 651 { 652 this.worldObj.playSound(this.posX, this.posY - (double)this.yOffset, this.posZ, par1Str, par2, par3, false); 653 } 654 }