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 var1 = this.taskOwner.getAttackTarget();
047
048        if (var1 == null)
049        {
050            return false;
051        }
052        else if (!var1.isEntityAlive())
053        {
054            return false;
055        }
056        else if (this.taskOwner.getDistanceSqToEntity(var1) > (double)(this.targetDistance * this.targetDistance))
057        {
058            return false;
059        }
060        else
061        {
062            if (this.shouldCheckSight)
063            {
064                if (this.taskOwner.getEntitySenses().canSee(var1))
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 var2 = this.taskOwner.getNavigator().getPathToEntityLiving(par1EntityLiving);
173
174        if (var2 == null)
175        {
176            return false;
177        }
178        else
179        {
180            PathPoint var3 = var2.getFinalPathPoint();
181
182            if (var3 == null)
183            {
184                return false;
185            }
186            else
187            {
188                int var4 = var3.xCoord - MathHelper.floor_double(par1EntityLiving.posX);
189                int var5 = var3.zCoord - MathHelper.floor_double(par1EntityLiving.posZ);
190                return (double)(var4 * var4 + var5 * var5) <= 2.25D;
191            }
192        }
193    }
194}