2018-09-10 03:50:12 +02:00
|
|
|
From 89a06baab04317f850f553f044a6fba5e35388ad Mon Sep 17 00:00:00 2001
|
2018-09-09 18:58:47 +02:00
|
|
|
From: Aikar <aikar@aikar.co>
|
|
|
|
Date: Sun, 9 Sep 2018 12:39:06 -0400
|
|
|
|
Subject: [PATCH] Mob Pathfinding API
|
|
|
|
|
|
|
|
Adds an API to allow plugins to instruct a Mob to Pathfind to a Location or Entity
|
|
|
|
|
|
|
|
This does not do anything to stop other AI rules from changing the location, so
|
|
|
|
it is still up to the plugin to control that or override after another goal changed
|
|
|
|
the location.
|
|
|
|
|
2018-09-09 20:48:32 +02:00
|
|
|
You can use EntityPathfindEvent to cancel new pathfinds from overriding your current.
|
|
|
|
|
2018-09-09 18:58:47 +02:00
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java
|
|
|
|
new file mode 100644
|
2018-09-10 03:45:54 +02:00
|
|
|
index 000000000..d6953b390
|
2018-09-09 18:58:47 +02:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/main/java/com/destroystokyo/paper/entity/Pathfinder.java
|
2018-09-10 03:45:54 +02:00
|
|
|
@@ -0,0 +1,167 @@
|
2018-09-09 18:58:47 +02:00
|
|
|
+package com.destroystokyo.paper.entity;
|
|
|
|
+
|
|
|
|
+import org.bukkit.Location;
|
|
|
|
+import org.bukkit.entity.LivingEntity;
|
|
|
|
+import org.bukkit.entity.Mob;
|
|
|
|
+
|
|
|
|
+import javax.annotation.Nonnull;
|
|
|
|
+import javax.annotation.Nullable;
|
|
|
|
+import java.util.List;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Handles pathfinding operations for an Entity
|
|
|
|
+ */
|
|
|
|
+public interface Pathfinder {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ *
|
|
|
|
+ * @return The entity that is controlled by this pathfinder
|
|
|
|
+ */
|
|
|
|
+ Mob getEntity();
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Instructs the Entity to stop trying to navigate to its current desired location
|
|
|
|
+ */
|
|
|
|
+ void stopPathfinding();
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * If the entity is currently trying to navigate to a destination, this will return true
|
|
|
|
+ * @return true if the entity is navigating to a destination
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ boolean hasPath();
|
2018-09-09 18:58:47 +02:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @return The location the entity is trying to navigate to, or null if there is no destination
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ @Nullable PathResult getCurrentPath();
|
2018-09-09 18:58:47 +02:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Calculates a destination for the Entity to navigate to, but does not set it
|
|
|
|
+ * as the current target. Useful for calculating what would happen before setting it.
|
|
|
|
+ * @param loc Location to navigate to
|
|
|
|
+ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ @Nullable PathResult findPath(Location loc);
|
2018-09-09 18:58:47 +02:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Calculates a destination for the Entity to navigate to to reach the target entity,
|
|
|
|
+ * but does not set it as the current target.
|
|
|
|
+ * Useful for calculating what would happen before setting it.
|
|
|
|
+ *
|
|
|
|
+ * The behavior of this PathResult is subject to the games pathfinding rules, and may
|
|
|
|
+ * result in the pathfinding automatically updating to follow the target Entity.
|
|
|
|
+ *
|
|
|
|
+ * However, this behavior is not guaranteed, and is subject to the games behavior.
|
|
|
|
+ *
|
|
|
|
+ * @param target the Entity to navigate to
|
|
|
|
+ * @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ @Nullable PathResult findPath(LivingEntity target);
|
2018-09-09 18:58:47 +02:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Calculates a destination for the Entity to navigate to, and sets it with default speed
|
|
|
|
+ * as the current target.
|
|
|
|
+ * @param loc Location to navigate to
|
|
|
|
+ * @return If the pathfinding was successfully started
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ default boolean moveTo(@Nonnull Location loc) {
|
|
|
|
+ return moveTo(loc, 1);
|
2018-09-09 18:58:47 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Calculates a destination for the Entity to navigate to, with desired speed
|
|
|
|
+ * as the current target.
|
|
|
|
+ * @param loc Location to navigate to
|
|
|
|
+ * @param speed Speed multiplier to navigate at, where 1 is 'normal'
|
|
|
|
+ * @return If the pathfinding was successfully started
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ default boolean moveTo(@Nonnull Location loc, double speed) {
|
|
|
|
+ PathResult path = findPath(loc);
|
|
|
|
+ return path != null && moveTo(path, speed);
|
2018-09-09 18:58:47 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Calculates a destination for the Entity to navigate to to reach the target entity,
|
|
|
|
+ * and sets it with default speed.
|
|
|
|
+ *
|
|
|
|
+ * The behavior of this PathResult is subject to the games pathfinding rules, and may
|
|
|
|
+ * result in the pathfinding automatically updating to follow the target Entity.
|
|
|
|
+ *
|
|
|
|
+ * However, this behavior is not guaranteed, and is subject to the games behavior.
|
|
|
|
+ *
|
|
|
|
+ * @param target the Entity to navigate to
|
|
|
|
+ * @return If the pathfinding was successfully started
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ default boolean moveTo(@Nonnull LivingEntity target) {
|
|
|
|
+ return moveTo(target, 1);
|
2018-09-09 18:58:47 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Calculates a destination for the Entity to navigate to to reach the target entity,
|
|
|
|
+ * and sets it with specified speed.
|
|
|
|
+ *
|
|
|
|
+ * The behavior of this PathResult is subject to the games pathfinding rules, and may
|
|
|
|
+ * result in the pathfinding automatically updating to follow the target Entity.
|
|
|
|
+ *
|
|
|
|
+ * However, this behavior is not guaranteed, and is subject to the games behavior.
|
|
|
|
+ *
|
|
|
|
+ * @param target the Entity to navigate to
|
|
|
|
+ * @param speed Speed multiplier to navigate at, where 1 is 'normal'
|
|
|
|
+ * @return If the pathfinding was successfully started
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ default boolean moveTo(@Nonnull LivingEntity target, double speed) {
|
|
|
|
+ PathResult path = findPath(target);
|
|
|
|
+ return path != null && moveTo(path, speed);
|
2018-09-09 18:58:47 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Takes the result of a previous pathfinding calculation and sets it
|
|
|
|
+ * as the active pathfinding with default speed.
|
|
|
|
+ *
|
|
|
|
+ * @param path The Path to start following
|
|
|
|
+ * @return If the pathfinding was successfully started
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ default boolean moveTo(@Nonnull PathResult path) {
|
|
|
|
+ return moveTo(path, 1);
|
2018-09-09 18:58:47 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Takes the result of a previous pathfinding calculation and sets it
|
|
|
|
+ * as the active pathfinding,
|
|
|
|
+ *
|
|
|
|
+ * @param path The Path to start following
|
|
|
|
+ * @param speed Speed multiplier to navigate at, where 1 is 'normal'
|
|
|
|
+ * @return If the pathfinding was successfully started
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ boolean moveTo(@Nonnull PathResult path, double speed);
|
2018-09-09 18:58:47 +02:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Represents the result of a pathfinding calculation
|
|
|
|
+ */
|
|
|
|
+ interface PathResult {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * All currently calculated points to follow along the path to reach the destination location
|
|
|
|
+ *
|
|
|
|
+ * Will return points the entity has already moved past, see {@link #getNextPointIndex()}
|
|
|
|
+ * @return List of points
|
|
|
|
+ */
|
|
|
|
+ List<Location> getPoints();
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @return Returns the index of the current point along the points returned in {@link #getPoints()} the entity
|
|
|
|
+ * is trying to reach, or null if we are done with this pathfinding.
|
|
|
|
+ */
|
2018-09-09 20:36:51 +02:00
|
|
|
+ int getNextPointIndex();
|
2018-09-09 18:58:47 +02:00
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @return The next location in the path points the entity is trying to reach, or null if there is no next point
|
|
|
|
+ */
|
2018-09-10 03:45:54 +02:00
|
|
|
+ @Nullable Location getNextPoint();
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @return The closest point the path can get to the target location
|
|
|
|
+ */
|
|
|
|
+ @Nullable Location getFinalPoint();
|
2018-09-09 18:58:47 +02:00
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
diff --git a/src/main/java/org/bukkit/entity/Mob.java b/src/main/java/org/bukkit/entity/Mob.java
|
|
|
|
index d029d34ea..48eddcd30 100644
|
|
|
|
--- a/src/main/java/org/bukkit/entity/Mob.java
|
|
|
|
+++ b/src/main/java/org/bukkit/entity/Mob.java
|
|
|
|
@@ -7,6 +7,14 @@ import org.bukkit.loot.Lootable;
|
|
|
|
*/
|
|
|
|
public interface Mob extends LivingEntity, Lootable {
|
|
|
|
|
|
|
|
+ // Paper start
|
|
|
|
+ /**
|
|
|
|
+ * Enables access to control the pathing of an Entity
|
|
|
|
+ * @return Pathfinding Manager for this entity
|
|
|
|
+ */
|
|
|
|
+ com.destroystokyo.paper.entity.Pathfinder getPathfinder();
|
|
|
|
+ // Paper end
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* Instructs this Mob to set the specified LivingEntity as its target.
|
|
|
|
* <p>
|
|
|
|
--
|
|
|
|
2.18.0
|
|
|
|
|