From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar 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 index 0000000000000000000000000000000000000000..92d1bb8b9cdb9eb0c04574c0b6ba5acdca9fb377 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java @@ -0,0 +1,139 @@ +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() { + entity.getNavigation().stopPathfinding(); + } + + @Override + public boolean hasPath() { + return entity.getNavigation().getPathEntity() != null; + } + + @Nullable + @Override + public PathResult getCurrentPath() { + Path path = entity.getNavigation().getPathEntity(); + return path != null ? new PaperPathResult(path) : null; + } + + @Nullable + @Override + public PathResult findPath(Location loc) { + Validate.notNull(loc, "Location can not be null"); + Path path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); + return path != null ? new PaperPathResult(path) : null; + } + + @Nullable + @Override + public PathResult findPath(LivingEntity target) { + Validate.notNull(target, "Target can not be null"); + Path path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); + 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; + return entity.getNavigation().setDestination(pathEntity, speed); + } + + @Override + public boolean canOpenDoors() { + return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); + } + + @Override + public void setCanOpenDoors(boolean canOpenDoors) { + entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); + } + + @Override + public boolean canPassDoors() { + return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); + } + + @Override + public void setCanPassDoors(boolean canPassDoors) { + entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); + } + + @Override + public boolean canFloat() { + return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); + } + + @Override + public void setCanFloat(boolean canFloat) { + entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); + } + + 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() { + Node point = path.getFinalPoint(); + return point != null ? toLoc(point) : null; + } + + @Override + public List getPoints() { + List points = new ArrayList<>(); + for (Node point : path.getPoints()) { + points.add(toLoc(point)); + } + return points; + } + + @Override + public int getNextPointIndex() { + return path.getNextIndex(); + } + + @Nullable + @Override + public Location getNextPoint() { + if (!path.hasNext()) { + return null; + } + return toLoc(path.getPoints().get(path.getNextIndex())); + } + } + + private Location toLoc(Node point) { + return new Location(entity.level.getWorld(), point.getX(), point.getY(), point.getZ()); + } +} diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java index 8212aab2884c2a894bc981850e483ce31814c708..69edca1ef95c37b11fe3f793e6a8f8a674bd7f6f 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java @@ -93,7 +93,7 @@ public abstract class PathNavigation { } @Nullable - public final Path createPath(double x, double y, double z, int distance) { + public final Path calculateDestination(double d0, double d1, double d2) { return createPath(d0, d1, d2, 0); } public final Path createPath(double x, double y, double z, int distance) { // Paper - OBFHELPER return this.createPath(new BlockPos(x, y, z), distance); } @@ -123,7 +123,7 @@ public abstract class PathNavigation { } @Nullable - public Path createPath(Entity entity, int distance) { + public final Path calculateDestination(Entity entity) { return createPath(entity, 0); } public Path createPath(Entity entity, int distance) { return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper } @@ -195,6 +195,7 @@ public abstract class PathNavigation { return path != null && this.moveTo(path, speed); } + public boolean setDestination(@Nullable Path pathentity, double speed) { return moveTo(pathentity, speed); } // Paper - OBFHELPER public boolean moveTo(@Nullable Path path, double speed) { if (path == null) { this.path = null; @@ -221,7 +222,7 @@ public abstract class PathNavigation { } } - @Nullable + @Nullable public Path getPathEntity() { return getPath(); } @Nullable // Paper - OBFHELPER public Path getPath() { return this.path; } @@ -335,6 +336,7 @@ public abstract class PathNavigation { return !this.isDone(); } + public void stopPathfinding() { stop(); } // Paper - OBFHELPER public void stop() { this.path = null; } diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Node.java b/src/main/java/net/minecraft/world/level/pathfinder/Node.java index d7a86444d0e76154319c409317fc5ac9c54403a8..328f050ae68e0b42690f05e5995fb2711b8cf46d 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/Node.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/Node.java @@ -6,9 +6,9 @@ import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; public class Node { - public final int x; - public final int y; - public final int z; + public final int x; public final int getX() { return x; } // Paper - OBFHELPER + public final int y; public final int getY() { return y; } // Paper - OBFHELPER + public final int z; public final int getZ() { return z; } // Paper - OBFHELPER private final int hash; public int heapIdx = -1; public float g; diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java index 72ca8adb9fa65588c6b1e19be2dc27a36c0146a6..e5bfd9ade1a49e11afd4a49784a0874654945709 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java @@ -15,9 +15,9 @@ public abstract class NodeEvaluator { protected int entityWidth; protected int entityHeight; protected int entityDepth; - protected boolean canPassDoors; - protected boolean canOpenDoors; - protected boolean canFloat; + protected boolean canPassDoors; public boolean shouldPassDoors() { return canPassDoors; } public void setShouldPassDoors(boolean b) { canPassDoors = b; } // Paper - obfhelper + protected boolean canOpenDoors; public boolean shouldOpenDoors() { return canOpenDoors; } public void setShouldOpenDoors(boolean b) { canOpenDoors = b; } // Paper - obfhelper + protected boolean canFloat; public boolean shouldFloat() { return canFloat; } public void setShouldFloat(boolean b) { canFloat = b; } // Paper - obfhelper public void prepare(PathNavigationRegion cachedWorld, Mob entity) { this.level = cachedWorld; diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java index 6928c415e328dd7cff2e9ec553bc4faa1ff8facf..e95312e5b0f0200178cbe1a61b3629dfeac55b4a 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java @@ -12,14 +12,15 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; public class Path { - private final List nodes; + private final List nodes; public List getPoints() { return nodes; } // Paper - OBFHELPER private Node[] openSet = new Node[0]; private Node[] closedSet = new Node[0]; private Set targetNodes; - private int nextNodeIndex; + private int nextNodeIndex; public int getNextIndex() { return this.nextNodeIndex; } // Paper - OBFHELPER private final BlockPos target; private final float distToTarget; private final boolean reached; + public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper public Path(List nodes, BlockPos target, boolean reachesTarget) { this.nodes = nodes; @@ -41,7 +42,7 @@ public class Path { } @Nullable - public Node getEndNode() { + public Node getFinalPoint() { return getEndNode(); } @Nullable public Node getEndNode() { // Paper - OBFHELPER return !this.nodes.isEmpty() ? this.nodes.get(this.nodes.size() - 1) : null; } @@ -88,7 +89,7 @@ public class Path { return this.getEntityPosAtNode(entity, this.nextNodeIndex); } - public BlockPos getNextNodePos() { + public BlockPos getNext() { return getNextNodePos(); } public BlockPos getNextNodePos() { // Paper - OBFHELPER return this.nodes.get(this.nextNodeIndex).asBlockPos(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java index 71872fdfafca82cf745eecee4bf984726d49f5a4..9c9fa83615cd06539ce5e4e3d4feaa69f65b7931 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -11,8 +11,11 @@ import org.bukkit.loot.LootTable; 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) { net.minecraft.world.entity.Mob entity = this.getHandle();