    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    }