    001    package net.minecraft.client.entity;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.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.shiftedIndex)
    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        protected void func_85030_a(String par1Str, float par2, float par3)
    651        {
    652            this.worldObj.playSound(this.posX, this.posY - (double)this.yOffset, this.posZ, par1Str, par2, par3);
    653        }
    654    }