Uses better approach #313

This uses CompleteableFutures instead of a recurring Bukkit task to
check if collections have been removed. This is a much more reliable way
to do it because it will complete when all the tasks are done and not
before.
This commit is contained in:
tastybento 2024-05-31 17:59:56 -07:00
parent 7a241f898d
commit c3e03a4f59

View File

@ -608,42 +608,32 @@ public class IslandLevelCalculator {
// Done
pipeliner.getInProcessQueue().remove(this);
// Chunk finished
// This was the last chunk
handleStackedBlocks();
handleChests();
long checkTime = System.currentTimeMillis();
finishTask = Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> {
// Check every half second if all the chests and stacks have been cleared
if ((chestBlocks.isEmpty() && stackedBlocks.isEmpty())
|| System.currentTimeMillis() - checkTime > MAX_AMOUNT) {
// This was the last chunk. Handle stacked blocks, then chests and exit
handleStackedBlocks().thenCompose(v -> handleChests()).thenRun(() -> {
this.tidyUp();
this.getR().complete(getResults());
finishTask.cancel();
}
}, 0, 10L);
});
}
});
}
private void handleChests() {
Iterator<Chunk> it = chestBlocks.iterator();
while (it.hasNext()) {
Chunk v = it.next();
Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> {
private CompletableFuture<Void> handleChests() {
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (Chunk v : chestBlocks) {
CompletableFuture<Void> future = Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> {
scanChests(c);
it.remove();
});
futures.add(future);
}
// Return a CompletableFuture that completes when all futures are done
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
}
private void handleStackedBlocks() {
private CompletableFuture<Void> handleStackedBlocks() {
// Deal with any stacked blocks
List<Location> toRemove = new ArrayList<>();
Iterator<Location> it = stackedBlocks.iterator();
while (it.hasNext()) {
Location v = it.next();
Util.getChunkAtAsync(v).thenAccept(c -> {
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (Location v : stackedBlocks) {
CompletableFuture<Void> future = Util.getChunkAtAsync(v).thenAccept(c -> {
Block stackedBlock = v.getBlock();
boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight;
if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) {
@ -658,17 +648,12 @@ public class IslandLevelCalculator {
checkBlock(stackedBlock.getType(), belowSeaLevel);
}
}
synchronized (toRemove) {
toRemove.add(v);
}
});
futures.add(future);
}
// Return a CompletableFuture that completes when all futures are done
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
// Wait for all asynchronous tasks to complete before removing elements
// Remove the elements collected in toRemove
synchronized (toRemove) {
stackedBlocks.removeAll(toRemove);
}
}
}