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..9a3edd114c4736b1843844c6ca49da7aea7983d1 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java @@ -0,0 +1,141 @@ +package com.destroystokyo.paper.entity; + +import net.minecraft.world.entity.EntityInsentient; +import net.minecraft.world.level.pathfinder.PathEntity; +import net.minecraft.world.level.pathfinder.PathPoint; +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 java.util.ArrayList; +import java.util.List; + +public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { + + private final EntityInsentient entity; + + public PaperPathfinder(EntityInsentient 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() { + PathEntity 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"); + PathEntity 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"); + PathEntity 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"); + PathEntity 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 PathEntity path; + PaperPathResult(PathEntity path) { + this.path = path; + } + + @Nullable + @Override + public Location getFinalPoint() { + PathPoint point = path.getFinalPoint(); + return point != null ? toLoc(point) : null; + } + + @Override + public List getPoints() { + List points = new ArrayList<>(); + for (PathPoint 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(PathPoint point) { + return new Location(entity.world.getWorld(), point.getX(), point.getY(), point.getZ()); + } +} diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java index d134333c736dc1ee1c722d680d7a9c22c1b265bd..06d05b511d623d0247d44989bee85b383a8fb52f 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java @@ -100,7 +100,7 @@ public abstract class NavigationAbstract { } @Nullable - public final PathEntity a(double d0, double d1, double d2, int i) { + public final PathEntity calculateDestination(double d0, double d1, double d2) { return a(d0, d1, d2, 0); } public final PathEntity a(double d0, double d1, double d2, int i) { // Paper - OBFHELPER return this.a(new BlockPosition(d0, d1, d2), i); } @@ -125,7 +125,7 @@ public abstract class NavigationAbstract { } @Nullable - public PathEntity a(Entity entity, int i) { + public final PathEntity calculateDestination(Entity entity) { return a(entity, 0); } public PathEntity a(Entity entity, int i) { return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper } @@ -190,6 +190,7 @@ public abstract class NavigationAbstract { return pathentity != null && this.a(pathentity, d0); } + public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER public boolean a(@Nullable PathEntity pathentity, double d0) { if (pathentity == null) { this.c = null; @@ -217,7 +218,7 @@ public abstract class NavigationAbstract { } } - @Nullable + @Nullable public PathEntity getPathEntity() { return k(); } @Nullable // Paper - OBFHELPER public PathEntity k() { return this.c; } @@ -341,6 +342,7 @@ public abstract class NavigationAbstract { return !this.m(); } + public void stopPathfinding() { o(); } // Paper - OBFHELPER public void o() { this.c = null; } diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java index 606027de777750f6d2ab0d7f1ef387ed4f0c6092..81c3cb9da3f901d2bcf384f7113bdc5c60f9962f 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java @@ -8,13 +8,14 @@ import net.minecraft.world.phys.Vec3D; public class PathEntity { - private final List a; + private final List a; public List getPoints() { return a; } // Paper - OBFHELPER private PathPoint[] b = new PathPoint[0]; private PathPoint[] c = new PathPoint[0]; - private int e; + private int e; public int getNextIndex() { return this.e; } // Paper - OBFHELPER private final BlockPosition f; private final float g; private final boolean h; + public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper public PathEntity(List list, BlockPosition blockposition, boolean flag) { this.a = list; @@ -36,7 +37,7 @@ public class PathEntity { } @Nullable - public PathPoint d() { + public PathPoint getFinalPoint() { return d(); } @Nullable public PathPoint d() { // Paper - OBFHELPER return !this.a.isEmpty() ? (PathPoint) this.a.get(this.a.size() - 1) : null; } @@ -84,7 +85,7 @@ public class PathEntity { return this.a(entity, this.e); } - public BlockPosition g() { + public BlockPosition getNext() { return g(); } public BlockPosition g() { // Paper - OBFHELPER return ((PathPoint) this.a.get(this.e)).a(); } diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java index 43cc9430972a18cbf03a590d576ed200e3836017..c260b0ca70cb18811158761c574aee9c3166da28 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java @@ -5,9 +5,9 @@ import net.minecraft.util.MathHelper; public class PathPoint { - public final int a; - public final int b; - public final int c; + public final int a; public final int getX() { return a; } // Paper - OBFHELPER + public final int b; public final int getY() { return b; } // Paper - OBFHELPER + public final int c; public final int getZ() { return c; } // Paper - OBFHELPER private final int m; public int d = -1; public float e; diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java index f2080bd50db04af6eabec4b4b757d6dadfb1a2f5..88be03bd77656235322522c3782b9f9a878b86b1 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java @@ -16,9 +16,9 @@ public abstract class PathfinderAbstract { protected int d; protected int e; protected int f; - protected boolean g; - protected boolean h; - protected boolean i; + protected boolean g; public boolean shouldPassDoors() { return g; } public void setShouldPassDoors(boolean b) { g = b; } // Paper - obfhelper + protected boolean h; public boolean shouldOpenDoors() { return h; } public void setShouldOpenDoors(boolean b) { h = b; } // Paper - obfhelper + protected boolean i; public boolean shouldFloat() { return i; } public void setShouldFloat(boolean b) { i = b; } // Paper - obfhelper public PathfinderAbstract() {} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java index eb275ac45def34d5bb1ed696b4f6a4d53d282ab3..28a4e90130f51fd2fda7003fde5b4d0a410e1aef 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -12,8 +12,11 @@ import org.bukkit.loot.LootTable; public abstract class CraftMob extends CraftLivingEntity implements Mob { public CraftMob(CraftServer server, EntityInsentient 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) { EntityInsentient entity = getHandle();