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