From b24c1fdc86f4b6b1757e4e68a153f21170a603be Mon Sep 17 00:00:00 2001 From: tastybento Date: Wed, 8 Sep 2021 21:08:15 -0700 Subject: [PATCH] Use final vars for lambdas to avoid them changing async The processes could run async, especially when chunk loading took a while, so using fields that could change would result in blocks being missed, especially in the nether or end. Switching to final vars avoids this. Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1840 --- .../bentobox/util/DeleteIslandChunks.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/util/DeleteIslandChunks.java b/src/main/java/world/bentobox/bentobox/util/DeleteIslandChunks.java index 422a4c617..593b550d8 100644 --- a/src/main/java/world/bentobox/bentobox/util/DeleteIslandChunks.java +++ b/src/main/java/world/bentobox/bentobox/util/DeleteIslandChunks.java @@ -77,13 +77,15 @@ public class DeleteIslandChunks { inDelete = true; for (int i = 0; i < plugin.getSettings().getDeleteSpeed(); i++) { boolean last = i == plugin.getSettings().getDeleteSpeed() -1; + final int x = chunkX; + final int z = chunkZ; plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm -> // Overworld - processChunk(gm, di.getWorld(), chunkX, chunkZ).thenRun(() -> + processChunk(gm, di.getWorld(), x, z).thenRun(() -> // Nether - processChunk(gm, netherWorld, chunkX, chunkZ).thenRun(() -> + processChunk(gm, netherWorld, x, z).thenRun(() -> // End - processChunk(gm, endWorld, chunkX, chunkZ).thenRun(() -> finish(last))))); + processChunk(gm, endWorld, x, z).thenRun(() -> finish(last, x))))); chunkZ++; if (chunkZ > di.getMaxZChunk()) { chunkZ = di.getMinZChunk(); @@ -94,8 +96,8 @@ public class DeleteIslandChunks { } - private void finish(boolean last) { - if (chunkX > di.getMaxXChunk()) { + private void finish(boolean last, int x) { + if (x > di.getMaxXChunk()) { // Fire event IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build(); // We're done @@ -107,19 +109,25 @@ public class DeleteIslandChunks { } private CompletableFuture processChunk(GameModeAddon gm, World world, int x, int z) { - if (world != null && PaperLib.isChunkGenerated(world, x, z)) { + if (world != null) { CompletableFuture r = new CompletableFuture<>(); - PaperLib.getChunkAtAsync(world, x, z).thenAccept(chunk -> regenerateChunk(r, gm, chunk)); + PaperLib.getChunkAtAsync(world, x, z).thenAccept(chunk -> regenerateChunk(r, gm, chunk, x, z)); return r; } return CompletableFuture.completedFuture(false); } - private void regenerateChunk(CompletableFuture r, GameModeAddon gm, Chunk chunk) { + private void regenerateChunk(CompletableFuture r, GameModeAddon gm, Chunk chunk, int x, int z) { // Clear all inventories Arrays.stream(chunk.getTileEntities()).filter(te -> (te instanceof InventoryHolder)) .filter(te -> di.inBounds(te.getLocation().getBlockX(), te.getLocation().getBlockZ())) .forEach(te -> ((InventoryHolder)te).getInventory().clear()); + // Remove all entities + for (Entity e : chunk.getEntities()) { + if (!(e instanceof Player)) { + e.remove(); + } + } // Reset blocks MyBiomeGrid grid = new MyBiomeGrid(chunk.getWorld().getEnvironment()); ChunkGenerator cg = gm.getDefaultWorldGenerator(chunk.getWorld().getName(), "delete");