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 }