diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 42f226e79..b9bbd65e7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -520,7 +520,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } 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.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); this.timeLastCacheCull = now; } diff --git a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java index 8a07b96e5..b81a6aed5 100644 --- a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java +++ b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java @@ -25,15 +25,17 @@ import dev.babbaj.pathfinder.Octree; */ public final class BlockStateOctreeInterface { - private final long context; - private long chunkPtr; + private final NetherPathfinderContext context; + private final long contextPtr; + volatile long chunkPtr; // Guarantee that the first lookup will fetch the context by setting MAX_VALUE private int prevChunkX = Integer.MAX_VALUE; private int prevChunkZ = Integer.MAX_VALUE; public BlockStateOctreeInterface(final NetherPathfinderContext context) { - this.context = context.context; + this.context = context; + this.contextPtr = context.context; } public boolean get0(final int x, final int y, final int z) { @@ -42,11 +44,14 @@ public final class BlockStateOctreeInterface { } final int chunkX = x >> 4; final int chunkZ = z >> 4; - if (((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { + long pointer = this.chunkPtr; + if (pointer == 0 | ((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { this.prevChunkX = chunkX; this.prevChunkZ = chunkZ; - this.chunkPtr = NetherPathfinder.getOrCreateChunk(this.context, chunkX, chunkZ); + synchronized (this.context.cacheLock) { + this.chunkPtr = pointer = NetherPathfinder.getOrCreateChunk(this.contextPtr, chunkX, chunkZ); + } } - return Octree.getBlock(this.chunkPtr, x & 0xF, y & 0x7F, z & 0xF); + return Octree.getBlock(pointer, x & 0xF, y & 0x7F, z & 0xF); } } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index e0eb7de0b..ebe563374 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -45,6 +45,7 @@ import java.util.concurrent.TimeUnit; public final class NetherPathfinderContext { private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); + public final Object cacheLock = new Object(); // Visible for access in BlockStateOctreeInterface final long context; @@ -57,8 +58,13 @@ public final class NetherPathfinderContext { this.executor = Executors.newSingleThreadExecutor(); } - public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks) { - this.executor.execute(() -> NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks)); + public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { + this.executor.execute(() -> { + synchronized (this.cacheLock) { + boi.chunkPtr = 0L; + NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks); + } + }); } public void queueForPacking(final Chunk chunkIn) {