From b4780ca17ee6dd1267a73e9624e891b182de6f39 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 16 Jul 2023 18:54:58 -0500 Subject: [PATCH 1/4] based --- .../elytra/NetherPathfinderContext.java | 228 +++++++++++++++++- 1 file changed, 223 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index ebe563374..37c226bdd 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -17,6 +17,7 @@ package baritone.behavior.elytra; +import baritone.Baritone; import baritone.api.event.events.BlockChangeEvent; import baritone.utils.accessor.IBitArray; import baritone.utils.accessor.IBlockStateContainer; @@ -33,11 +34,13 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import javax.annotation.Nonnull; import java.lang.ref.SoftReference; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Stream; /** * @author Brady @@ -55,7 +58,7 @@ public final class NetherPathfinderContext { public NetherPathfinderContext(long seed) { this.context = NetherPathfinder.newContext(seed); this.seed = seed; - this.executor = Executors.newSingleThreadExecutor(); + this.executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new WorkQueue()); } public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { @@ -223,6 +226,221 @@ private static void writeChunkData(Chunk chunk, long ptr) { } } + private static final class WorkQueue extends TrollBlockingQueue { + + private final ConcurrentLinkedDeque path; + private final ConcurrentLinkedDeque chunk; + + private final ReentrantLock takeLock = new ReentrantLock(); + private final ReentrantLock putLock = new ReentrantLock(); + private final Condition notEmpty = takeLock.newCondition(); + + public WorkQueue() { + this.path = new ConcurrentLinkedDeque<>(); + this.chunk = new ConcurrentLinkedDeque<>(); + } + + private void signalNotEmpty() { + final ReentrantLock takeLock = this.takeLock; + takeLock.lock(); + try { + this.notEmpty.signal(); + } finally { + takeLock.unlock(); + } + } + + @Override + public boolean offer(@Nonnull Runnable runnable) { + final ReentrantLock putLock = this.putLock; + putLock.lock(); + try { + if (runnable instanceof ForkJoinTask) { + this.path.offer(runnable); + } else { + // Put new chunks at the head of the queue + this.chunk.offerFirst(runnable); + // Purge oldest chunks + while (this.chunk.size() > Baritone.settings().chunkPackerQueueMaxSize.value) { + this.chunk.removeLast(); + } + } + } finally { + putLock.unlock(); + } + signalNotEmpty(); + return true; + } + + @Override + public Runnable take() throws InterruptedException { + Runnable x; + final ReentrantLock takeLock = this.takeLock; + takeLock.lockInterruptibly(); + try { + while (size() == 0) { + notEmpty.await(); + } + x = dequeue(); + if (!isEmpty()) { + notEmpty.signal(); + } + } finally { + takeLock.unlock(); + } + return x; + } + + @Override + public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException { + Runnable x; + long nanos = unit.toNanos(timeout); + final ReentrantLock takeLock = this.takeLock; + takeLock.lockInterruptibly(); + try { + while (isEmpty()) { + if (nanos <= 0) + return null; + nanos = notEmpty.awaitNanos(nanos); + } + x = dequeue(); + if (!isEmpty()) + notEmpty.signal(); + } finally { + takeLock.unlock(); + } + return x; + } + + @Override + public boolean remove(Object o) { + takeLock.lock(); + putLock.lock(); + try { + return this.path.remove(o) || this.chunk.remove(o); + } finally { + takeLock.unlock(); + putLock.unlock(); + } + } + + @Override + public int drainTo(Collection c) { + final ReentrantLock takeLock = this.takeLock; + takeLock.lock(); + int n = size(); + try { + if (!this.path.isEmpty()) { + c.add(this.path.remove()); + } + if (!this.chunk.isEmpty()) { + c.add(this.chunk.remove()); + } + } finally { + takeLock.unlock(); + } + return n; + } + + @Override + public int size() { + takeLock.lock(); + putLock.lock(); + try { + return this.path.size() + this.chunk.size(); + } finally { + takeLock.unlock(); + putLock.unlock(); + } + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @SuppressWarnings("unchecked") + @Override + public synchronized @Nonnull T[] toArray(@Nonnull T[] a) { + takeLock.lock(); + putLock.lock(); + try { + return (T[]) Stream.concat(this.path.stream(), this.chunk.stream()).toArray(Runnable[]::new); + } finally { + takeLock.unlock(); + putLock.unlock(); + } + } + + private Runnable dequeue() { + return !this.path.isEmpty() ? this.path.remove() : this.chunk.remove(); + } + } + + @SuppressWarnings("NullableProblems") + private static class TrollBlockingQueue extends AbstractQueue implements BlockingQueue { + + @Override + public Iterator iterator() { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + throw new UnsupportedOperationException(); + } + + @Override + public void put(T t) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean offer(T t, long timeout, TimeUnit unit) { + throw new UnsupportedOperationException(); + } + + @Override + public T take() throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public T poll(long timeout, TimeUnit unit) throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public int remainingCapacity() { + throw new UnsupportedOperationException(); + } + + @Override + public int drainTo(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int drainTo(Collection c, int maxElements) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean offer(T t) { + throw new UnsupportedOperationException(); + } + + @Override + public T poll() { + throw new UnsupportedOperationException(); + } + + @Override + public T peek() { + throw new UnsupportedOperationException(); + } + } + public static final class Visibility { public static final int ALL = 0; From 839ddaf85e8beed5767c96e9efd071989eab3829 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 16 Jul 2023 18:55:14 -0500 Subject: [PATCH 2/4] hack fix babij trolle --- src/main/java/baritone/behavior/ElytraBehavior.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b9bbd65e7..c54a0eb2c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -518,10 +518,13 @@ public void onTick(final TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { return; } - final long now = System.currentTimeMillis(); - if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { - this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); - this.timeLastCacheCull = now; + + if (this.context != null && this.boi != null) { + final long now = System.currentTimeMillis(); + if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { + this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); + this.timeLastCacheCull = now; + } } // Fetch the previous solution, regardless of if it's going to be used From 19b66903d0e4f787f669ecf94c49ca2abc54f1a7 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 16 Jul 2023 18:58:13 -0500 Subject: [PATCH 3/4] move cull code --- .../java/baritone/behavior/ElytraBehavior.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index c54a0eb2c..0ad6ad62d 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -519,14 +519,6 @@ public void onTick(final TickEvent event) { return; } - if (this.context != null && this.boi != null) { - final long now = System.currentTimeMillis(); - if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { - this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); - this.timeLastCacheCull = now; - } - } - // Fetch the previous solution, regardless of if it's going to be used this.pendingSolution = null; if (this.solver != null) { @@ -597,6 +589,12 @@ public void onTick(final TickEvent event) { Math.max(playerNear - 30, 0), Math.min(playerNear + 100, path.size()) ); + + final long now = System.currentTimeMillis(); + if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { + this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); + this.timeLastCacheCull = now; + } } /** From 3873aae7100926913536ec5f9c03f8f88e8d5f65 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 16 Jul 2023 19:14:44 -0500 Subject: [PATCH 4/4] surely this is ok --- .../baritone/behavior/elytra/NetherPathfinderContext.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 37c226bdd..2fd5066ca 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -228,16 +228,16 @@ private static void writeChunkData(Chunk chunk, long ptr) { private static final class WorkQueue extends TrollBlockingQueue { - private final ConcurrentLinkedDeque path; - private final ConcurrentLinkedDeque chunk; + private final LinkedList path; + private final LinkedList chunk; private final ReentrantLock takeLock = new ReentrantLock(); private final ReentrantLock putLock = new ReentrantLock(); private final Condition notEmpty = takeLock.newCondition(); public WorkQueue() { - this.path = new ConcurrentLinkedDeque<>(); - this.chunk = new ConcurrentLinkedDeque<>(); + this.path = new LinkedList<>(); + this.chunk = new LinkedList<>(); } private void signalNotEmpty() {