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 }