001    package net.minecraft.entity.ai;
002    
003    import net.minecraft.entity.EntityLiving;
004    import net.minecraft.entity.passive.EntityTameable;
005    import net.minecraft.entity.player.EntityPlayer;
006    import net.minecraft.pathfinding.PathEntity;
007    import net.minecraft.pathfinding.PathPoint;
008    import net.minecraft.util.MathHelper;
009    
010    public 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    }