001package net.minecraft.entity.ai; 002 003import java.util.List; 004import net.minecraft.command.IEntitySelector; 005import net.minecraft.entity.Entity; 006import net.minecraft.entity.EntityCreature; 007import net.minecraft.entity.passive.EntityTameable; 008import net.minecraft.entity.player.EntityPlayer; 009import net.minecraft.pathfinding.PathEntity; 010import net.minecraft.pathfinding.PathNavigate; 011import net.minecraft.util.Vec3; 012 013public class EntityAIAvoidEntity extends EntityAIBase 014{ 015 public final IEntitySelector field_98218_a = new EntityAIAvoidEntitySelector(this); 016 017 /** The entity we are attached to */ 018 private EntityCreature theEntity; 019 private float farSpeed; 020 private float nearSpeed; 021 private Entity closestLivingEntity; 022 private float distanceFromEntity; 023 024 /** The PathEntity of our entity */ 025 private PathEntity entityPathEntity; 026 027 /** The PathNavigate of our entity */ 028 private PathNavigate entityPathNavigate; 029 030 /** The class of the entity we should avoid */ 031 private Class targetEntityClass; 032 033 public EntityAIAvoidEntity(EntityCreature par1EntityCreature, Class par2Class, float par3, float par4, float par5) 034 { 035 this.theEntity = par1EntityCreature; 036 this.targetEntityClass = par2Class; 037 this.distanceFromEntity = par3; 038 this.farSpeed = par4; 039 this.nearSpeed = par5; 040 this.entityPathNavigate = par1EntityCreature.getNavigator(); 041 this.setMutexBits(1); 042 } 043 044 /** 045 * Returns whether the EntityAIBase should begin execution. 046 */ 047 public boolean shouldExecute() 048 { 049 if (this.targetEntityClass == EntityPlayer.class) 050 { 051 if (this.theEntity instanceof EntityTameable && ((EntityTameable)this.theEntity).isTamed()) 052 { 053 return false; 054 } 055 056 this.closestLivingEntity = this.theEntity.worldObj.getClosestPlayerToEntity(this.theEntity, (double)this.distanceFromEntity); 057 058 if (this.closestLivingEntity == null) 059 { 060 return false; 061 } 062 } 063 else 064 { 065 List list = this.theEntity.worldObj.selectEntitiesWithinAABB(this.targetEntityClass, this.theEntity.boundingBox.expand((double)this.distanceFromEntity, 3.0D, (double)this.distanceFromEntity), this.field_98218_a); 066 067 if (list.isEmpty()) 068 { 069 return false; 070 } 071 072 this.closestLivingEntity = (Entity)list.get(0); 073 } 074 075 Vec3 vec3 = RandomPositionGenerator.findRandomTargetBlockAwayFrom(this.theEntity, 16, 7, this.theEntity.worldObj.getWorldVec3Pool().getVecFromPool(this.closestLivingEntity.posX, this.closestLivingEntity.posY, this.closestLivingEntity.posZ)); 076 077 if (vec3 == null) 078 { 079 return false; 080 } 081 else if (this.closestLivingEntity.getDistanceSq(vec3.xCoord, vec3.yCoord, vec3.zCoord) < this.closestLivingEntity.getDistanceSqToEntity(this.theEntity)) 082 { 083 return false; 084 } 085 else 086 { 087 this.entityPathEntity = this.entityPathNavigate.getPathToXYZ(vec3.xCoord, vec3.yCoord, vec3.zCoord); 088 return this.entityPathEntity == null ? false : this.entityPathEntity.isDestinationSame(vec3); 089 } 090 } 091 092 /** 093 * Returns whether an in-progress EntityAIBase should continue executing 094 */ 095 public boolean continueExecuting() 096 { 097 return !this.entityPathNavigate.noPath(); 098 } 099 100 /** 101 * Execute a one shot task or start executing a continuous task 102 */ 103 public void startExecuting() 104 { 105 this.entityPathNavigate.setPath(this.entityPathEntity, this.farSpeed); 106 } 107 108 /** 109 * Resets the task 110 */ 111 public void resetTask() 112 { 113 this.closestLivingEntity = null; 114 } 115 116 /** 117 * Updates the task 118 */ 119 public void updateTask() 120 { 121 if (this.theEntity.getDistanceSqToEntity(this.closestLivingEntity) < 49.0D) 122 { 123 this.theEntity.getNavigator().setSpeed(this.nearSpeed); 124 } 125 else 126 { 127 this.theEntity.getNavigator().setSpeed(this.farSpeed); 128 } 129 } 130 131 static EntityCreature func_98217_a(EntityAIAvoidEntity par0EntityAIAvoidEntity) 132 { 133 return par0EntityAIAvoidEntity.theEntity; 134 } 135}