diff --git a/src/main/java/fr/themode/demo/PlayerInit.java b/src/main/java/fr/themode/demo/PlayerInit.java index ec402c7d5..1abd3ef7a 100644 --- a/src/main/java/fr/themode/demo/PlayerInit.java +++ b/src/main/java/fr/themode/demo/PlayerInit.java @@ -151,6 +151,7 @@ public class PlayerInit { ChickenCreature chickenCreature = new ChickenCreature(player.getPosition()); chickenCreature.setInstance(player.getInstance()); + chickenCreature.setTarget(player); /*EntityZombie zombie = new EntityZombie(player.getPosition()); zombie.setAttribute(Attribute.MOVEMENT_SPEED, 0.25f); diff --git a/src/main/java/fr/themode/demo/entity/ChickenCreature.java b/src/main/java/fr/themode/demo/entity/ChickenCreature.java index 39df66458..6b56874cd 100644 --- a/src/main/java/fr/themode/demo/entity/ChickenCreature.java +++ b/src/main/java/fr/themode/demo/entity/ChickenCreature.java @@ -1,7 +1,8 @@ package fr.themode.demo.entity; import net.minestom.server.attribute.Attribute; -import net.minestom.server.entity.ai.goal.RandomStrollGoal; +import net.minestom.server.entity.ai.goal.FollowTargetGoal; +import net.minestom.server.entity.ai.target.PlayerTarget; import net.minestom.server.entity.type.EntityChicken; import net.minestom.server.utils.Position; @@ -11,7 +12,11 @@ public class ChickenCreature extends EntityChicken { super(defaultPosition); //goalSelectors.add(new DoNothingGoal(this, 500, 0.1f)); - goalSelectors.add(new RandomStrollGoal(this, 2)); + //goalSelectors.add(new RandomStrollGoal(this, 2)); + goalSelectors.add(new FollowTargetGoal(this)); + + + targetSelectors.add(new PlayerTarget(this, 15)); setAttribute(Attribute.MOVEMENT_SPEED, 0.1f); diff --git a/src/main/java/net/minestom/server/entity/EntityCreature.java b/src/main/java/net/minestom/server/entity/EntityCreature.java index a61dcd85c..a9b2c6a8e 100644 --- a/src/main/java/net/minestom/server/entity/EntityCreature.java +++ b/src/main/java/net/minestom/server/entity/EntityCreature.java @@ -32,6 +32,7 @@ public abstract class EntityCreature extends LivingEntity { private PFPathingEntity pathingEntity = new PFPathingEntity(this); private HydrazinePathFinder pathFinder; private PathObject path; + private Position pathPosition; protected List goalSelectors = new ArrayList<>(); protected List targetSelectors = new ArrayList<>(); @@ -122,6 +123,7 @@ public abstract class EntityCreature extends LivingEntity { } else { // TODO not call this every tick (code above with #done() is never called) pathFinder.reset(); + pathPosition = null; } super.update(time); @@ -400,7 +402,21 @@ public abstract class EntityCreature extends LivingEntity { position = position.clone(); this.path = pathFinder.initiatePathTo(position.getX(), position.getY(), position.getZ()); - return path != null; + + final boolean success = path != null; + + this.pathPosition = success ? position : null; + + return success; + } + + /** + * Get the target pathfinder position + * + * @return the target pathfinder position, null if there is no one + */ + public Position getPathPosition() { + return pathPosition; } /** diff --git a/src/main/java/net/minestom/server/entity/ai/GoalSelector.java b/src/main/java/net/minestom/server/entity/ai/GoalSelector.java index 664822160..3adc651d5 100644 --- a/src/main/java/net/minestom/server/entity/ai/GoalSelector.java +++ b/src/main/java/net/minestom/server/entity/ai/GoalSelector.java @@ -5,7 +5,7 @@ import net.minestom.server.entity.EntityCreature; public abstract class GoalSelector { - private EntityCreature entityCreature; + protected EntityCreature entityCreature; public GoalSelector(EntityCreature entityCreature) { this.entityCreature = entityCreature; @@ -40,15 +40,6 @@ public abstract class GoalSelector { */ public abstract void end(); - /** - * Get the entity linked to this goal selector - * - * @return the entity - */ - public EntityCreature getEntityCreature() { - return entityCreature; - } - /** * Find a target based on the entity {@link TargetSelector} * diff --git a/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java new file mode 100644 index 000000000..0a89e9e75 --- /dev/null +++ b/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java @@ -0,0 +1,53 @@ +package net.minestom.server.entity.ai.goal; + +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityCreature; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.utils.Position; + +public class FollowTargetGoal extends GoalSelector { + + private Position lastPath; + + public FollowTargetGoal(EntityCreature entityCreature) { + super(entityCreature); + } + + @Override + public boolean shouldStart() { + return entityCreature.getTarget() != null; + } + + @Override + public void start() { + final Entity target = entityCreature.getTarget(); + + if (target != null) { + final Position targetPosition = target.getPosition(); + if (targetPosition.getDistance(entityCreature.getPosition()) < 1) { + entityCreature.setPathTo(null); + return; + } + + if (lastPath == null || lastPath.equals(targetPosition)) { + entityCreature.setPathTo(targetPosition); + lastPath = targetPosition; + } + } + } + + @Override + public void tick() { + + } + + @Override + public boolean shouldEnd() { + return true; + } + + @Override + public void end() { + + } +} diff --git a/src/main/java/net/minestom/server/entity/ai/goal/RandomStrollGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/RandomStrollGoal.java index 0ca2d7ce7..4347d153d 100644 --- a/src/main/java/net/minestom/server/entity/ai/goal/RandomStrollGoal.java +++ b/src/main/java/net/minestom/server/entity/ai/goal/RandomStrollGoal.java @@ -38,8 +38,8 @@ public class RandomStrollGoal extends GoalSelector { Collections.shuffle(closePositions); for (Position position : closePositions) { - Position target = position.clone().add(getEntityCreature().getPosition()); - final boolean result = getEntityCreature().setPathTo(target); + Position target = position.clone().add(entityCreature.getPosition()); + final boolean result = entityCreature.setPathTo(target); if (result) { break; } diff --git a/src/main/java/net/minestom/server/entity/ai/target/PlayerTarget.java b/src/main/java/net/minestom/server/entity/ai/target/PlayerTarget.java new file mode 100644 index 000000000..99544cc84 --- /dev/null +++ b/src/main/java/net/minestom/server/entity/ai/target/PlayerTarget.java @@ -0,0 +1,40 @@ +package net.minestom.server.entity.ai.target; + +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityCreature; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.instance.Instance; + +import java.util.Set; + +public class PlayerTarget extends TargetSelector { + + private float range; + + public PlayerTarget(EntityCreature entityCreature, float range) { + super(entityCreature); + this.range = range; + } + + @Override + public Entity findTarget() { + final Instance instance = getEntityCreature().getInstance(); + final Set players = instance.getPlayers(); + + Player player = null; + { + float distance = Float.MAX_VALUE; + for (Player p : players) { + final float d = getEntityCreature().getDistance(p); + if ((player == null || d < distance) && d < range) { + player = p; + distance = d; + continue; + } + } + } + + return player; + } +}