001 package net.minecraft.entity.ai;
002
003 import net.minecraft.entity.EntityLiving;
004 import net.minecraft.entity.passive.EntityTameable;
005 import net.minecraft.pathfinding.PathNavigate;
006 import net.minecraft.util.MathHelper;
007 import net.minecraft.world.World;
008
009 public class EntityAIFollowOwner extends EntityAIBase
010 {
011 private EntityTameable thePet;
012 private EntityLiving theOwner;
013 World theWorld;
014 private float field_75336_f;
015 private PathNavigate petPathfinder;
016 private int field_75343_h;
017 float maxDist;
018 float minDist;
019 private boolean field_75344_i;
020
021 public EntityAIFollowOwner(EntityTameable par1EntityTameable, float par2, float par3, float par4)
022 {
023 this.thePet = par1EntityTameable;
024 this.theWorld = par1EntityTameable.worldObj;
025 this.field_75336_f = par2;
026 this.petPathfinder = par1EntityTameable.getNavigator();
027 this.minDist = par3;
028 this.maxDist = par4;
029 this.setMutexBits(3);
030 }
031
032 /**
033 * Returns whether the EntityAIBase should begin execution.
034 */
035 public boolean shouldExecute()
036 {
037 EntityLiving var1 = this.thePet.getOwner();
038
039 if (var1 == null)
040 {
041 return false;
042 }
043 else if (this.thePet.isSitting())
044 {
045 return false;
046 }
047 else if (this.thePet.getDistanceSqToEntity(var1) < (double)(this.minDist * this.minDist))
048 {
049 return false;
050 }
051 else
052 {
053 this.theOwner = var1;
054 return true;
055 }
056 }
057
058 /**
059 * Returns whether an in-progress EntityAIBase should continue executing
060 */
061 public boolean continueExecuting()
062 {
063 return !this.petPathfinder.noPath() && this.thePet.getDistanceSqToEntity(this.theOwner) > (double)(this.maxDist * this.maxDist) && !this.thePet.isSitting();
064 }
065
066 /**
067 * Execute a one shot task or start executing a continuous task
068 */
069 public void startExecuting()
070 {
071 this.field_75343_h = 0;
072 this.field_75344_i = this.thePet.getNavigator().getAvoidsWater();
073 this.thePet.getNavigator().setAvoidsWater(false);
074 }
075
076 /**
077 * Resets the task
078 */
079 public void resetTask()
080 {
081 this.theOwner = null;
082 this.petPathfinder.clearPathEntity();
083 this.thePet.getNavigator().setAvoidsWater(this.field_75344_i);
084 }
085
086 /**
087 * Updates the task
088 */
089 public void updateTask()
090 {
091 this.thePet.getLookHelper().setLookPositionWithEntity(this.theOwner, 10.0F, (float)this.thePet.getVerticalFaceSpeed());
092
093 if (!this.thePet.isSitting())
094 {
095 if (--this.field_75343_h <= 0)
096 {
097 this.field_75343_h = 10;
098
099 if (!this.petPathfinder.tryMoveToEntityLiving(this.theOwner, this.field_75336_f))
100 {
101 if (this.thePet.getDistanceSqToEntity(this.theOwner) >= 144.0D)
102 {
103 int var1 = MathHelper.floor_double(this.theOwner.posX) - 2;
104 int var2 = MathHelper.floor_double(this.theOwner.posZ) - 2;
105 int var3 = MathHelper.floor_double(this.theOwner.boundingBox.minY);
106
107 for (int var4 = 0; var4 <= 4; ++var4)
108 {
109 for (int var5 = 0; var5 <= 4; ++var5)
110 {
111 if ((var4 < 1 || var5 < 1 || var4 > 3 || var5 > 3) && this.theWorld.doesBlockHaveSolidTopSurface(var1 + var4, var3 - 1, var2 + var5) && !this.theWorld.isBlockNormalCube(var1 + var4, var3, var2 + var5) && !this.theWorld.isBlockNormalCube(var1 + var4, var3 + 1, var2 + var5))
112 {
113 this.thePet.setLocationAndAngles((double)((float)(var1 + var4) + 0.5F), (double)var3, (double)((float)(var2 + var5) + 0.5F), this.thePet.rotationYaw, this.thePet.rotationPitch);
114 this.petPathfinder.clearPathEntity();
115 return;
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123 }
124 }