mirror of
https://github.com/BentoBoxWorld/Level.git
synced 2024-12-25 18:47:56 +01:00
Avoid async chunk snapshotting.
Fixes https://github.com/BentoBoxWorld/Level/issues/256
This commit is contained in:
parent
5d9aa00c13
commit
0a79b7fa58
@ -417,48 +417,6 @@ public class IslandLevelCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Count the blocks on the island
|
|
||||||
* @param chunk chunk to scan
|
|
||||||
*/
|
|
||||||
private void scanAsync(Chunk chunk) {
|
|
||||||
ChunkSnapshot chunkSnapshot = chunk.getChunkSnapshot();
|
|
||||||
for (int x = 0; x< 16; x++) {
|
|
||||||
// Check if the block coordinate is inside the protection zone and if not, don't count it
|
|
||||||
if (chunkSnapshot.getX() * 16 + x < island.getMinProtectedX() || chunkSnapshot.getX() * 16 + x >= island.getMinProtectedX() + island.getProtectionRange() * 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
// Check if the block coordinate is inside the protection zone and if not, don't count it
|
|
||||||
if (chunkSnapshot.getZ() * 16 + z < island.getMinProtectedZ() || chunkSnapshot.getZ() * 16 + z >= island.getMinProtectedZ() + island.getProtectionRange() * 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Only count to the highest block in the world for some optimization
|
|
||||||
for (int y = chunk.getWorld().getMinHeight(); y < chunk.getWorld().getMaxHeight(); y++) {
|
|
||||||
BlockData blockData = chunkSnapshot.getBlockData(x, y, z);
|
|
||||||
boolean belowSeaLevel = seaHeight > 0 && y <= seaHeight;
|
|
||||||
// Slabs can be doubled, so check them twice
|
|
||||||
if (Tag.SLABS.isTagged(blockData.getMaterial())) {
|
|
||||||
Slab slab = (Slab)blockData;
|
|
||||||
if (slab.getType().equals(Slab.Type.DOUBLE)) {
|
|
||||||
checkBlock(blockData.getMaterial(), belowSeaLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Hook for Wild Stackers (Blocks and Spawners Only) - this has to use the real chunk
|
|
||||||
if (addon.isStackersEnabled() && (blockData.getMaterial().equals(Material.CAULDRON) || blockData.getMaterial().equals(Material.SPAWNER))) {
|
|
||||||
stackedBlocks.add(new Location(chunk.getWorld(), x + chunkSnapshot.getX() * 16,y,z + chunkSnapshot.getZ() * 16));
|
|
||||||
}
|
|
||||||
// Scan chests
|
|
||||||
if (addon.getSettings().isIncludeChests() && CHESTS.contains(blockData.getMaterial())) {
|
|
||||||
chestBlocks.add(chunk);
|
|
||||||
}
|
|
||||||
// Add the value of the block's material
|
|
||||||
checkBlock(blockData.getMaterial(), belowSeaLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan all containers in a chunk and count their blocks
|
* Scan all containers in a chunk and count their blocks
|
||||||
* @param chunk - the chunk to scan
|
* @param chunk - the chunk to scan
|
||||||
@ -493,8 +451,9 @@ public class IslandLevelCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the chunk chests and count the blocks
|
* Scan the chunk chests and count the blocks. Note that the chunks are a list of all the island chunks
|
||||||
* @param chunks - the chunk to scan
|
* in a particular world, so the memory usage is high, but I think most servers can handle it.
|
||||||
|
* @param chunks - a list of chunks to scan
|
||||||
* @return future that completes when the scan is done and supplies a boolean that will be true if the scan was successful, false if not
|
* @return future that completes when the scan is done and supplies a boolean that will be true if the scan was successful, false if not
|
||||||
*/
|
*/
|
||||||
private CompletableFuture<Boolean> scanChunk(List<Chunk> chunks) {
|
private CompletableFuture<Boolean> scanChunk(List<Chunk> chunks) {
|
||||||
@ -504,14 +463,63 @@ public class IslandLevelCalculator {
|
|||||||
}
|
}
|
||||||
// Count blocks in chunk
|
// Count blocks in chunk
|
||||||
CompletableFuture<Boolean> result = new CompletableFuture<>();
|
CompletableFuture<Boolean> result = new CompletableFuture<>();
|
||||||
|
/*
|
||||||
|
* At this point, we need to grab a snapshot of each chunk and then scan it async.
|
||||||
|
* At the end, we make the CompletableFuture true to show it is done.
|
||||||
|
* I'm not sure how much lag this will cause, but as all the chunks are loaded, maybe not that much.
|
||||||
|
*/
|
||||||
|
List<ChunkPair> preLoad = chunks.stream().map(c -> new ChunkPair(c.getWorld(), c, c.getChunkSnapshot())).toList();
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () -> {
|
||||||
chunks.forEach(chunk -> scanAsync(chunk));
|
preLoad.forEach(this::scanAsync);
|
||||||
|
// Once they are all done, return to the main thread.
|
||||||
Bukkit.getScheduler().runTask(addon.getPlugin(),() -> result.complete(true));
|
Bukkit.getScheduler().runTask(addon.getPlugin(),() -> result.complete(true));
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record ChunkPair(World world, Chunk chunk, ChunkSnapshot chunkSnapshot) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the blocks on the island
|
||||||
|
* @param chunk chunk to scan
|
||||||
|
*/
|
||||||
|
private void scanAsync(ChunkPair cp) {
|
||||||
|
for (int x = 0; x< 16; x++) {
|
||||||
|
// Check if the block coordinate is inside the protection zone and if not, don't count it
|
||||||
|
if (cp.chunkSnapshot.getX() * 16 + x < island.getMinProtectedX() || cp.chunkSnapshot.getX() * 16 + x >= island.getMinProtectedX() + island.getProtectionRange() * 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
// Check if the block coordinate is inside the protection zone and if not, don't count it
|
||||||
|
if (cp.chunkSnapshot.getZ() * 16 + z < island.getMinProtectedZ() || cp.chunkSnapshot.getZ() * 16 + z >= island.getMinProtectedZ() + island.getProtectionRange() * 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Only count to the highest block in the world for some optimization
|
||||||
|
for (int y = cp.world.getMinHeight(); y < cp.world.getMaxHeight(); y++) {
|
||||||
|
BlockData blockData = cp.chunkSnapshot.getBlockData(x, y, z);
|
||||||
|
boolean belowSeaLevel = seaHeight > 0 && y <= seaHeight;
|
||||||
|
// Slabs can be doubled, so check them twice
|
||||||
|
if (Tag.SLABS.isTagged(blockData.getMaterial())) {
|
||||||
|
Slab slab = (Slab)blockData;
|
||||||
|
if (slab.getType().equals(Slab.Type.DOUBLE)) {
|
||||||
|
checkBlock(blockData.getMaterial(), belowSeaLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Hook for Wild Stackers (Blocks and Spawners Only) - this has to use the real chunk
|
||||||
|
if (addon.isStackersEnabled() && (blockData.getMaterial().equals(Material.CAULDRON) || blockData.getMaterial().equals(Material.SPAWNER))) {
|
||||||
|
stackedBlocks.add(new Location(cp.world, x + cp.chunkSnapshot.getX() * 16,y,z + cp.chunkSnapshot.getZ() * 16));
|
||||||
|
}
|
||||||
|
// Scan chests
|
||||||
|
if (addon.getSettings().isIncludeChests() && CHESTS.contains(blockData.getMaterial())) {
|
||||||
|
chestBlocks.add(cp.chunk);
|
||||||
|
}
|
||||||
|
// Add the value of the block's material
|
||||||
|
checkBlock(blockData.getMaterial(), belowSeaLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the next chunk on the island
|
* Scan the next chunk on the island
|
||||||
* @return completable boolean future that will be true if more chunks are left to be scanned, and false if not
|
* @return completable boolean future that will be true if more chunks are left to be scanned, and false if not
|
||||||
|
Loading…
Reference in New Issue
Block a user