    001package net.minecraft.entity.ai;
    002
    003import java.util.List;
    004import net.minecraft.entity.Entity;
    005import net.minecraft.entity.EntityCreature;
    006import net.minecraft.entity.passive.EntityTameable;
    007import net.minecraft.entity.player.EntityPlayer;
    008import net.minecraft.pathfinding.PathEntity;
    009import net.minecraft.pathfinding.PathNavigate;
    010import net.minecraft.util.Vec3;
    011
    012public class EntityAIAvoidEntity extends EntityAIBase
    013{
    014    /** The entity we are attached to */
    015    private EntityCreature theEntity;
    016    private float farSpeed;
    017    private float nearSpeed;
    018    private Entity closestLivingEntity;
    019    private float distanceFromEntity;
    020
    021    /** The PathEntity of our entity */
    022    private PathEntity entityPathEntity;
    023
    024    /** The PathNavigate of our entity */
    025    private PathNavigate entityPathNavigate;
    026
    027    /** The class of the entity we should avoid */
    028    private Class targetEntityClass;
    029
    030    public EntityAIAvoidEntity(EntityCreature par1EntityCreature, Class par2Class, float par3, float par4, float par5)
    031    {
    032        this.theEntity = par1EntityCreature;
    033        this.targetEntityClass = par2Class;
    034        this.distanceFromEntity = par3;
    035        this.farSpeed = par4;
    036        this.nearSpeed = par5;
    037        this.entityPathNavigate = par1EntityCreature.getNavigator();
    038        this.setMutexBits(1);
    039    }
    040
    041    /**
    042     * Returns whether the EntityAIBase should begin execution.
    043     */
    044    public boolean shouldExecute()
    045    {
    046        if (this.targetEntityClass == EntityPlayer.class)
    047        {
    048            if (this.theEntity instanceof EntityTameable && ((EntityTameable)this.theEntity).isTamed())
    049            {
    050                return false;
    051            }
    052
    053            this.closestLivingEntity = this.theEntity.worldObj.getClosestPlayerToEntity(this.theEntity, (double)this.distanceFromEntity);
    054
    055            if (this.closestLivingEntity == null)
    056            {
    057                return false;
    058            }
    059        }
    060        else
    061        {
    062            List var1 = this.theEntity.worldObj.getEntitiesWithinAABB(this.targetEntityClass, this.theEntity.boundingBox.expand((double)this.distanceFromEntity, 3.0D, (double)this.distanceFromEntity));
    063
    064            if (var1.isEmpty())
    065            {
    066                return false;
    067            }
    068
    069            this.closestLivingEntity = (Entity)var1.get(0);
    070        }
    071
    072        if (!this.theEntity.getEntitySenses().canSee(this.closestLivingEntity))
    073        {
    074            return false;
    075        }
    076        else
    077        {
    078            Vec3 var2 = RandomPositionGenerator.findRandomTargetBlockAwayFrom(this.theEntity, 16, 7, this.theEntity.worldObj.getWorldVec3Pool().getVecFromPool(this.closestLivingEntity.posX, this.closestLivingEntity.posY, this.closestLivingEntity.posZ));
    079
    080            if (var2 == null)
    081            {
    082                return false;
    083            }
    084            else if (this.closestLivingEntity.getDistanceSq(var2.xCoord, var2.yCoord, var2.zCoord) < this.closestLivingEntity.getDistanceSqToEntity(this.theEntity))
    085            {
    086                return false;
    087            }
    088            else
    089            {
    090                this.entityPathEntity = this.entityPathNavigate.getPathToXYZ(var2.xCoord, var2.yCoord, var2.zCoord);
    091                return this.entityPathEntity == null ? false : this.entityPathEntity.isDestinationSame(var2);
    092            }
    093        }
    094    }
    095
    096    /**
    097     * Returns whether an in-progress EntityAIBase should continue executing
    098     */
    099    public boolean continueExecuting()
    100    {
    101        return !this.entityPathNavigate.noPath();
    102    }
    103
    104    /**
    105     * Execute a one shot task or start executing a continuous task
    106     */
    107    public void startExecuting()
    108    {
    109        this.entityPathNavigate.setPath(this.entityPathEntity, this.farSpeed);
    110    }
    111
    112    /**
    113     * Resets the task
    114     */
    115    public void resetTask()
    116    {
    117        this.closestLivingEntity = null;
    118    }
    119
    120    /**
    121     * Updates the task
    122     */
    123    public void updateTask()
    124    {
    125        if (this.theEntity.getDistanceSqToEntity(this.closestLivingEntity) < 49.0D)
    126        {
    127            this.theEntity.getNavigator().setSpeed(this.nearSpeed);
    128        }
    129        else
    130        {
    131            this.theEntity.getNavigator().setSpeed(this.farSpeed);
    132        }
    133    }
    134}