From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: tsao chi <tsao-chi@the-lingo.org>
Date: Sun, 2 Aug 2020 12:25:52 -0500
Subject: [PATCH] Akarin updated Async Path Finding

Co-authored-by: Bud Gidiere <sgidiere@gmail.com>

diff --git a/src/main/java/net/minecraft/server/Navigation.java b/src/main/java/net/minecraft/server/Navigation.java
index 0ed01f40edfdbeeeea9db55fcba7501ee597c1fb..795fd9308dcd9edce4ef12da2e8bc5a65f358abc 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 (!this.a(pathtype)) {
                             return false;
diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java
index ed37caf036ef9ae4c39622caf9b582678fecdccf..d1306caa5f98cd6b3fc0614dc6a4edeb0ad6a53a 100644
--- a/src/main/java/net/minecraft/server/NavigationAbstract.java
+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java
@@ -28,6 +28,15 @@ public abstract class NavigationAbstract {
     private int q;
     private float r;
     private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER
+    // Akarin start - Async pathfinder
+    private long lastPathfindAsync;
+    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 end
 
     // Tuinity start
     public boolean isViableForPathRecalculationChecking() {
@@ -36,6 +45,128 @@ public abstract class NavigationAbstract {
     }
     // Tuinity end
 
+    // Akarin start - Async pathfinder, copied from above with modification
+    public void doPathfindAsync() {
+        if (this.b.getTime() - this.lastPathfindAsync > 20L) {
+            if (this.p != null) {
+                this.lastPathfindAsync = this.b.getTime();
+
+                // Baeke chunk cache
+                float f = (float) this.a.b(GenericAttributes.FOLLOW_RANGE);
+                BlockPosition blockposition = this.a.getChunkCoordinates();
+                int k = (int) (f + (float) 8);
+                ChunkCache chunkCache = 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(chunkCache, java.util.Collections.singleton(this.p), this.q);
+                    NavigationAbstract.this.b.getMinecraftServer().processQueue.add(() -> {
+                        if (result != null && result.m() != null) {
+                            this.p = result.m();
+                        }
+
+                        NavigationAbstract.this.c = result;
+                    });
+                });
+            }
+        } else {
+            doTickAsync(this.c);
+        }
+    }
+
+    protected PathEntity findPathAsync(ChunkCache cache, Set<BlockPosition> set, int j) {
+        if (this.a.locY() < 0.0D) {
+            return null;
+        } else if (!this.a()) {
+            return null;
+        } else {
+            return this.s.a(cache, this.a, set, f, j, this.r);
+        }
+    }
+
+    public static boolean shouldContinuePathfind(PathEntity pathEntity) {
+        return pathEntity == null || pathEntity.b();
+    }
+
+    public void doTickAsync(PathEntity pathEntity) {
+        if (shouldContinuePathfind(pathEntity)) {
+            return;
+        }
+
+        Vec3D vec3d;
+        if (this.a()) {
+            this.applyPath(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.isOnGround() && MathHelper.floor(vec3d.x) == MathHelper.floor(vec3d1.x) && MathHelper.floor(vec3d.z) == MathHelper.floor(vec3d1.z)) {
+                pathEntity.c(pathEntity.f() + 1);
+            }
+        }
+
+        if (shouldContinuePathfind(pathEntity)) {
+            return;
+        }
+        vec3d = pathEntity.a(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 applyPath(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;
+        BaseBlockPosition baseBlockPosition = pathEntity.g();
+        double d0 = Math.abs(this.a.locX() - ((double) baseBlockPosition.getX() + 0.5));
+        double d1 = Math.abs(this.a.locY() - ((double) baseBlockPosition.getY()));
+        double d2 = Math.abs(this.a.locZ() - ((double) baseBlockPosition.getZ() + 0.5));
+        boolean flag = d0 < (double) this.l && d2 < (double) this.l && d1 < 1.0D;
+
+        if (flag || this.a.b(pathEntity.h().l) && this.b(vec3d)) {
+            pathEntity.c(pathEntity.f() + 1);
+        }
+
+        this.applyPath0(pathEntity, vec3d);
+    }
+
+    protected void applyPath0(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()) {
+            BaseBlockPosition baseblockposition = pathEntity.g();
+
+            if (baseblockposition.equals(this.h)) {
+                this.i += SystemUtils.getMonotonicMillis() - this.j;
+            } else {
+                this.h = baseblockposition;
+                double d0 = vec3d.f(Vec3D.c(this.h));
+
+                this.k = this.a.dM() > 0.0F ? d0 / (double) this.a.dM() * 1000.0D : 0.0D;
+            }
+
+            if (this.k > 0.0D && (double) this.i > this.k * 3.0D) {
+                this.e();
+                this.o();
+            }
+
+            this.j = SystemUtils.getMonotonicMillis();
+        }
+
+    }
+    // Akarin end
+
     public NavigationAbstract(EntityInsentient entityinsentient, World world) {
         this.g = Vec3D.a;
         this.h = BaseBlockPosition.ZERO;
@@ -230,6 +361,8 @@ public abstract class NavigationAbstract {
 
     public void c() {
         ++this.e;
+        this.doPathfindAsync(); // Akarin
+        /* // Akarin
         if (this.m) {
             this.j();
         }
@@ -256,6 +389,7 @@ public abstract class NavigationAbstract {
                 this.a.getControllerMove().a(vec3d.x, this.b.getType(blockposition.down()).isAir() ? vec3d.y : PathfinderNormal.a((IBlockAccess) this.b, blockposition), vec3d.z, this.d);
             }
         }
+         */ // Akarin
     }
 
     protected void l() {
diff --git a/src/main/java/net/minecraft/server/NavigationFlying.java b/src/main/java/net/minecraft/server/NavigationFlying.java
index 013bdfe5540ae594a7f9cbe3ef8dc54dfb25afd4..d9460cdb87a87450269c468857f0e87947de8861 100644
--- a/src/main/java/net/minecraft/server/NavigationFlying.java
+++ b/src/main/java/net/minecraft/server/NavigationFlying.java
@@ -28,6 +28,7 @@ public class NavigationFlying extends NavigationAbstract {
         return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity
     }
 
+    /* // Akarin
     @Override
     public void c() {
         ++this.e;
@@ -54,6 +55,7 @@ public class NavigationFlying extends NavigationAbstract {
             }
         }
     }
+     */ // Akarin
 
     @Override
     protected boolean a(Vec3D vec3d, Vec3D vec3d1, int i, int j, int k) {
diff --git a/src/main/java/net/minecraft/server/Pathfinder.java b/src/main/java/net/minecraft/server/Pathfinder.java
index 997982136cdd2a0d922e501473e0d4d1aabf567a..9b2d23ef1c9369cf15f9f12161c28199fbf4f373 100644
--- a/src/main/java/net/minecraft/server/Pathfinder.java
+++ b/src/main/java/net/minecraft/server/Pathfinder.java
@@ -26,7 +26,7 @@ public class Pathfinder {
     }
 
     @Nullable
-    public PathEntity a(ChunkCache chunkcache, EntityInsentient entityinsentient, Set<BlockPosition> set, float f, int i, float f1) {
+    public synchronized PathEntity a(ChunkCache chunkcache, EntityInsentient entityinsentient, Set<BlockPosition> set, float f, int i, float f1) { // Akarin - synchronized
         this.d.a();
         this.c.a(chunkcache, entityinsentient);
         PathPoint pathpoint = this.c.b();
diff --git a/src/main/java/net/minecraft/server/PathfinderTurtle.java b/src/main/java/net/minecraft/server/PathfinderTurtle.java
index e8aca88284dff6055de6d45e2a50bb28b7a64297..d8dd3aeedee76eaa828bb751dbcdff4c290c66da 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 fba6692a1e537b90e20aa448567c0ad6db653332..d576edc8c30288e98aeda8f1cb561b22c6b37536 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) {
