    001package net.minecraft.entity.ai;
    002
    003import net.minecraft.entity.EntityLiving;
    004import net.minecraft.entity.passive.EntityTameable;
    005import net.minecraft.entity.player.EntityPlayer;
    006import net.minecraft.pathfinding.PathEntity;
    007import net.minecraft.pathfinding.PathPoint;
    008import net.minecraft.util.MathHelper;
    009
    010public abstract class EntityAITarget extends EntityAIBase
    011{
    012    /** The entity that this task belongs to */
    013    protected EntityLiving taskOwner;
    014    protected float targetDistance;
    015
    016    /**
    017     * If true, EntityAI targets must be able to be seen (cannot be blocked by walls) to be suitable targets.
    018     */
    019    protected boolean shouldCheckSight;
    020    private boolean field_75303_a;
    021    private int field_75301_b;
    022    private int field_75302_c;
    023    private int field_75298_g;
    024
    025    public EntityAITarget(EntityLiving par1EntityLiving, float par2, boolean par3)
    026    {
    027        this(par1EntityLiving, par2, par3, false);
    028    }
    029
    030    public EntityAITarget(EntityLiving par1EntityLiving, float par2, boolean par3, boolean par4)
    031    {
    032        this.field_75301_b = 0;
    033        this.field_75302_c = 0;
    034        this.field_75298_g = 0;
    035        this.taskOwner = par1EntityLiving;
    036        this.targetDistance = par2;
    037        this.shouldCheckSight = par3;
    038        this.field_75303_a = par4;
    039    }
    040
    041    /**
    042     * Returns whether an in-progress EntityAIBase should continue executing
    043     */
    044    public boolean continueExecuting()
    045    {
    046        EntityLiving entityliving = this.taskOwner.getAttackTarget();
    047
    048        if (entityliving == null)
    049        {
    050            return false;
    051        }
    052        else if (!entityliving.isEntityAlive())
    053        {
    054            return false;
    055        }
    056        else if (this.taskOwner.getDistanceSqToEntity(entityliving) > (double)(this.targetDistance * this.targetDistance))
    057        {
    058            return false;
    059        }
    060        else
    061        {
    062            if (this.shouldCheckSight)
    063            {
    064                if (this.taskOwner.getEntitySenses().canSee(entityliving))
    065                {
    066                    this.field_75298_g = 0;
    067                }
    068                else if (++this.field_75298_g > 60)
    069                {
    070                    return false;
    071                }
    072            }
    073
    074            return true;
    075        }
    076    }
    077
    078    /**
    079     * Execute a one shot task or start executing a continuous task
    080     */
    081    public void startExecuting()
    082    {
    083        this.field_75301_b = 0;
    084        this.field_75302_c = 0;
    085        this.field_75298_g = 0;
    086    }
    087
    088    /**
    089     * Resets the task
    090     */
    091    public void resetTask()
    092    {
    093        this.taskOwner.setAttackTarget((EntityLiving)null);
    094    }
    095
    096    /**
    097     * A method used to see if an entity is a suitable target through a number of checks.
    098     */
    099    protected boolean isSuitableTarget(EntityLiving par1EntityLiving, boolean par2)
    100    {
    101        if (par1EntityLiving == null)
    102        {
    103            return false;
    104        }
    105        else if (par1EntityLiving == this.taskOwner)
    106        {
    107            return false;
    108        }
    109        else if (!par1EntityLiving.isEntityAlive())
    110        {
    111            return false;
    112        }
    113        else if (!this.taskOwner.canAttackClass(par1EntityLiving.getClass()))
    114        {
    115            return false;
    116        }
    117        else
    118        {
    119            if (this.taskOwner instanceof EntityTameable && ((EntityTameable)this.taskOwner).isTamed())
    120            {
    121                if (par1EntityLiving instanceof EntityTameable && ((EntityTameable)par1EntityLiving).isTamed())
    122                {
    123                    return false;
    124                }
    125
    126                if (par1EntityLiving == ((EntityTameable)this.taskOwner).getOwner())
    127                {
    128                    return false;
    129                }
    130            }
    131            else if (par1EntityLiving instanceof EntityPlayer && !par2 && ((EntityPlayer)par1EntityLiving).capabilities.disableDamage)
    132            {
    133                return false;
    134            }
    135
    136            if (!this.taskOwner.isWithinHomeDistance(MathHelper.floor_double(par1EntityLiving.posX), MathHelper.floor_double(par1EntityLiving.posY), MathHelper.floor_double(par1EntityLiving.posZ)))
    137            {
    138                return false;
    139            }
    140            else if (this.shouldCheckSight && !this.taskOwner.getEntitySenses().canSee(par1EntityLiving))
    141            {
    142                return false;
    143            }
    144            else
    145            {
    146                if (this.field_75303_a)
    147                {
    148                    if (--this.field_75302_c <= 0)
    149                    {
    150                        this.field_75301_b = 0;
    151                    }
    152
    153                    if (this.field_75301_b == 0)
    154                    {
    155                        this.field_75301_b = this.func_75295_a(par1EntityLiving) ? 1 : 2;
    156                    }
    157
    158                    if (this.field_75301_b == 2)
    159                    {
    160                        return false;
    161                    }
    162                }
    163
    164                return true;
    165            }
    166        }
    167    }
    168
    169    private boolean func_75295_a(EntityLiving par1EntityLiving)
    170    {
    171        this.field_75302_c = 10 + this.taskOwner.getRNG().nextInt(5);
    172        PathEntity pathentity = this.taskOwner.getNavigator().getPathToEntityLiving(par1EntityLiving);
    173
    174        if (pathentity == null)
    175        {
    176            return false;
    177        }
    178        else
    179        {
    180            PathPoint pathpoint = pathentity.getFinalPathPoint();
    181
    182            if (pathpoint == null)
    183            {
    184                return false;
    185            }
    186            else
    187            {
    188                int i = pathpoint.xCoord - MathHelper.floor_double(par1EntityLiving.posX);
    189                int j = pathpoint.zCoord - MathHelper.floor_double(par1EntityLiving.posZ);
    190                return (double)(i * i + j * j) <= 2.25D;
    191            }
    192        }
    193    }
    194}