From f3b58f561f37417a17ed2dd7827fcbbfbba995d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?= Date: Sun, 5 Apr 2020 13:01:13 +0800 Subject: [PATCH] Async pathfinder diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java index e9f00a1e1..72fa93d75 100644 --- a/src/main/java/net/minecraft/server/EntityInsentient.java +++ b/src/main/java/net/minecraft/server/EntityInsentient.java @@ -686,7 +686,7 @@ public abstract class EntityInsentient extends EntityLiving { this.goalSelector.doTick(); //this.world.getMethodProfiler().exit(); // Akarin - remove caller //this.world.getMethodProfiler().enter("navigation"); // Akarin - remove caller - this.navigation.c(); + this.navigation.tickAsync(); // Akarin - Async pathfinder //this.world.getMethodProfiler().exit(); // Akarin - remove caller //this.world.getMethodProfiler().enter("mob tick"); // Akarin - remove caller this.mobTick(); diff --git a/src/main/java/net/minecraft/server/Navigation.java b/src/main/java/net/minecraft/server/Navigation.java index abf450917..4f7f40d5e 100644 --- a/src/main/java/net/minecraft/server/Navigation.java +++ b/src/main/java/net/minecraft/server/Navigation.java @@ -183,7 +183,7 @@ public class Navigation extends NavigationAbstract { double d3 = (double) j2 + 0.5D - vec3d.z; if (d2 * d0 + d3 * d1 >= 0.0D) { - PathType pathtype = this.o.a(this.b, i2, j - 1, j2, this.a, l, i1, j1, true, true); + PathType pathtype = this.o.a(this.o.a, i2, j - 1, j2, this.a, l, i1, j1, true, true); // Akarin - use chunk cache if (pathtype == PathType.WATER) { return false; diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java index b763d7f37..e1f3baa7b 100644 --- a/src/main/java/net/minecraft/server/NavigationAbstract.java +++ b/src/main/java/net/minecraft/server/NavigationAbstract.java @@ -22,13 +22,15 @@ public abstract class NavigationAbstract { protected long j; protected double k; protected float l; - protected boolean m; + protected boolean m; public boolean needPathfind() { return m; } // Akarin - OBFHELPER protected long n; protected PathfinderAbstract o; - private BlockPosition q; + private BlockPosition q; public BlockPosition origin() { return q; } // Akarin - OBFHELPER private int r; private float s; private final Pathfinder t; public Pathfinder getPathfinder() { return this.t; } // Paper - OBFHELPER + private long lastPathfindAsync; // Akarin - Async pathfinder + private static final java.util.concurrent.ExecutorService pathfindExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("StarLink Pathfinder - %d").build()); // Akarin - Async pathfinder public NavigationAbstract(EntityInsentient entityinsentient, World world) { this.g = Vec3D.a; @@ -65,7 +67,7 @@ public abstract class NavigationAbstract { return this.m; } - public void j() { + public void doPathfind() { j(); } public void j() { // Akarin - OBFHELPER if (this.b.getTime() - this.n > 20L) { if (this.q != null) { this.c = null; @@ -78,6 +80,37 @@ public abstract class NavigationAbstract { } } + // Akarin Start - Async pathfinder + public void doPathfindAsync() { + if (this.b.getTime() - this.lastPathfindAsync > 20L) { + if (this.q != null) { + this.lastPathfindAsync = this.b.getTime(); + + float f = (float) this.p.getValue(); + BlockPosition blockposition = new BlockPosition(this.a); + int k = (int) (f + (float) 8); + ChunkCache cache = new ChunkCache(this.b, blockposition.b(-k, -k, -k), blockposition.b(k, k, k)); + + if (this.c != null && !this.c.b()) { + doTickAsync(this.c); + return; + } + + pathfindExecutor.execute(() -> { + PathEntity result = findPathAsync(cache, java.util.Collections.singleton(this.q), this.r); + NavigationAbstract.this.b.getMinecraftServer().processQueue.add(() -> { + if (result != null && result.k() != null) + this.q = result.k(); + + NavigationAbstract.this.c = result; + }); + }); + } + } else { + doTickAsync(this.c); + } + } + // Akarin End - Async pathfinder @Nullable 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 @@ -106,7 +139,7 @@ public abstract class NavigationAbstract { @Nullable // Paper start - Add target - protected PathEntity a(Set set, int i, boolean flag, int j) { + protected PathEntity findPath(Set set, int i, boolean flag, int j) { return a(set, 1, flag, j); } protected PathEntity a(Set set, int i, boolean flag, int j) { // Akarin - OBFHELPER return this.a(set, null, i, flag, j); } @Nullable protected PathEntity a(Set set, Entity target, int i, boolean flag, int j) { @@ -153,6 +186,17 @@ public abstract class NavigationAbstract { return pathentity; } } + // Akarin Start - Async pathfinder + protected PathEntity findPathAsync(ChunkCache cache, Set set, int j) { + if (this.a.locY() < 0.0D) { + return null; + } else if (!this.a()) { + return null; + } else { + return this.t.a(cache, this.a, set, f, j, this.s); + } + } + // Akarin End - Async pathfinder public boolean a(double d0, double d1, double d2, double d3) { return this.a(this.a(d0, d1, d2, 1), d3); @@ -217,7 +261,7 @@ public abstract class NavigationAbstract { return this.c; } - public void c() { + public void doTick() { c(); } public void c() { // Akarin - OBFHELPER ++this.e; if (this.m) { this.j(); @@ -246,6 +290,84 @@ public abstract class NavigationAbstract { } } } + // Akarin Start - Async pathfinder + public void tickAsync() { + ++this.e; + this.doPathfindAsync(); + } + + public void doTickAsync(PathEntity pathEntity) { + if (shouldContinuePathfind(pathEntity)) return; + + Vec3D vec3d; + + if (this.a()) { + applyUnitAsync(pathEntity); + } else if (pathEntity.f() < pathEntity.e()) { + vec3d = this.b(); + Vec3D vec3d1 = pathEntity.a(this.a, pathEntity.f()); + + if (vec3d.y > vec3d1.y && !this.a.onGround && MathHelper.floor(vec3d.x) == MathHelper.floor(vec3d1.x) && MathHelper.floor(vec3d.z) == MathHelper.floor(vec3d1.z)) { + pathEntity.c(pathEntity.f() + 1); + } + } + + // PacketDebug.a(this.b, this.a, pathEntity, this.l); + if (shouldContinuePathfind(pathEntity)) return; + + vec3d = pathEntity.a((Entity) this.a); + BlockPosition blockposition = new BlockPosition(vec3d); + + this.a.getControllerMove().a(vec3d.x, this.b.getType(blockposition.down()).isAir() ? vec3d.y : PathfinderNormal.a((IBlockAccess) this.b, blockposition), vec3d.z, this.d); + } + + protected void applyUnitAsync(PathEntity pathEntity) { + Vec3D vec3d = this.b(); + + this.l = this.a.getWidth() > 0.75F ? this.a.getWidth() / 2.0F : 0.75F - this.a.getWidth() / 2.0F; + Vec3D vec3d1 = pathEntity.g(); + + if (Math.abs(this.a.locX() - (vec3d1.x + 0.5D)) < (double) this.l && Math.abs(this.a.locZ() - (vec3d1.z + 0.5D)) < (double) this.l && Math.abs(this.a.locY() - vec3d1.y) < 1.0D) { + pathEntity.c(pathEntity.f() + 1); + } + + this.setUnitAsync(pathEntity, vec3d); + } + + protected void setUnitAsync(PathEntity pathEntity, Vec3D vec3d) { + if (this.e - this.f > 100) { + if (vec3d.distanceSquared(this.g) < 2.25D) { + this.o(); + } + + this.f = this.e; + this.g = vec3d; + } + + if (!pathEntity.b()) { + Vec3D vec3d1 = pathEntity.g(); + + if (vec3d1.equals(this.h)) { + this.i += SystemUtils.getMonotonicMillis() - this.j; + } else { + this.h = vec3d1; + double d0 = vec3d.f(this.h); + + this.k = this.a.dt() > 0.0F ? d0 / (double) this.a.dt() * 1000.0D : 0.0D; + } + + if (this.k > 0.0D && (double) this.i > this.k * 3.0D) { + this.h = Vec3D.a; + this.i = 0L; + this.k = 0.0D; + this.o(); + } + + this.j = SystemUtils.getMonotonicMillis(); + } + + } + // Akarin End - Async pathfinder protected void l() { Vec3D vec3d = this.b(); @@ -294,9 +416,14 @@ public abstract class NavigationAbstract { } - public boolean m() { + public boolean shouldContinuePathfind() { return m(); } public boolean m() { // Akarin - OBFHELPER return this.c == null || this.c.b(); } + // Akarin Start - Async pathfinder + public boolean shouldContinuePathfind(PathEntity pathEntity) { + return pathEntity == null || pathEntity.b(); + } + // Akarin End - Async pathfinder public boolean n() { return !this.m(); @@ -307,9 +434,9 @@ public abstract class NavigationAbstract { this.c = null; } - protected abstract Vec3D b(); + protected Vec3D getEntityPathfindUnit() { return b(); } protected abstract Vec3D b(); // Akarin - OBFHELPER - protected abstract boolean a(); + protected boolean canPathfind() { return a(); } protected abstract boolean a(); // Akarin - OBFHELPER protected boolean p() { return this.a.az() || this.a.aH(); diff --git a/src/main/java/net/minecraft/server/PathEntity.java b/src/main/java/net/minecraft/server/PathEntity.java index dcb4e2508..265b6df4f 100644 --- a/src/main/java/net/minecraft/server/PathEntity.java +++ b/src/main/java/net/minecraft/server/PathEntity.java @@ -110,7 +110,7 @@ public class PathEntity { return "Path(length=" + this.a.size() + ")"; } - public BlockPosition k() { + public BlockPosition origin() { return k(); } public BlockPosition k() { // Akarin - OBFHELPER return this.f; } diff --git a/src/main/java/net/minecraft/server/Pathfinder.java b/src/main/java/net/minecraft/server/Pathfinder.java index 67c63cfe3..00bd2327f 100644 --- a/src/main/java/net/minecraft/server/Pathfinder.java +++ b/src/main/java/net/minecraft/server/Pathfinder.java @@ -15,9 +15,9 @@ import javax.annotation.Nullable; public class Pathfinder { - private final Path a = new Path(); - private final Set b = Sets.newHashSet(); - private final PathPoint[] c = new PathPoint[32]; + private final Path a = new Path(); private Path nodePath() { return this.a; } // Akarin - OBFHELPER + private final Set b = Sets.newHashSet(); private Set nodesSet() { return this.b; } // Akarin - OBFHELPER + private final PathPoint[] c = new PathPoint[32]; private PathPoint[] pathNodes() { return this.c; } // Akarin - OBFHELPER private final int d; private final PathfinderAbstract e; public PathfinderAbstract getPathfinder() { return this.e; } // Paper - OBFHELPER @@ -26,8 +26,9 @@ public class Pathfinder { this.d = i; } + public PathEntity findPaths(ChunkCache chunkcache, EntityInsentient entityinsentient, Set set, float f, int i, float f1) { return a(chunkcache, entityinsentient, set, f, i, f1); } // Akarin - OBFHELPER @Nullable - public PathEntity a(ChunkCache chunkcache, EntityInsentient entityinsentient, Set set, float f, int i, float f1) { + public synchronized PathEntity a(ChunkCache chunkcache, EntityInsentient entityinsentient, Set set, float f, int i, float f1) { this.a.a(); this.e.a(chunkcache, entityinsentient); PathPoint pathpoint = this.e.b(); @@ -40,6 +41,7 @@ public class Pathfinder { return pathentity; } + private PathEntity findPaths0(PathPoint pathpoint, Map map, float f, int i, float f1) { return a(pathpoint, map, f, i, f1); } // Akarin - OBFHELPER @Nullable private PathEntity a(PathPoint pathpoint, Map map, float f, int i, float f1) { Set set = map.keySet(); @@ -117,6 +119,7 @@ public class Pathfinder { } } + private float getNearestDistance(PathPoint pathpoint, Set set) { return a(pathpoint, set); } // Akarin - OBFHELPER private float a(PathPoint pathpoint, Set set) { float f = Float.MAX_VALUE; @@ -132,6 +135,7 @@ public class Pathfinder { return f; } + private PathEntity gatherAssociatedNodes(PathPoint pathpoint, BlockPosition blockposition, boolean flag) { return a(pathpoint, blockposition, flag); } // Akarin - OBFHELPER private PathEntity a(PathPoint pathpoint, BlockPosition blockposition, boolean flag) { List list = Lists.newArrayList(); PathPoint pathpoint1 = pathpoint; diff --git a/src/main/java/net/minecraft/server/PathfinderTurtle.java b/src/main/java/net/minecraft/server/PathfinderTurtle.java index 59b1fe289..1790878ae 100644 --- a/src/main/java/net/minecraft/server/PathfinderTurtle.java +++ b/src/main/java/net/minecraft/server/PathfinderTurtle.java @@ -148,7 +148,7 @@ public class PathfinderTurtle extends PathfinderNormal { if (pathtype == PathType.OPEN) { AxisAlignedBB axisalignedbb = new AxisAlignedBB((double) i - d2 + 0.5D, (double) j + 0.001D, (double) k - d2 + 0.5D, (double) i + d2 + 0.5D, (double) ((float) j + this.b.getHeight()), (double) k + d2 + 0.5D); - if (!this.b.world.getCubes(this.b, axisalignedbb)) { + if (!this.a.getCubes(this.b, axisalignedbb)) { // Akarin - use chunk cache return null; } diff --git a/src/main/java/net/minecraft/server/PathfinderWater.java b/src/main/java/net/minecraft/server/PathfinderWater.java index 075b63ef5..a3473ddcf 100644 --- a/src/main/java/net/minecraft/server/PathfinderWater.java +++ b/src/main/java/net/minecraft/server/PathfinderWater.java @@ -63,7 +63,7 @@ public class PathfinderWater extends PathfinderAbstract { @Override protected PathPoint a(int i, int j, int k) { PathPoint pathpoint = null; - PathType pathtype = this.a(this.b.world, i, j, k); + PathType pathtype = this.a(this.a, i, j, k); // Akarin - use chunk cache float f = this.b.a(pathtype); if (f >= 0.0F) { -- 2.25.1.windows.1