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