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    }