diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index 6da9f6821..4e74d4814 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -285,7 +285,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { LocalSession session = WorldEdit.getInstance().getSessionManager().get(wePlayer); session.remember(editSession); - editSession.flushQueue(); + editSession.flushSession(); WorldEdit.getInstance().flushBlockBag(wePlayer, editSession); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 1e3005f59..bc98a20e3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -134,7 +134,7 @@ import javax.annotation.Nullable; * using the {@link ChangeSetExtent}.

*/ @SuppressWarnings({"FieldCanBeLocal"}) -public class EditSession implements Extent { +public class EditSession implements Extent, AutoCloseable { private static final Logger log = Logger.getLogger(EditSession.class.getCanonicalName()); @@ -298,13 +298,13 @@ public class EditSession implements Extent { } /** - * Disable the queue. This will flush the queue. + * Disable the queue. This will {@linkplain #flushSession() flush the session}. */ public void disableQueue() { if (isQueueEnabled()) { - flushQueue(); + flushSession(); } - reorderExtent.setEnabled(true); + reorderExtent.setEnabled(false); } /** @@ -393,10 +393,21 @@ public class EditSession implements Extent { return blockBagExtent.popMissing(); } + /** + * Returns chunk batching status. + * + * @return whether chunk batching is enabled + */ public boolean isBatchingChunks() { return chunkBatchingExtent != null && chunkBatchingExtent.isEnabled(); } + /** + * Enable or disable chunk batching. Disabling will + * {@linkplain #flushSession() flush the session}. + * + * @param batchingChunks {@code true} to enable, {@code false} to disable + */ public void setBatchingChunks(boolean batchingChunks) { if (chunkBatchingExtent == null) { if (batchingChunks) { @@ -404,12 +415,30 @@ public class EditSession implements Extent { } return; } - if (!batchingChunks) { - flushQueue(); + if (!batchingChunks && isBatchingChunks()) { + flushSession(); } chunkBatchingExtent.setEnabled(batchingChunks); } + /** + * Disable all buffering extents. + * + * @see #disableQueue() + * @see #setBatchingChunks(boolean) + */ + public void disableBuffering() { + // We optimize here to avoid repeated calls to flushSession. + boolean needsFlush = isQueueEnabled() || isBatchingChunks(); + if (needsFlush) { + flushSession(); + } + reorderExtent.setEnabled(false); + if (chunkBatchingExtent != null) { + chunkBatchingExtent.setEnabled(false); + } + } + /** * Get the number of blocks changed, including repeated block changes. * @@ -569,7 +598,7 @@ public class EditSession implements Extent { UndoContext context = new UndoContext(); context.setExtent(editSession.bypassHistory); Operations.completeBlindly(ChangeSetExecutor.createUndo(changeSet, context)); - editSession.flushQueue(); + editSession.flushSession(); } /** @@ -581,7 +610,7 @@ public class EditSession implements Extent { UndoContext context = new UndoContext(); context.setExtent(editSession.bypassHistory); Operations.completeBlindly(ChangeSetExecutor.createRedo(changeSet, context)); - editSession.flushQueue(); + editSession.flushSession(); } /** @@ -614,9 +643,18 @@ public class EditSession implements Extent { } /** - * Finish off the queue. + * Closing an EditSession {@linkplain #flushSession() flushes its buffers}. */ - public void flushQueue() { + @Override + public void close() { + flushSession(); + } + + /** + * Communicate to the EditSession that all block changes are complete, + * and that it should apply them to the world. + */ + public void flushSession() { Operations.completeBlindly(commit()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java index c25e5a2c0..69a62a5c2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -628,7 +628,7 @@ public class WorldEdit { logger.log(Level.WARNING, "Failed to execute script", e); } finally { for (EditSession editSession : scriptContext.getEditSessions()) { - editSession.flushQueue(); + editSession.flushSession(); session.remember(editSession); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index f20b54d51..96e3e9875 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -460,7 +460,7 @@ public class UtilityCommands { if (editSession != null) { session.remember(editSession); - editSession.flushQueue(); + editSession.flushSession(); } } @@ -520,7 +520,7 @@ public class UtilityCommands { if (editSession != null) { session.remember(editSession); - editSession.flushQueue(); + editSession.flushSession(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java index e7b64ad7e..1af33599c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/AreaPickaxe.java @@ -62,29 +62,29 @@ public class AreaPickaxe implements BlockTool { return true; } - EditSession editSession = session.createEditSession(player); - editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop); + try (EditSession editSession = session.createEditSession(player)) { + editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop); - try { - for (int x = ox - range; x <= ox + range; ++x) { - for (int y = oy - range; y <= oy + range; ++y) { - for (int z = oz - range; z <= oz + range; ++z) { - Vector pos = new Vector(x, y, z); - if (editSession.getBlock(pos).getBlockType() != initialType) { - continue; + try { + for (int x = ox - range; x <= ox + range; ++x) { + for (int y = oy - range; y <= oy + range; ++y) { + for (int z = oz - range; z <= oz + range; ++z) { + Vector pos = new Vector(x, y, z); + if (editSession.getBlock(pos).getBlockType() != initialType) { + continue; + } + + ((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, clicked.toVector().distanceSq(pos)); + + editSession.setBlock(pos, BlockTypes.AIR.getDefaultState()); } - - ((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, clicked.toVector().distanceSq(pos)); - - editSession.setBlock(pos, BlockTypes.AIR.getDefaultState()); } } + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + session.remember(editSession); } - } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); - } finally { - editSession.flushQueue(); - session.remember(editSession); } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index 1388b66ea..38619396b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -52,17 +52,19 @@ public class BlockReplacer implements DoubleActionBlockTool { public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { BlockBag bag = session.getBlockBag(player); - EditSession editSession = session.createEditSession(player); - - try { - Vector position = clicked.toVector(); - editSession.setBlock(position, pattern.apply(position)); - } catch (MaxChangedBlocksException ignored) { + try (EditSession editSession = session.createEditSession(player)) { + try { + editSession.disableBuffering(); + Vector position = clicked.toVector(); + editSession.setBlock(position, pattern.apply(position)); + } catch (MaxChangedBlocksException ignored) { + } finally { + session.remember(editSession); + } } finally { if (bag != null) { bag.flushChanges(); } - session.remember(editSession); } return true; @@ -71,8 +73,7 @@ public class BlockReplacer implements DoubleActionBlockTool { @Override public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) { - EditSession editSession = session.createEditSession(player); - BlockStateHolder targetBlock = editSession.getBlock(clicked.toVector()); + BlockStateHolder targetBlock = player.getWorld().getBlock(clicked.toVector()); if (targetBlock != null) { pattern = new BlockPattern(targetBlock); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index 9096a4d19..55d2947f7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -172,31 +172,33 @@ public class BrushTool implements TraceTool { BlockBag bag = session.getBlockBag(player); - EditSession editSession = session.createEditSession(player); - Request.request().setEditSession(editSession); - if (mask != null) { - Mask existingMask = editSession.getMask(); + try (EditSession editSession = session.createEditSession(player)) { + Request.request().setEditSession(editSession); + if (mask != null) { + Mask existingMask = editSession.getMask(); - if (existingMask == null) { - editSession.setMask(mask); - } else if (existingMask instanceof MaskIntersection) { - ((MaskIntersection) existingMask).add(mask); - } else { - MaskIntersection newMask = new MaskIntersection(existingMask); - newMask.add(mask); - editSession.setMask(newMask); + if (existingMask == null) { + editSession.setMask(mask); + } else if (existingMask instanceof MaskIntersection) { + ((MaskIntersection) existingMask).add(mask); + } else { + MaskIntersection newMask = new MaskIntersection(existingMask); + newMask.add(mask); + editSession.setMask(newMask); + } } - } - try { - brush.build(editSession, target.toVector(), material, size); - } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + try { + brush.build(editSession, target.toVector(), material, size); + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + session.remember(editSession); + } } finally { if (bag != null) { bag.flushChanges(); } - session.remember(editSession); } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java index b2fcf6525..afeb4728d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java @@ -66,17 +66,17 @@ public class RecursivePickaxe implements BlockTool { return true; } - EditSession editSession = session.createEditSession(player); - editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop); + try (EditSession editSession = session.createEditSession(player)) { + editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop); - try { - recurse(server, editSession, world, clicked.toVector().toBlockVector(), - clicked.toVector(), range, initialType, new HashSet<>()); - } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); - } finally { - editSession.flushQueue(); - session.remember(editSession); + try { + recurse(server, editSession, world, clicked.toVector().toBlockVector(), + clicked.toVector(), range, initialType, new HashSet<>()); + } catch (MaxChangedBlocksException e) { + player.printError("Max blocks change limit reached."); + } finally { + session.remember(editSession); + } } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java index f3f4c9945..fbf1874ce 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java @@ -49,15 +49,11 @@ public class SinglePickaxe implements BlockTool { return true; } - EditSession editSession = session.createEditSession(player); - editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); - - try { + try (EditSession editSession = session.createEditSession(player)) { + editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); editSession.setBlock(clicked.toVector(), BlockTypes.AIR.getDefaultState()); } catch (MaxChangedBlocksException e) { player.printError("Max blocks change limit reached."); - } finally { - editSession.flushQueue(); } world.playEffect(clicked.toVector(), 2001, blockType.getLegacyId()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 12f56a81a..297ccf318 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -316,7 +316,7 @@ public final class CommandManager { if (editSession != null) { session.remember(editSession); - editSession.flushQueue(); + editSession.flushSession(); if (config.profile) { long time = System.currentTimeMillis() - start;