This commit is contained in:
Leijurv 2023-07-16 18:17:15 -07:00
parent a83d1901f2
commit 0e567f2f90
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
1 changed files with 44 additions and 32 deletions

View File

@ -34,10 +34,7 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/** /**
* @author Brady * @author Brady
@ -50,12 +47,15 @@ public final class NetherPathfinderContext {
// Visible for access in BlockStateOctreeInterface // Visible for access in BlockStateOctreeInterface
final long context; final long context;
private final long seed; private final long seed;
private final ExecutorService executor; private final ThreadPoolExecutor executor;
private final ExecutorService executorHighPriority;
public NetherPathfinderContext(long seed) { public NetherPathfinderContext(long seed) {
this.context = NetherPathfinder.newContext(seed); this.context = NetherPathfinder.newContext(seed);
this.seed = seed; this.seed = seed;
this.executor = Executors.newSingleThreadExecutor();
this.executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
this.executorHighPriority = Executors.newSingleThreadExecutor();
} }
public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) {
@ -68,46 +68,58 @@ public final class NetherPathfinderContext {
} }
public void queueForPacking(final Chunk chunkIn) { public void queueForPacking(final Chunk chunkIn) {
if (this.executor.getQueue().size() > 50000) {
return;
}
final SoftReference<Chunk> ref = new SoftReference<>(chunkIn); final SoftReference<Chunk> ref = new SoftReference<>(chunkIn);
this.executor.execute(() -> { this.executor.execute(() -> {
// TODO: Prioritize packing recent chunks and/or ones that the path goes through, synchronized (this.cacheLock) {
// and prune the oldest chunks per chunkPackerQueueMaxSize // TODO: Prioritize packing recent chunks and/or ones that the path goes through,
final Chunk chunk = ref.get(); // and prune the oldest chunks per chunkPackerQueueMaxSize
if (chunk != null) { final Chunk chunk = ref.get();
long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z); if (chunk != null) {
writeChunkData(chunk, ptr); long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z);
writeChunkData(chunk, ptr);
}
} }
}); });
} }
public void queueBlockUpdate(BlockChangeEvent event) { public void queueBlockUpdate(BlockChangeEvent event) {
if (this.executor.getQueue().size() > 50000) {
return;
}
this.executor.execute(() -> { this.executor.execute(() -> {
ChunkPos chunkPos = event.getChunkPos(); synchronized (this.cacheLock) {
long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z); ChunkPos chunkPos = event.getChunkPos();
if (ptr == 0) return; // this shouldn't ever happen long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z);
event.getBlocks().forEach(pair -> { if (ptr == 0) return; // this shouldn't ever happen
BlockPos pos = pair.first(); event.getBlocks().forEach(pair -> {
if (pos.getY() >= 128) return; BlockPos pos = pair.first();
boolean isSolid = pair.second() != AIR_BLOCK_STATE; if (pos.getY() >= 128) return;
Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid); boolean isSolid = pair.second() != AIR_BLOCK_STATE;
}); Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid);
});
}
}); });
} }
public CompletableFuture<PathSegment> pathFindAsync(final BlockPos src, final BlockPos dst) { public CompletableFuture<PathSegment> pathFindAsync(final BlockPos src, final BlockPos dst) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
final PathSegment segment = NetherPathfinder.pathFind( synchronized (this.cacheLock) {
this.context, final PathSegment segment = NetherPathfinder.pathFind(
src.getX(), src.getY(), src.getZ(), this.context,
dst.getX(), dst.getY(), dst.getZ(), src.getX(), src.getY(), src.getZ(),
true, dst.getX(), dst.getY(), dst.getZ(),
10000 true,
); 10000
if (segment == null) { );
throw new PathCalculationException("Path calculation failed"); if (segment == null) {
throw new PathCalculationException("Path calculation failed");
}
return segment;
} }
return segment; }, this.executorHighPriority);
}, this.executor);
} }
/** /**