    001package net.minecraft.entity.ai;
    002
    003import net.minecraft.block.Block;
    004import net.minecraft.block.BlockHalfSlab;
    005import net.minecraft.entity.EntityCreature;
    006import net.minecraft.entity.EntityLiving;
    007import net.minecraft.entity.player.EntityPlayer;
    008import net.minecraft.item.Item;
    009import net.minecraft.item.ItemStack;
    010import net.minecraft.pathfinding.PathFinder;
    011import net.minecraft.pathfinding.PathPoint;
    012import net.minecraft.util.MathHelper;
    013
    014public class EntityAIControlledByPlayer extends EntityAIBase
    015{
    016    private final EntityLiving thisEntity;
    017    private final float maxSpeed;
    018    private float currentSpeed = 0.0F;
    019
    020    /** Whether the entity's speed is boosted. */
    021    private boolean speedBoosted = false;
    022
    023    /**
    024     * Counter for speed boosting, upon reaching maxSpeedBoostTime the speed boost will be disabled
    025     */
    026    private int speedBoostTime = 0;
    027
    028    /** Maximum time the entity's speed should be boosted for. */
    029    private int maxSpeedBoostTime = 0;
    030
    031    public EntityAIControlledByPlayer(EntityLiving par1EntityLiving, float par2)
    032    {
    033        this.thisEntity = par1EntityLiving;
    034        this.maxSpeed = par2;
    035        this.setMutexBits(7);
    036    }
    037
    038    /**
    039     * Execute a one shot task or start executing a continuous task
    040     */
    041    public void startExecuting()
    042    {
    043        this.currentSpeed = 0.0F;
    044    }
    045
    046    /**
    047     * Resets the task
    048     */
    049    public void resetTask()
    050    {
    051        this.speedBoosted = false;
    052        this.currentSpeed = 0.0F;
    053    }
    054
    055    /**
    056     * Returns whether the EntityAIBase should begin execution.
    057     */
    058    public boolean shouldExecute()
    059    {
    060        return this.thisEntity.isEntityAlive() && this.thisEntity.riddenByEntity != null && this.thisEntity.riddenByEntity instanceof EntityPlayer && (this.speedBoosted || this.thisEntity.canBeSteered());
    061    }
    062
    063    /**
    064     * Updates the task
    065     */
    066    public void updateTask()
    067    {
    068        EntityPlayer entityplayer = (EntityPlayer)this.thisEntity.riddenByEntity;
    069        EntityCreature entitycreature = (EntityCreature)this.thisEntity;
    070        float f = MathHelper.wrapAngleTo180_float(entityplayer.rotationYaw - this.thisEntity.rotationYaw) * 0.5F;
    071
    072        if (f > 5.0F)
    073        {
    074            f = 5.0F;
    075        }
    076
    077        if (f < -5.0F)
    078        {
    079            f = -5.0F;
    080        }
    081
    082        this.thisEntity.rotationYaw = MathHelper.wrapAngleTo180_float(this.thisEntity.rotationYaw + f);
    083
    084        if (this.currentSpeed < this.maxSpeed)
    085        {
    086            this.currentSpeed += (this.maxSpeed - this.currentSpeed) * 0.01F;
    087        }
    088
    089        if (this.currentSpeed > this.maxSpeed)
    090        {
    091            this.currentSpeed = this.maxSpeed;
    092        }
    093
    094        int i = MathHelper.floor_double(this.thisEntity.posX);
    095        int j = MathHelper.floor_double(this.thisEntity.posY);
    096        int k = MathHelper.floor_double(this.thisEntity.posZ);
    097        float f1 = this.currentSpeed;
    098
    099        if (this.speedBoosted)
    100        {
    101            if (this.speedBoostTime++ > this.maxSpeedBoostTime)
    102            {
    103                this.speedBoosted = false;
    104            }
    105
    106            f1 += f1 * 1.15F * MathHelper.sin((float)this.speedBoostTime / (float)this.maxSpeedBoostTime * (float)Math.PI);
    107        }
    108
    109        float f2 = 0.91F;
    110
    111        if (this.thisEntity.onGround)
    112        {
    113            f2 = 0.54600006F;
    114            int l = this.thisEntity.worldObj.getBlockId(MathHelper.floor_float((float)i), MathHelper.floor_float((float)j) - 1, MathHelper.floor_float((float)k));
    115
    116            if (l > 0)
    117            {
    118                f2 = Block.blocksList[l].slipperiness * 0.91F;
    119            }
    120        }
    121
    122        float f3 = 0.16277136F / (f2 * f2 * f2);
    123        float f4 = MathHelper.sin(entitycreature.rotationYaw * (float)Math.PI / 180.0F);
    124        float f5 = MathHelper.cos(entitycreature.rotationYaw * (float)Math.PI / 180.0F);
    125        float f6 = entitycreature.getAIMoveSpeed() * f3;
    126        float f7 = Math.max(f1, 1.0F);
    127        f7 = f6 / f7;
    128        float f8 = f1 * f7;
    129        float f9 = -(f8 * f4);
    130        float f10 = f8 * f5;
    131
    132        if (MathHelper.abs(f9) > MathHelper.abs(f10))
    133        {
    134            if (f9 < 0.0F)
    135            {
    136                f9 -= this.thisEntity.width / 2.0F;
    137            }
    138
    139            if (f9 > 0.0F)
    140            {
    141                f9 += this.thisEntity.width / 2.0F;
    142            }
    143
    144            f10 = 0.0F;
    145        }
    146        else
    147        {
    148            f9 = 0.0F;
    149
    150            if (f10 < 0.0F)
    151            {
    152                f10 -= this.thisEntity.width / 2.0F;
    153            }
    154
    155            if (f10 > 0.0F)
    156            {
    157                f10 += this.thisEntity.width / 2.0F;
    158            }
    159        }
    160
    161        int i1 = MathHelper.floor_double(this.thisEntity.posX + (double)f9);
    162        int j1 = MathHelper.floor_double(this.thisEntity.posZ + (double)f10);
    163        PathPoint pathpoint = new PathPoint(MathHelper.floor_float(this.thisEntity.width + 1.0F), MathHelper.floor_float(this.thisEntity.height + entityplayer.height + 1.0F), MathHelper.floor_float(this.thisEntity.width + 1.0F));
    164
    165        if (i != i1 || k != j1)
    166        {
    167            int k1 = this.thisEntity.worldObj.getBlockId(i, j, k);
    168            int l1 = this.thisEntity.worldObj.getBlockId(i, j - 1, k);
    169            boolean flag = this.func_98216_b(k1) || Block.blocksList[k1] == null && this.func_98216_b(l1);
    170
    171            if (!flag && PathFinder.func_82565_a(this.thisEntity, i1, j, j1, pathpoint, false, false, true) == 0 && PathFinder.func_82565_a(this.thisEntity, i, j + 1, k, pathpoint, false, false, true) == 1 && PathFinder.func_82565_a(this.thisEntity, i1, j + 1, j1, pathpoint, false, false, true) == 1)
    172            {
    173                entitycreature.getJumpHelper().setJumping();
    174            }
    175        }
    176
    177        if (!entityplayer.capabilities.isCreativeMode && this.currentSpeed >= this.maxSpeed * 0.5F && this.thisEntity.getRNG().nextFloat() < 0.006F && !this.speedBoosted)
    178        {
    179            ItemStack itemstack = entityplayer.getHeldItem();
    180
    181            if (itemstack != null && itemstack.itemID == Item.carrotOnAStick.itemID)
    182            {
    183                itemstack.damageItem(1, entityplayer);
    184
    185                if (itemstack.stackSize == 0)
    186                {
    187                    ItemStack itemstack1 = new ItemStack(Item.fishingRod);
    188                    itemstack1.setTagCompound(itemstack.stackTagCompound);
    189                    entityplayer.inventory.mainInventory[entityplayer.inventory.currentItem] = itemstack1;
    190                }
    191            }
    192        }
    193
    194        this.thisEntity.moveEntityWithHeading(0.0F, f1);
    195    }
    196
    197    private boolean func_98216_b(int par1)
    198    {
    199        return Block.blocksList[par1] != null && (Block.blocksList[par1].getRenderType() == 10 || Block.blocksList[par1] instanceof BlockHalfSlab);
    200    }
    201
    202    /**
    203     * Return whether the entity's speed is boosted.
    204     */
    205    public boolean isSpeedBoosted()
    206    {
    207        return this.speedBoosted;
    208    }
    209
    210    /**
    211     * Boost the entity's movement speed.
    212     */
    213    public void boostSpeed()
    214    {
    215        this.speedBoosted = true;
    216        this.speedBoostTime = 0;
    217        this.maxSpeedBoostTime = this.thisEntity.getRNG().nextInt(841) + 140;
    218    }
    219
    220    /**
    221     * Return whether the entity is being controlled by a player.
    222     */
    223    public boolean isControlledByPlayer()
    224    {
    225        return !this.isSpeedBoosted() && this.currentSpeed > this.maxSpeed * 0.3F;
    226    }
    227}