2021-06-11 14:02:28 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Aikar <aikar@aikar.co>
|
|
|
|
Date: Sun, 9 Sep 2018 13:30:00 -0400
|
|
|
|
Subject: [PATCH] Mob Pathfinding API
|
|
|
|
|
|
|
|
Implements Pathfinding API for mobs
|
|
|
|
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
|
|
|
new file mode 100644
|
2021-06-17 23:39:36 +02:00
|
|
|
index 0000000000000000000000000000000000000000..8c9f0c6c38627beded373ca29f1989ae3ba6f873
|
2021-06-11 14:02:28 +02:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java
|
2021-06-13 06:03:02 +02:00
|
|
|
@@ -0,0 +1,139 @@
|
2021-06-11 14:02:28 +02:00
|
|
|
+package com.destroystokyo.paper.entity;
|
|
|
|
+
|
|
|
|
+import org.apache.commons.lang.Validate;
|
|
|
|
+import org.bukkit.Location;
|
|
|
|
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
|
|
|
|
+import org.bukkit.entity.LivingEntity;
|
|
|
|
+import org.bukkit.entity.Mob;
|
|
|
|
+import javax.annotation.Nonnull;
|
|
|
|
+import javax.annotation.Nullable;
|
|
|
|
+import net.minecraft.world.level.pathfinder.Node;
|
|
|
|
+import net.minecraft.world.level.pathfinder.Path;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.List;
|
|
|
|
+
|
|
|
|
+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder {
|
|
|
|
+
|
|
|
|
+ private final net.minecraft.world.entity.Mob entity;
|
|
|
|
+
|
|
|
|
+ public PaperPathfinder(net.minecraft.world.entity.Mob entity) {
|
|
|
|
+ this.entity = entity;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Mob getEntity() {
|
|
|
|
+ return entity.getBukkitMob();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void stopPathfinding() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ entity.getNavigation().stop();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean hasPath() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return entity.getNavigation().getPath() != null;
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Nullable
|
|
|
|
+ @Override
|
|
|
|
+ public PathResult getCurrentPath() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ Path path = entity.getNavigation().getPath();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ return path != null ? new PaperPathResult(path) : null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Nullable
|
|
|
|
+ @Override
|
|
|
|
+ public PathResult findPath(Location loc) {
|
|
|
|
+ Validate.notNull(loc, "Location can not be null");
|
2021-06-17 23:39:36 +02:00
|
|
|
+ Path path = entity.getNavigation().createPath(loc.getX(), loc.getY(), loc.getZ(), 0);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ return path != null ? new PaperPathResult(path) : null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Nullable
|
|
|
|
+ @Override
|
|
|
|
+ public PathResult findPath(LivingEntity target) {
|
|
|
|
+ Validate.notNull(target, "Target can not be null");
|
2021-06-17 23:39:36 +02:00
|
|
|
+ Path path = entity.getNavigation().createPath(((CraftLivingEntity) target).getHandle(), 0);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ return path != null ? new PaperPathResult(path) : null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean moveTo(@Nonnull PathResult path, double speed) {
|
|
|
|
+ Validate.notNull(path, "PathResult can not be null");
|
|
|
|
+ Path pathEntity = ((PaperPathResult) path).path;
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return entity.getNavigation().moveTo(pathEntity, speed);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean canOpenDoors() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return entity.getNavigation().pathFinder.nodeEvaluator.canOpenDoors();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void setCanOpenDoors(boolean canOpenDoors) {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanOpenDoors(canOpenDoors);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean canPassDoors() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return entity.getNavigation().pathFinder.nodeEvaluator.canPassDoors();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void setCanPassDoors(boolean canPassDoors) {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanPassDoors(canPassDoors);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean canFloat() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return entity.getNavigation().pathFinder.nodeEvaluator.canFloat();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void setCanFloat(boolean canFloat) {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ entity.getNavigation().pathFinder.nodeEvaluator.setCanFloat(canFloat);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult {
|
|
|
|
+
|
|
|
|
+ private final Path path;
|
|
|
|
+ PaperPathResult(Path path) {
|
|
|
|
+ this.path = path;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Nullable
|
|
|
|
+ @Override
|
|
|
|
+ public Location getFinalPoint() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ Node point = path.getEndNode();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ return point != null ? toLoc(point) : null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<Location> getPoints() {
|
|
|
|
+ List<Location> points = new ArrayList<>();
|
2021-06-17 23:39:36 +02:00
|
|
|
+ for (Node point : path.nodes) {
|
2021-06-11 14:02:28 +02:00
|
|
|
+ points.add(toLoc(point));
|
|
|
|
+ }
|
|
|
|
+ return points;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public int getNextPointIndex() {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return path.getNextNodeIndex();
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Nullable
|
|
|
|
+ @Override
|
|
|
|
+ public Location getNextPoint() {
|
|
|
|
+ if (!path.hasNext()) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return toLoc(path.nodes.get(path.getNextNodeIndex()));
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Location toLoc(Node point) {
|
2021-06-17 23:39:36 +02:00
|
|
|
+ return new Location(entity.level.getWorld(), point.x, point.y, point.z);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
2021-11-24 00:06:05 +01:00
|
|
|
index 5f59b2bd26571d16e04f2b6a5ded8f8fb7c4e31e..bdc221f5b1eccff017c5eace11f4ea2540329f1d 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java
|
2021-11-24 00:06:05 +01:00
|
|
|
@@ -21,6 +21,7 @@ public class Path {
|
2021-06-11 14:02:28 +02:00
|
|
|
private final BlockPos target;
|
|
|
|
private final float distToTarget;
|
|
|
|
private final boolean reached;
|
2021-06-17 23:39:36 +02:00
|
|
|
+ public boolean hasNext() { return getNextNodeIndex() < this.nodes.size(); } // Paper
|
2021-06-11 14:02:28 +02:00
|
|
|
|
|
|
|
public Path(List<Node> nodes, BlockPos target, boolean reachesTarget) {
|
|
|
|
this.nodes = nodes;
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
2021-11-24 00:06:05 +01:00
|
|
|
index 219bdf53a860628335efe92d4f294a5fa52087b2..b0d348061487110993b6c4c8a7dc7208f27361b3 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
|
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
|
2021-08-25 09:59:26 +02:00
|
|
|
@@ -12,8 +12,11 @@ import org.bukkit.loot.LootTable;
|
2021-06-11 14:02:28 +02:00
|
|
|
public abstract class CraftMob extends CraftLivingEntity implements Mob {
|
|
|
|
public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) {
|
|
|
|
super(server, entity);
|
|
|
|
+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper
|
|
|
|
}
|
|
|
|
|
|
|
|
+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper
|
|
|
|
+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper
|
|
|
|
@Override
|
|
|
|
public void setTarget(LivingEntity target) {
|
2021-08-25 09:59:26 +02:00
|
|
|
Preconditions.checkState(!this.getHandle().generation, "Cannot set target during world generation");
|