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 // Done
pipeliner.getInProcessQueue().remove(this); pipeliner.getInProcessQueue().remove(this);
// Chunk finished // Chunk finished
// This was the last chunk // This was the last chunk. Handle stacked blocks, then chests and exit
handleStackedBlocks(); handleStackedBlocks().thenCompose(v -> handleChests()).thenRun(() -> {
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.tidyUp(); this.tidyUp();
this.getR().complete(getResults()); this.getR().complete(getResults());
finishTask.cancel(); });
}
}, 0, 10L);
} }
}); });
} }
private void handleChests() { private CompletableFuture<Void> handleChests() {
Iterator<Chunk> it = chestBlocks.iterator(); List<CompletableFuture<Void>> futures = new ArrayList<>();
while (it.hasNext()) { for (Chunk v : chestBlocks) {
Chunk v = it.next(); CompletableFuture<Void> future = Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> {
Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> {
scanChests(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 // Deal with any stacked blocks
List<Location> toRemove = new ArrayList<>(); List<CompletableFuture<Void>> futures = new ArrayList<>();
Iterator<Location> it = stackedBlocks.iterator(); for (Location v : stackedBlocks) {
while (it.hasNext()) { CompletableFuture<Void> future = Util.getChunkAtAsync(v).thenAccept(c -> {
Location v = it.next();
Util.getChunkAtAsync(v).thenAccept(c -> {
Block stackedBlock = v.getBlock(); Block stackedBlock = v.getBlock();
boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight; boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight;
if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) { if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) {
@ -658,17 +648,12 @@ public class IslandLevelCalculator {
checkBlock(stackedBlock.getType(), belowSeaLevel); 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);
}
} }
} }