From 4e5e9f609edfe12fdf288a6c2c58e75f64821faf Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Mon, 15 Oct 2018 16:12:21 +1000 Subject: [PATCH 01/10] Added the multi-staging from the multipass2 branch --- .../com/sk89q/worldedit/blocks/Blocks.java | 22 ++++ .../extent/reorder/MultiStageReorder.java | 112 +++++++++++------- .../history/changeset/ArrayListHistory.java | 16 ++- .../history/changeset/ChangeSet.java | 13 ++ 4 files changed, 119 insertions(+), 44 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java index 09bd50ff2..939fb7e7e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java @@ -36,6 +36,28 @@ public final class Blocks { private Blocks() { } + /** + * HashSet for shouldPlaceLate. + */ + private static final Set shouldPlaceLate = new HashSet<>(); + static { + shouldPlaceLate.add(BlockTypes.WATER); + shouldPlaceLate.add(BlockTypes.LAVA); + shouldPlaceLate.add(BlockTypes.GRAVEL); + shouldPlaceLate.add(BlockTypes.SAND); + } + /** + * Checks to see whether a block should be placed in the final queue. + * + * This applies to blocks that can be attached to other blocks that have an attachment. + * + * @param type the type of the block + * @return whether the block is in the late queue + */ + public static boolean shouldPlaceLate(BlockType type) { + return shouldPlaceLate.contains(type); + } + /** * HashSet for shouldPlaceLast. */ diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java index ea6bece5a..f741ff1b3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.extent.reorder; -import com.google.common.collect.Iterables; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.Blocks; import com.sk89q.worldedit.extent.AbstractDelegateExtent; @@ -37,6 +36,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; +import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; @@ -50,11 +50,21 @@ import java.util.Set; */ public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent { - private LocatedBlockList stage1 = new LocatedBlockList(); - private LocatedBlockList stage2 = new LocatedBlockList(); - private LocatedBlockList stage3 = new LocatedBlockList(); + private static final int STAGE_COUNT = 4; + + private List stages = new ArrayList<>(); + private boolean enabled; + /** + * Create a new instance when the re-ordering is enabled. + * + * @param extent the extent + */ + public MultiStageReorder(Extent extent) { + this(extent, true); + } + /** * Create a new instance. * @@ -64,15 +74,10 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder public MultiStageReorder(Extent extent, boolean enabled) { super(extent); this.enabled = enabled; - } - /** - * Create a new instance when the re-ordering is enabled. - * - * @param extent the extent - */ - public MultiStageReorder(Extent extent) { - this(extent, true); + for (int i = 0; i < STAGE_COUNT; ++i) { + stages.add(new LocatedBlockList()); + } } /** @@ -94,58 +99,76 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } public boolean commitRequired() { - return stage1.size() > 0 || stage2.size() > 0 || stage3.size() > 0; + return stages.stream().anyMatch(stage -> stage.size() > 0); + } + + /** + * Gets the stage priority of the block. + * + * @param block The block + * @return The priority + */ + public int getPlacementPriority(BlockStateHolder block) { + if (Blocks.shouldPlaceLate(block.getBlockType())) { + return 1; + } else if (Blocks.shouldPlaceLast(block.getBlockType())) { + // Place torches, etc. last + return 2; + } else if (Blocks.shouldPlaceFinal(block.getBlockType())) { + // Place signs, reed, etc even later + return 3; + } else { + return 0; + } } @Override public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException { - BlockState existing = getBlock(location); - if (!enabled) { return super.setBlock(location, block); } - if (Blocks.shouldPlaceLast(block.getBlockType())) { - // Place torches, etc. last - stage2.add(location, block); - return !existing.equalsFuzzy(block); - } else if (Blocks.shouldPlaceFinal(block.getBlockType())) { - // Place signs, reed, etc even later - stage3.add(location, block); - return !existing.equalsFuzzy(block); - } else if (Blocks.shouldPlaceLast(existing.getBlockType())) { + BlockState existing = getBlock(location); + int priority = getPlacementPriority(block); + int srcPriority = getPlacementPriority(existing); + + if (srcPriority == 1 || srcPriority == 2) { // Destroy torches, etc. first super.setBlock(location, BlockTypes.AIR.getDefaultState()); return super.setBlock(location, block); - } else { - stage1.add(location, block); - return !existing.equalsFuzzy(block); } + + stages.get(priority).add(location, block); + return !existing.equalsFuzzy(block); } @Override public Operation commitBefore() { - return new OperationQueue( - new SetLocatedBlocks( - getExtent(), - Iterables.concat(stage1, stage2)), - new Stage3Committer()); + List operations = new ArrayList<>(); + for (int i = 0; i < stages.size() - 1; ++i) { + operations.add(new SetLocatedBlocks(getExtent(), stages.get(i))); + } + + operations.add(new FinalStageCommitter()); + return new OperationQueue(operations); } - private class Stage3Committer implements Operation { + private class FinalStageCommitter implements Operation { + private Extent extent = getExtent(); - @Override - public Operation resume(RunContext run) throws WorldEditException { - Extent extent = getExtent(); + private final Set blocks = new HashSet<>(); + private final Map blockTypes = new HashMap<>(); - final Set blocks = new HashSet<>(); - final Map blockTypes = new HashMap<>(); - for (LocatedBlock entry : stage3) { + public FinalStageCommitter() { + for (LocatedBlock entry : stages.get(stages.size() - 1)) { final BlockVector3 pt = entry.getLocation(); blocks.add(pt); blockTypes.put(pt, entry.getBlock()); } + } + @Override + public Operation resume(RunContext run) throws WorldEditException { while (!blocks.isEmpty()) { BlockVector3 current = blocks.iterator().next(); if (!blocks.contains(current)) { @@ -201,11 +224,14 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } } - stage1.clear(); - stage2.clear(); - stage3.clear(); + if (blocks.isEmpty()) { + for (LocatedBlockList stage : stages) { + stage.clear(); + } + return null; + } - return null; + return this; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java index bc13a5755..d014835d3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ArrayListHistory.java @@ -35,10 +35,24 @@ public class ArrayListHistory implements ChangeSet { private final List changes = new ArrayList<>(); + private boolean recordChanges = true; + @Override public void add(Change change) { checkNotNull(change); - changes.add(change); + if (recordChanges) { + changes.add(change); + } + } + + @Override + public boolean isRecordingChanges() { + return recordChanges; + } + + @Override + public void setRecordChanges(boolean recordChanges) { + this.recordChanges = recordChanges; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java index 0b018bcb9..fc5adb2e7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java @@ -36,6 +36,19 @@ public interface ChangeSet { */ void add(Change change); + /** + * Whether or not the ChangeSet is recording changes. + * + * @return whether or not the ChangeSet is set to record changes + */ + boolean isRecordingChanges(); + /** + * Tell the change set whether to record changes or not. + * + * @param recordChanges whether to record changes or not + */ + void setRecordChanges(boolean recordChanges); + /** * Get a backward directed iterator that can be used for undo. * From 7d468357e32ec69d9478e8bfd8f2fe8d5a1893ba Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Mon, 15 Oct 2018 20:50:09 +1000 Subject: [PATCH 02/10] Added "fast mode corrections" --- .../sk89q/worldedit/bukkit/BukkitWorld.java | 11 ++++++ .../bukkit/adapter/BukkitImplAdapter.java | 10 ++++++ .../java/com/sk89q/worldedit/EditSession.java | 20 ++++++++--- .../extent/world/FastModeExtent.java | 36 ++++++++++++++++++- .../history/changeset/ChangeSet.java | 1 + .../com/sk89q/worldedit/world/NullWorld.java | 5 +++ .../java/com/sk89q/worldedit/world/World.java | 13 +++++++ .../com/sk89q/worldedit/forge/ForgeWorld.java | 6 ++++ .../sk89q/worldedit/sponge/SpongeWorld.java | 7 +++- 9 files changed, 103 insertions(+), 6 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index afc6c36de..8bffc3a2e 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -448,6 +448,17 @@ public class BukkitWorld extends AbstractWorld { } } + @Override + public boolean notifyAndLightBlock(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType) throws WorldEditException { + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + adapter.notifyAndLightBlock(BukkitAdapter.adapt(getWorld(), position), previousType); + return true; + } + + return false; + } + @Override public BaseBiome getBiome(BlockVector2 position) { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index 393877581..13631e1d9 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import org.bukkit.Location; @@ -78,6 +79,15 @@ public interface BukkitImplAdapter { */ boolean setBlock(Location location, BlockStateHolder state, boolean notifyAndLight); + /** + * Notifies the simulation that the block at the given location has + * been changed and it must be re-lighted (and issue other events). + * + * @param position position of the block + * @param previousType the type of the previous block that was there + */ + void notifyAndLightBlock(Location position, BlockState previousType); + /** * Get the state for the given entity. * 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 fabf49f3f..fad8c8850 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -170,6 +170,8 @@ public class EditSession implements Extent, AutoCloseable { private final Extent bypassHistory; private final Extent bypassNone; + private final boolean useFastModeCorrections; + private Mask oldMask; /** @@ -187,12 +189,13 @@ public class EditSession implements Extent, AutoCloseable { checkNotNull(event); this.world = world; + this.useFastModeCorrections = false; if (world != null) { Extent extent; // These extents are ALWAYS used - extent = fastModeExtent = new FastModeExtent(world, false); + extent = fastModeExtent = new FastModeExtent(world, useFastModeCorrections); extent = survivalExtent = new SurvivalModeExtent(extent, world); extent = quirkExtent = new BlockQuirkExtent(extent, world); extent = chunkLoadingExtent = new ChunkLoadingExtent(extent, world); @@ -299,14 +302,16 @@ public class EditSession implements Extent, AutoCloseable { * @return whether the queue is enabled */ public boolean isQueueEnabled() { - return reorderExtent.isEnabled(); + return !useFastModeCorrections && reorderExtent.isEnabled(); } /** * Queue certain types of block for better reproduction of those blocks. */ public void enableQueue() { - reorderExtent.setEnabled(true); + if (!useFastModeCorrections) { + reorderExtent.setEnabled(true); + } } /** @@ -361,7 +366,14 @@ public class EditSession implements Extent, AutoCloseable { */ public void setFastMode(boolean enabled) { if (fastModeExtent != null) { - fastModeExtent.setEnabled(enabled); + // If fast mode corrections are enabled, we're using fast mode for + // multipass support. Thus, we do not actually ever turn the fast mode + // extent off, we instead toggle post edit simulation + if (useFastModeCorrections) { + fastModeExtent.setPostEditSimulationEnabled(!enabled); + } else { + fastModeExtent.setEnabled(enabled); + } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java index b75156d3b..37f524ad0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java @@ -29,9 +29,12 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypes; +import java.util.ArrayDeque; import java.util.HashSet; import java.util.List; +import java.util.Queue; import java.util.Set; /** @@ -40,8 +43,10 @@ import java.util.Set; public class FastModeExtent extends AbstractDelegateExtent { private final World world; + private final Queue positions = new ArrayDeque<>(); private final Set dirtyChunks = new HashSet<>(); private boolean enabled = true; + private boolean postEditSimulation; /** * Create a new instance with fast mode enabled. @@ -63,6 +68,9 @@ public class FastModeExtent extends AbstractDelegateExtent { checkNotNull(world); this.world = world; this.enabled = enabled; + if (enabled) { + this.postEditSimulation = true; + } } /** @@ -83,11 +91,27 @@ public class FastModeExtent extends AbstractDelegateExtent { this.enabled = enabled; } + public boolean isPostEditSimulationEnabled() { + return postEditSimulation; + } + + public void setPostEditSimulationEnabled(boolean enabled) { + this.postEditSimulation = enabled; + } + @Override public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException { if (enabled) { dirtyChunks.add(BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4)); - return world.setBlock(location, block, false); + + if (world.setBlock(location, block, false)) { + if (postEditSimulation) { + positions.offer(location); + } + return true; + } + + return false; } else { return world.setBlock(location, block, true); } @@ -101,6 +125,16 @@ public class FastModeExtent extends AbstractDelegateExtent { if (!dirtyChunks.isEmpty()) { world.fixAfterFastMode(dirtyChunks); } + + if (postEditSimulation) { + while (run.shouldContinue() && !positions.isEmpty()) { + BlockVector3 position = positions.poll(); // Remove from queue + world.notifyAndLightBlock(position, BlockTypes.AIR.getDefaultState()); + } + + return !positions.isEmpty() ? this : null; + } + return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java index fc5adb2e7..003a007b6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java @@ -42,6 +42,7 @@ public interface ChangeSet { * @return whether or not the ChangeSet is set to record changes */ boolean isRecordingChanges(); + /** * Tell the change set whether to record changes or not. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java index 43ee77e39..eec1d47a9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java @@ -64,6 +64,11 @@ public class NullWorld extends AbstractWorld { return false; } + @Override + public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { + return false; + } + @Override public int getBlockLightLevel(BlockVector3 position) { return 0; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java index 3e7bbf88c..d47723a42 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java @@ -33,10 +33,13 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.weather.WeatherType; +import java.util.Vector; + /** * Represents a world (dimension). */ @@ -95,6 +98,16 @@ public interface World extends Extent { */ boolean setBlock(BlockVector3 position, BlockStateHolder block, boolean notifyAndLight) throws WorldEditException; + /** + * Notifies the simulation that the block at the given location has + * been changed and it must be re-lighted (and issue other events). + * + * @param position position of the block + * @param previousType the type of the previous block that was there + * @return true if the block was successfully notified + */ + boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException; + /** * Get the light level at the given block. * diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 23ea709ff..d3d84d48a 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -212,6 +212,12 @@ public class ForgeWorld extends AbstractWorld { return successful; } + @Override + public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { + // TODO Implement + return false; + } + // Can't get the "Object" to be right for withProperty w/o this @SuppressWarnings({ "rawtypes", "unchecked" }) private IBlockState applyProperties(BlockStateContainer stateContainer, IBlockState newState, Map, Object> states) { diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java index 74c2a6a3c..e3401190e 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java @@ -41,7 +41,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.weather.WeatherType; import com.sk89q.worldedit.world.weather.WeatherTypes; - import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.block.BlockState; @@ -163,6 +162,12 @@ public abstract class SpongeWorld extends AbstractWorld { return true; } + @Override + public boolean notifyAndLightBlock(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType) throws WorldEditException { + // TODO Move this to adapter + return false; + } + @Override public boolean regenerate(Region region, EditSession editSession) { return false; From 36430863a16896d4fcaa3dc7be019e97255364a7 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 15 Nov 2018 18:58:21 +1000 Subject: [PATCH 03/10] Update adapters --- .../bukkit/adapter/impl/Spigot_v1_13_R1.class | Bin 21478 -> 22415 bytes .../bukkit/adapter/impl/Spigot_v1_13_R2.class | Bin 21671 -> 22608 bytes .../adapter/impl/Spigot_v1_13_R2_2.class | Bin 21725 -> 22662 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/worldedit-bukkit/src/main/resources/com/sk89q/worldedit/bukkit/adapter/impl/Spigot_v1_13_R1.class b/worldedit-bukkit/src/main/resources/com/sk89q/worldedit/bukkit/adapter/impl/Spigot_v1_13_R1.class index b4c1e73b500b36c8c8bc3b7e2481d984cecfa0c1..855eaaa082bd0e81a71a6349f9c1351fe7b6cf5f 100644 GIT binary patch delta 7934 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 diff --git a/worldedit-bukkit/src/main/resources/com/sk89q/worldedit/bukkit/adapter/impl/Spigot_v1_13_R2.class b/worldedit-bukkit/src/main/resources/com/sk89q/worldedit/bukkit/adapter/impl/Spigot_v1_13_R2.class index 0c8ead5c3c9c6a9ebe247d10cc28488a54424ceb..a431d058405ad3d2eaa0de1cddbdd99d6f84073f 100644 GIT binary patch delta 7982 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 delta 7442 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 Ta;kLkdn09(jI8aQFC+g862TPB diff --git a/worldedit-bukkit/src/main/resources/com/sk89q/worldedit/bukkit/adapter/impl/Spigot_v1_13_R2_2.class b/worldedit-bukkit/src/main/resources/com/sk89q/worldedit/bukkit/adapter/impl/Spigot_v1_13_R2_2.class index 0c0194e0ca3d9352aa8a55162fb365b171204e19..68d629d18cbdea69d604b75e99c28ec1c9e80fc8 100644 GIT binary patch delta 8071 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 delta 7549 zcmZ`;349dA(yyxC-QLVj$i;?iAR!@~IY4d*$Q@K59D+cQD?qp*m;?|-7eNucPzI48 zB7zbwF%Z~I$WsnE6nu!NASm9b_*8uAQ{>94nhl4(?@NB$(^K7DT~%HGfA`ER+=gd1 zqW|#KU2gzDD|Om{%eY61y#_?$J_Fyx{bA_D0~!w+cnIGT@!J{?yYYxr-;u_D8h8}n z)p*Q}?`b?9hVSDC()gh?o-pvFG=Aj9QwDgEr|{y(27ZEPr1;dp&;0ng0lo1HuHu&l zeuZBfkc4M7ek0e@BKcO@zLSCnoWt+K@L%|Yhl?Mj_(|h=5&vx9zws9Xf5qQ4{ztCA zOYw&k7o_;pgBS6VftT@$0U3BzW0e7|{R9RfktSt8JN6%)?uvrnquTyQwp!9Sc7U&oB@5wCq=wLwW$ub z`6)r}!^0?%>Uv;4C3z^B>PeBJslI4!ASxQN3)D!8#!@tqB2|hs4h*G-Q3f>?N18Zi_fca~S1x)?B-x*F7tx_hVx zC27ji)Kk-K9w?&QrRZ+Z9n{N!S=3uoA5GcPuWvLU4e-#NG|-?ybeGfyYZ_v}TfW!2H0Y_-HrWZX>gRuff@wBEjnqD&CxGdUQ1Hxz>qmEvd z+AESX>!m0$Xaj8&k2gsSH*4DBfiv`~6k9dDCcc*%_&#luP|P-*;=Ry3C** zv{Pc>7oP(L1*u#@ut2=7FlZN5iogF5&liiQuZz!5vJD}h-Vkeci!*x++DrSyxs~F} zn+ENt1LE3h_J$5>IwV%S#oRz|>jXONrX!l(@gP#J0Xg(fgO1X>nvQ9DuWY@eHad=L zdcW*|GnE|QFeJ);)guVcmklubVI+6@fZ?v`Lro_%owQ0l$M7R-PWWC&jHXjoryA$N zV>NLIU5s!|AD6X?D5UUDY#f}i6a3S%9Z_$P<1=2fvRO5opmCUUSJUU3z9`%1t%(j^ zy2IAq*cA!kSi__*=_`}Irn8#9G3i_S&P0uFgfy#8-K4ng1-avk2Idva$}7-x&ZO_@ zUnc#4mDbi;tzv$ppG*uxL(_Saex`pTG_bbSO15UiIIQ@%x;5z+lYYhZCjCbLG0}sj zrr#}pX7W;(tNXyBf=SaSAUKNh3X4n(r$0=(AV!=t=})?7(j~gg{+e`!u9{S(z*MM6 zD`hH&a+=CTXGN8DOq-2NrIp)MVRTU|!&Dw+Y87s(8Y)6sB25*gq7fQd10w5MtJ2+Z zrixKDwep%O7Ara4rmCgl5K_fsYqHNw^{IGM)s~_T7uZQ9@OqdkQPtHd$yCXzo|u#( zK^hR5Vl@kQhqDW+KCg?Z8mNZWJ;{x%Dxcv_z(fZkgfYJj>EA+lS3eoTXjFR}or`ki{4&hK@o=nVwhF zY}%yhd1I|%k?~e`om*>Q)7gyz&a8grRQ^@ zSsGa9lN}j=1*sCC`#(vZ4l4VXA*;1y`WZG9tg*GPUZQ7>dP(%Jy=HMlO0s*M zdRb(zSnX2gHOUjWwZuwOt+#6`+EgWKgH{_&wMlI@)fV-tskW*`))y&p?$=aTk#x1N zeys^xRH>=9ap+jGM2hWNm6>XXB=HutQ>%cff|AEuRJm3arrISlY~d(yu|f)-wM6|x zYOibchN*V5wS2QjtG%Y$$7ZT6!Z-E3?l;wbQyowTtyT3$)i@-n_?D^ORBuauY%^6?+`{tUO*+Fd9Wz)4tg|ULpYj0()otY z(-00H-=s78y3S~h-mR=N9GoGYJh~HhwsrLGInR!H8*T;og6I8;YhQB)pM^O11`^>r zs1N7h7We_O;78~MKfypa55wSRm;}Gt^NnZw212YIOTj??^_lar3wE_<9)sPmJ7-oj zjKCgjjbiOXFpF!B!92+T?8#LpPt_Z5!`nHqw?JpS1ABqyX;ZN`=d;@m1?O`W&m5+) zkH&0`eGwU?{WSL1IDjWdyb}l7uC2MP!gj3}PYQ5>wg1V6UV<2gw-2sBUAPJjP(e$E zdM0Y<&QQM{Jur$PJ`Tg#jT+$Rq*}tD6KJf*Slith;DLN-YrAW}D7ejrN*IHDEDplE zKnP<)CVFXKD9Bj}MJ1$N(Yq1>{7c_tcc38CSxKA8k z5AJJ@=dj!2yzTQayjy(c`g`oBi?3bN$|21^ByA7$&Q1?NoxU06&?nR3a~y=mmC!CH z2<V8%&?B)5uJGU6sTiI$Jt*Dxty-a-zff#4nVHY z;d5?>F##Am#ODk^?VF>~6WC8|%F$@X(P+*-*>8lJK{o`>0CsSj%7bkL9opvxYz)=O+HxM(4^G4%jJG4_YPSrRK z;3Cw$2(F8~ls7Xg;&jZHxbxPt5S)_QIC>Y111N{Q?Cmg~!!@BCCRV^C;t)^v_suv2 z^-_0$vl6CoicO847J%u}i7x@j55SD{QeL`yBoPBpPyvO!TD*p#)k2rl?A0pDbopF+ zVP-KTRl=+spQ{39Bgo}m66SIz|INKB-~ohP@E|}1@avp% zm{$Q0iJ9|*us{Ycl)(?%gCF_Z4Ao;7{$FDsm9f2K>>}H`#W%+C{MXETOnNn_gvWEP zh2ja0fzK5H3c!=0a0KD0-RVAE!Pp16Jgs0z$<^P}1$hn|d4m}kfPMI3I-4=omtTGL zgIlpbqwP+}VxF78DU#2m@&xZ(%W$Y4UcwxB3x~lmCWJFM936}_6Gvhb9L*#;7VqXv z8;N<>iEJ@Ldj`?=HQbXFW z`OMt)C@uma;1;+TA7f{j?_1#Gye5imdIF!UwrnITm4jU3&4#VaslJP>6NKmgVnnn| zgoW&95p!%IB;YLD0ErxHxo$vWwE-j#$1<1Ip?_`vDhA#Q*{r->09N)#qaVug=4&W0lY`Cp`!+m8R{5wZ#x!3G2k>wE=iJ2(O5A zy)7*f>G}X{2*SqFG;4SNruDMyhV9aj6@aoJ?2zs|ZD~NHJFSQTNgczAAuW~f!h-O6 zX}0jjcGw-ghgWHDCG5+IURMckvN!vKa6rZ%w8tNk@dpFelmT`9-eQQVgrhlW74R-X z5ROT=_lm(&3CDTh`=vJn@PiN+G5*vI{BhU_4c_+OsD|81KD7fr#CP-gApJ0(I3MB7 zZXqwiBItmNp(n5OUHCYM@Coqe@)}RXr(J2rd2uw>R|1XD3gV#? zugh9?E*m_&I_r6Ny?+o77f^-1)lB#3rf`fI%;H`wU0+)3G_#yyb2H`7dD6w(0UK&aQ@O2Q*igdHxeUnHx`vdSz z0KN^vchd5j-Lh3$UJJmv0DK>We@Vl3yCF*&wg=#c0Q?w)p3)GoXV@tXfdKpzg!3ZZ zWlJkWx+?%b2jSl$-B%1G`irpEzP@}w@c$Y*$lai=gzL2Rd8U)ogiosM>u*C! zsy?%wJ!G45P;?&(z<&bpdl3E*^+)W6!_sgh02c!AXAmw*!%^EBuQVJDz@;G666x_` zNJ!n`=MBK|I$X|CsvNEi48T=R&(dtXnNMO6{vSeFj$80msH!HEO_0i2`YzucV?sI3 zIru&k$_L=X4_#ZTd7{EVNnKZn=x z3)qieGMRkE`}@~SCTIC6>>DPNZ}}a?cNoQ=ykhZtY|Ed(y5SFe%KVYZ}GVcAP8i{EfsxVC~vgs4VddxZ1`IT}JREg{Br1(HIi zP-d5lfN|cqxH!MpYx53crrhS8ls~y8&O1V51%FeM*ERwb*3gP|$`)*-?m?{JIDimD z=tYVBB7qM!){pvAzv|jB>i1t0 Cd^(Q+ From b3f5bc030ed343fcddefa9406956f2c8604d5e22 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 15 Nov 2018 19:18:22 +1000 Subject: [PATCH 04/10] Few fixes for FastModeExtent. --- .../java/com/sk89q/worldedit/EditSession.java | 3 +++ .../worldedit/extent/world/FastModeExtent.java | 17 +++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) 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 fad8c8850..5088a2bdf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -246,6 +246,9 @@ public class EditSession implements Extent, AutoCloseable { if (isBatchingChunks() && chunkBatchingExtent.commitRequired()) { return true; } + if (hasFastMode() && fastModeExtent.commitRequired()) { + return true; + } return false; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java index 37f524ad0..9ca43b63f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java @@ -31,10 +31,9 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; -import java.util.ArrayDeque; import java.util.HashSet; +import java.util.Iterator; import java.util.List; -import java.util.Queue; import java.util.Set; /** @@ -43,7 +42,7 @@ import java.util.Set; public class FastModeExtent extends AbstractDelegateExtent { private final World world; - private final Queue positions = new ArrayDeque<>(); + private final Set positions = new HashSet<>(); private final Set dirtyChunks = new HashSet<>(); private boolean enabled = true; private boolean postEditSimulation; @@ -106,7 +105,7 @@ public class FastModeExtent extends AbstractDelegateExtent { if (world.setBlock(location, block, false)) { if (postEditSimulation) { - positions.offer(location); + positions.add(location); } return true; } @@ -117,6 +116,10 @@ public class FastModeExtent extends AbstractDelegateExtent { } } + public boolean commitRequired() { + return !dirtyChunks.isEmpty() || !positions.isEmpty(); + } + @Override protected Operation commitBefore() { return new Operation() { @@ -127,9 +130,11 @@ public class FastModeExtent extends AbstractDelegateExtent { } if (postEditSimulation) { - while (run.shouldContinue() && !positions.isEmpty()) { - BlockVector3 position = positions.poll(); // Remove from queue + Iterator positionIterator = positions.iterator(); + while (run.shouldContinue() && positionIterator.hasNext()) { + BlockVector3 position = positionIterator.next(); world.notifyAndLightBlock(position, BlockTypes.AIR.getDefaultState()); + positionIterator.remove(); } return !positions.isEmpty() ? this : null; From 7f11b2800ddb557aa2f3fbedcc057ffbe0657c1d Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Tue, 4 Dec 2018 20:20:27 +1000 Subject: [PATCH 05/10] Added an option to switch reorder modes --- .../java/com/sk89q/worldedit/EditSession.java | 122 ++++++++++++++---- .../com/sk89q/worldedit/LocalSession.java | 19 +++ .../worldedit/command/GeneralCommands.java | 24 ++++ .../extent/reorder/MultiStageReorder.java | 2 +- .../extent/world/FastModeExtent.java | 9 +- 5 files changed, 145 insertions(+), 31 deletions(-) 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 5088a2bdf..f2155a3e8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -149,6 +149,38 @@ public class EditSession implements Extent, AutoCloseable { BEFORE_CHANGE } + /** + * Reorder mode for {@link EditSession#setReorderMode(ReorderMode)}. + * + * MULTI_STAGE = Multi stage reorder, may not be great with mods. + * FAST = Use the fast mode. Good for mods. + * NONE = Place blocks without worrying about placement order. + */ + public enum ReorderMode { + MULTI_STAGE("multi"), + FAST("fast"), + NONE("none"); + + private String name; + + ReorderMode(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public static ReorderMode getFromName(String name) { + for (ReorderMode mode : values()) { + if (mode.getName().equalsIgnoreCase(name)) { + return mode; + } + } + return null; + } + } + @SuppressWarnings("ProtectedField") protected final World world; private final ChangeSet changeSet = new BlockOptimizedHistory(); @@ -170,7 +202,7 @@ public class EditSession implements Extent, AutoCloseable { private final Extent bypassHistory; private final Extent bypassNone; - private final boolean useFastModeCorrections; + private ReorderMode reorderMode = ReorderMode.MULTI_STAGE; private Mask oldMask; @@ -189,13 +221,12 @@ public class EditSession implements Extent, AutoCloseable { checkNotNull(event); this.world = world; - this.useFastModeCorrections = false; if (world != null) { Extent extent; // These extents are ALWAYS used - extent = fastModeExtent = new FastModeExtent(world, useFastModeCorrections); + extent = fastModeExtent = new FastModeExtent(world, false); extent = survivalExtent = new SurvivalModeExtent(extent, world); extent = quirkExtent = new BlockQuirkExtent(extent, world); extent = chunkLoadingExtent = new ChunkLoadingExtent(extent, world); @@ -240,13 +271,13 @@ public class EditSession implements Extent, AutoCloseable { // pkg private for TracedEditSession only, may later become public API boolean commitRequired() { - if (isQueueEnabled() && reorderExtent.commitRequired()) { + if (reorderExtent.commitRequired()) { return true; } if (isBatchingChunks() && chunkBatchingExtent.commitRequired()) { return true; } - if (hasFastMode() && fastModeExtent.commitRequired()) { + if (fastModeExtent != null && fastModeExtent.commitRequired()) { return true; } return false; @@ -254,14 +285,60 @@ public class EditSession implements Extent, AutoCloseable { /** * Turns on specific features for a normal WorldEdit session, such as - * {@link #enableQueue() queuing} and {@link #setBatchingChunks(boolean) + * {@link #setReorderMode(ReorderMode)} reordering} and {@link #setBatchingChunks(boolean) * chunk batching}. */ public void enableStandardMode() { - enableQueue(); + setReorderMode(ReorderMode.MULTI_STAGE); setBatchingChunks(true); } + /** + * Sets the {@link ReorderMode} of this EditSession. + * + * @param reorderMode The reorder mode + */ + public void setReorderMode(ReorderMode reorderMode) { + if (reorderMode == ReorderMode.FAST && fastModeExtent == null) { + throw new IllegalArgumentException("An EditSession without a fast mode tried to use it for reordering!"); + } + if (reorderMode == ReorderMode.MULTI_STAGE && reorderExtent == null) { + throw new IllegalArgumentException("An EditSession without a reorder extent tried to use it for reordering!"); + } + this.reorderMode = reorderMode; + switch (reorderMode) { + case MULTI_STAGE: + if (fastModeExtent != null) { + fastModeExtent.setPostEditSimulationEnabled(false); + } + reorderExtent.setEnabled(true); + break; + case FAST: + fastModeExtent.setPostEditSimulationEnabled(true); + if (reorderExtent != null) { + reorderExtent.setEnabled(false); + } + break; + case NONE: + if (fastModeExtent != null) { + fastModeExtent.setPostEditSimulationEnabled(false); + } + if (reorderExtent != null) { + reorderExtent.setEnabled(false); + } + break; + } + } + + /** + * Get the reorder mode. + * + * @return the reorder mode + */ + public ReorderMode getReorderMode() { + return reorderMode; + } + /** * Get the world. * @@ -305,26 +382,31 @@ public class EditSession implements Extent, AutoCloseable { * @return whether the queue is enabled */ public boolean isQueueEnabled() { - return !useFastModeCorrections && reorderExtent.isEnabled(); + return reorderMode == ReorderMode.MULTI_STAGE && reorderExtent.isEnabled(); } /** * Queue certain types of block for better reproduction of those blocks. + * + * Uses {@link ReorderMode#MULTI_STAGE} + * @deprecated Use {@link EditSession#setReorderMode(ReorderMode)} with MULTI_STAGE instead. */ + @Deprecated public void enableQueue() { - if (!useFastModeCorrections) { - reorderExtent.setEnabled(true); - } + setReorderMode(ReorderMode.MULTI_STAGE); } /** * Disable the queue. This will {@linkplain #flushSession() flush the session}. + * + * @deprecated Use {@link EditSession#setReorderMode(ReorderMode)} with another mode instead. */ + @Deprecated public void disableQueue() { if (isQueueEnabled()) { flushSession(); } - reorderExtent.setEnabled(false); + setReorderMode(ReorderMode.NONE); } /** @@ -369,14 +451,7 @@ public class EditSession implements Extent, AutoCloseable { */ public void setFastMode(boolean enabled) { if (fastModeExtent != null) { - // If fast mode corrections are enabled, we're using fast mode for - // multipass support. Thus, we do not actually ever turn the fast mode - // extent off, we instead toggle post edit simulation - if (useFastModeCorrections) { - fastModeExtent.setPostEditSimulationEnabled(!enabled); - } else { - fastModeExtent.setEnabled(enabled); - } + fastModeExtent.setEnabled(enabled); } } @@ -451,16 +526,15 @@ public class EditSession implements Extent, AutoCloseable { /** * Disable all buffering extents. * - * @see #disableQueue() + * @see #setReorderMode(ReorderMode) * @see #setBatchingChunks(boolean) */ public void disableBuffering() { // We optimize here to avoid repeated calls to flushSession. - boolean needsFlush = isQueueEnabled() || isBatchingChunks(); - if (needsFlush) { + if (commitRequired()) { flushSession(); } - reorderExtent.setEnabled(false); + setReorderMode(ReorderMode.NONE); if (chunkBatchingExtent != null) { chunkBatchingExtent.setEnabled(false); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index ee1c038fe..1133c6e7b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -93,6 +93,7 @@ public class LocalSession { private transient Mask mask; private transient TimeZone timezone = TimeZone.getDefault(); private transient BlockVector3 cuiTemporaryBlock; + private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE; // Saved properties private String lastScript; @@ -877,6 +878,24 @@ public class LocalSession { this.fastMode = fastMode; } + /** + * Gets the reorder mode of the session. + * + * @return The reorder mode + */ + public EditSession.ReorderMode getReorderMode() { + return reorderMode; + } + + /** + * Sets the reorder mode of the session. + * + * @param reorderMode The reorder mode + */ + public void setReorderMode(EditSession.ReorderMode reorderMode) { + this.reorderMode = reorderMode; + } + /** * Get the mask. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 862b4398d..a2e051493 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -115,6 +115,30 @@ public class GeneralCommands { } } + @Command( + aliases = { "/reorder" }, + usage = "[multi|fast|none]", + desc = "Sets the reorder mode of WorldEdit", + min = 0, + max = 1 + ) + @CommandPermissions("worldedit.reorder") + public void reorderMode(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { + String newState = args.getString(0, null); + if (newState == null) { + player.print("The reorder mode is " + session.getReorderMode().getName()); + } else { + EditSession.ReorderMode reorderMode = EditSession.ReorderMode.getFromName(newState); + if (reorderMode == null) { + player.printError("Unknown reorder mode!"); + return; + } + + session.setReorderMode(reorderMode); + player.print("The reorder mode is now " + session.getReorderMode().getName()); + } + } + @Command( aliases = { "/drawsel" }, usage = "[on|off]", diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java index f741ff1b3..2be03cbae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java @@ -99,7 +99,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } public boolean commitRequired() { - return stages.stream().anyMatch(stage -> stage.size() > 0); + return enabled && stages.stream().anyMatch(stage -> stage.size() > 0); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java index 9ca43b63f..ad92c6a45 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java @@ -67,9 +67,6 @@ public class FastModeExtent extends AbstractDelegateExtent { checkNotNull(world); this.world = world; this.enabled = enabled; - if (enabled) { - this.postEditSimulation = true; - } } /** @@ -100,11 +97,11 @@ public class FastModeExtent extends AbstractDelegateExtent { @Override public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException { - if (enabled) { + if (enabled || postEditSimulation) { dirtyChunks.add(BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4)); if (world.setBlock(location, block, false)) { - if (postEditSimulation) { + if (!enabled && postEditSimulation) { positions.add(location); } return true; @@ -129,7 +126,7 @@ public class FastModeExtent extends AbstractDelegateExtent { world.fixAfterFastMode(dirtyChunks); } - if (postEditSimulation) { + if (!enabled && postEditSimulation) { Iterator positionIterator = positions.iterator(); while (run.shouldContinue() && positionIterator.hasNext()) { BlockVector3 position = positionIterator.next(); From 59f9864ba3371cb109b48708be37da6b57e19fb4 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Tue, 4 Dec 2018 20:20:59 +1000 Subject: [PATCH 06/10] Set fast to the default --- .../src/main/java/com/sk89q/worldedit/EditSession.java | 2 +- .../src/main/java/com/sk89q/worldedit/LocalSession.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 f2155a3e8..31bc0bd07 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -202,7 +202,7 @@ public class EditSession implements Extent, AutoCloseable { private final Extent bypassHistory; private final Extent bypassNone; - private ReorderMode reorderMode = ReorderMode.MULTI_STAGE; + private ReorderMode reorderMode = ReorderMode.FAST; private Mask oldMask; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 1133c6e7b..07ea35981 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -93,7 +93,7 @@ public class LocalSession { private transient Mask mask; private transient TimeZone timezone = TimeZone.getDefault(); private transient BlockVector3 cuiTemporaryBlock; - private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE; + private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.FAST; // Saved properties private String lastScript; From 618cbd2250e89a233e6f7663ef09f812cd766403 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Tue, 4 Dec 2018 20:24:50 +1000 Subject: [PATCH 07/10] Few small fixes --- .../src/main/java/com/sk89q/worldedit/EditSession.java | 8 +++++--- .../worldedit/extent/reorder/ChunkBatchingExtent.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) 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 31bc0bd07..354121c8d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -271,10 +271,10 @@ public class EditSession implements Extent, AutoCloseable { // pkg private for TracedEditSession only, may later become public API boolean commitRequired() { - if (reorderExtent.commitRequired()) { + if (reorderExtent != null && reorderExtent.commitRequired()) { return true; } - if (isBatchingChunks() && chunkBatchingExtent.commitRequired()) { + if (chunkBatchingExtent != null && chunkBatchingExtent.commitRequired()) { return true; } if (fastModeExtent != null && fastModeExtent.commitRequired()) { @@ -294,7 +294,7 @@ public class EditSession implements Extent, AutoCloseable { } /** - * Sets the {@link ReorderMode} of this EditSession. + * Sets the {@link ReorderMode} of this EditSession, and flushes the session. * * @param reorderMode The reorder mode */ @@ -305,6 +305,8 @@ public class EditSession implements Extent, AutoCloseable { if (reorderMode == ReorderMode.MULTI_STAGE && reorderExtent == null) { throw new IllegalArgumentException("An EditSession without a reorder extent tried to use it for reordering!"); } + flushSession(); + this.reorderMode = reorderMode; switch (reorderMode) { case MULTI_STAGE: diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java index 730edefea..4379a0550 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java @@ -73,7 +73,7 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent { } public boolean commitRequired() { - return batches.size() > 0; + return enabled && batches.size() > 0; } @Override From 5f2c77b7190b814f8794c9f04ce04a57aca00d84 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 9 Dec 2018 15:11:11 +1000 Subject: [PATCH 08/10] Further work on this. Currently fast mode breaks doors, gotta work out why applying physics to doors breaks them. --- .../java/com/sk89q/worldedit/EditSession.java | 30 +-- .../com/sk89q/worldedit/LocalSession.java | 3 + .../com/sk89q/worldedit/blocks/Blocks.java | 142 -------------- .../worldedit/command/GeneralCommands.java | 9 +- .../extent/reorder/MultiStageReorder.java | 176 ++++++++++++++---- .../extent/world/FastModeExtent.java | 5 +- 6 files changed, 168 insertions(+), 197 deletions(-) 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 354121c8d..b7e2753a3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -120,6 +120,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -161,23 +162,23 @@ public class EditSession implements Extent, AutoCloseable { FAST("fast"), NONE("none"); - private String name; + private String displayName; - ReorderMode(String name) { - this.name = name; + ReorderMode(String displayName) { + this.displayName = displayName; } - public String getName() { - return this.name; + public String getDisplayName() { + return this.displayName; } - public static ReorderMode getFromName(String name) { + public static Optional getFromDisplayName(String name) { for (ReorderMode mode : values()) { - if (mode.getName().equalsIgnoreCase(name)) { - return mode; + if (mode.getDisplayName().equalsIgnoreCase(name)) { + return Optional.of(mode); } } - return null; + return Optional.empty(); } } @@ -202,7 +203,7 @@ public class EditSession implements Extent, AutoCloseable { private final Extent bypassHistory; private final Extent bypassNone; - private ReorderMode reorderMode = ReorderMode.FAST; + private ReorderMode reorderMode = ReorderMode.MULTI_STAGE; private Mask oldMask; @@ -260,6 +261,8 @@ public class EditSession implements Extent, AutoCloseable { this.bypassHistory = extent; this.bypassNone = extent; } + + setReorderMode(this.reorderMode); } private Extent wrapExtent(Extent extent, EventBus eventBus, EditSessionEvent event, Stage stage) { @@ -285,11 +288,10 @@ public class EditSession implements Extent, AutoCloseable { /** * Turns on specific features for a normal WorldEdit session, such as - * {@link #setReorderMode(ReorderMode)} reordering} and {@link #setBatchingChunks(boolean) + * {@link #setBatchingChunks(boolean) * chunk batching}. */ public void enableStandardMode() { - setReorderMode(ReorderMode.MULTI_STAGE); setBatchingChunks(true); } @@ -305,7 +307,9 @@ public class EditSession implements Extent, AutoCloseable { if (reorderMode == ReorderMode.MULTI_STAGE && reorderExtent == null) { throw new IllegalArgumentException("An EditSession without a reorder extent tried to use it for reordering!"); } - flushSession(); + if (commitRequired()) { + flushSession(); + } this.reorderMode = reorderMode; switch (reorderMode) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 07ea35981..2dc413932 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -229,6 +229,7 @@ public class LocalSession { EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() .getEditSession(editSession.getWorld(), -1, newBlockBag, player); newEditSession.enableStandardMode(); + newEditSession.setReorderMode(reorderMode); newEditSession.setFastMode(fastMode); editSession.undo(newEditSession); return editSession; @@ -252,6 +253,7 @@ public class LocalSession { EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() .getEditSession(editSession.getWorld(), -1, newBlockBag, player); newEditSession.enableStandardMode(); + newEditSession.setReorderMode(reorderMode); newEditSession.setFastMode(fastMode); editSession.redo(newEditSession); ++historyPointer; @@ -854,6 +856,7 @@ public class LocalSession { .getEditSession(player.isPlayer() ? player.getWorld() : null, getBlockChangeLimit(), blockBag, player); editSession.setFastMode(fastMode); + editSession.setReorderMode(reorderMode); Request.request().setEditSession(editSession); editSession.setMask(mask); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java index 939fb7e7e..c71bd6ef6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java @@ -19,14 +19,9 @@ package com.sk89q.worldedit.blocks; -import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; import java.util.Collection; -import java.util.HashSet; -import java.util.Set; /** * Block-related utility methods. @@ -36,143 +31,6 @@ public final class Blocks { private Blocks() { } - /** - * HashSet for shouldPlaceLate. - */ - private static final Set shouldPlaceLate = new HashSet<>(); - static { - shouldPlaceLate.add(BlockTypes.WATER); - shouldPlaceLate.add(BlockTypes.LAVA); - shouldPlaceLate.add(BlockTypes.GRAVEL); - shouldPlaceLate.add(BlockTypes.SAND); - } - /** - * Checks to see whether a block should be placed in the final queue. - * - * This applies to blocks that can be attached to other blocks that have an attachment. - * - * @param type the type of the block - * @return whether the block is in the late queue - */ - public static boolean shouldPlaceLate(BlockType type) { - return shouldPlaceLate.contains(type); - } - - /** - * HashSet for shouldPlaceLast. - */ - private static final Set shouldPlaceLast = new HashSet<>(); - static { - shouldPlaceLast.addAll(BlockCategories.SAPLINGS.getAll()); - shouldPlaceLast.addAll(BlockCategories.FLOWER_POTS.getAll()); - shouldPlaceLast.addAll(BlockCategories.BUTTONS.getAll()); - shouldPlaceLast.addAll(BlockCategories.ANVIL.getAll()); // becomes relevant with asynchronous placement - shouldPlaceLast.addAll(BlockCategories.WOODEN_PRESSURE_PLATES.getAll()); - shouldPlaceLast.addAll(BlockCategories.CARPETS.getAll()); - shouldPlaceLast.addAll(BlockCategories.RAILS.getAll()); - shouldPlaceLast.add(BlockTypes.BLACK_BED); - shouldPlaceLast.add(BlockTypes.BLUE_BED); - shouldPlaceLast.add(BlockTypes.BROWN_BED); - shouldPlaceLast.add(BlockTypes.CYAN_BED); - shouldPlaceLast.add(BlockTypes.GRAY_BED); - shouldPlaceLast.add(BlockTypes.GREEN_BED); - shouldPlaceLast.add(BlockTypes.LIGHT_BLUE_BED); - shouldPlaceLast.add(BlockTypes.LIGHT_GRAY_BED); - shouldPlaceLast.add(BlockTypes.LIME_BED); - shouldPlaceLast.add(BlockTypes.MAGENTA_BED); - shouldPlaceLast.add(BlockTypes.ORANGE_BED); - shouldPlaceLast.add(BlockTypes.PINK_BED); - shouldPlaceLast.add(BlockTypes.PURPLE_BED); - shouldPlaceLast.add(BlockTypes.RED_BED); - shouldPlaceLast.add(BlockTypes.WHITE_BED); - shouldPlaceLast.add(BlockTypes.YELLOW_BED); - shouldPlaceLast.add(BlockTypes.GRASS); - shouldPlaceLast.add(BlockTypes.TALL_GRASS); - shouldPlaceLast.add(BlockTypes.ROSE_BUSH); - shouldPlaceLast.add(BlockTypes.DANDELION); - shouldPlaceLast.add(BlockTypes.BROWN_MUSHROOM); - shouldPlaceLast.add(BlockTypes.RED_MUSHROOM); - shouldPlaceLast.add(BlockTypes.FERN); - shouldPlaceLast.add(BlockTypes.LARGE_FERN); - shouldPlaceLast.add(BlockTypes.OXEYE_DAISY); - shouldPlaceLast.add(BlockTypes.AZURE_BLUET); - shouldPlaceLast.add(BlockTypes.TORCH); - shouldPlaceLast.add(BlockTypes.WALL_TORCH); - shouldPlaceLast.add(BlockTypes.FIRE); - shouldPlaceLast.add(BlockTypes.REDSTONE_WIRE); - shouldPlaceLast.add(BlockTypes.CARROTS); - shouldPlaceLast.add(BlockTypes.POTATOES); - shouldPlaceLast.add(BlockTypes.WHEAT); - shouldPlaceLast.add(BlockTypes.BEETROOTS); - shouldPlaceLast.add(BlockTypes.COCOA); - shouldPlaceLast.add(BlockTypes.LADDER); - shouldPlaceLast.add(BlockTypes.LEVER); - shouldPlaceLast.add(BlockTypes.REDSTONE_TORCH); - shouldPlaceLast.add(BlockTypes.REDSTONE_WALL_TORCH); - shouldPlaceLast.add(BlockTypes.SNOW); - shouldPlaceLast.add(BlockTypes.NETHER_PORTAL); - shouldPlaceLast.add(BlockTypes.END_PORTAL); - shouldPlaceLast.add(BlockTypes.REPEATER); - shouldPlaceLast.add(BlockTypes.VINE); - shouldPlaceLast.add(BlockTypes.LILY_PAD); - shouldPlaceLast.add(BlockTypes.NETHER_WART); - shouldPlaceLast.add(BlockTypes.PISTON); - shouldPlaceLast.add(BlockTypes.STICKY_PISTON); - shouldPlaceLast.add(BlockTypes.TRIPWIRE_HOOK); - shouldPlaceLast.add(BlockTypes.TRIPWIRE); - shouldPlaceLast.add(BlockTypes.STONE_PRESSURE_PLATE); - shouldPlaceLast.add(BlockTypes.HEAVY_WEIGHTED_PRESSURE_PLATE); - shouldPlaceLast.add(BlockTypes.LIGHT_WEIGHTED_PRESSURE_PLATE); - shouldPlaceLast.add(BlockTypes.COMPARATOR); - shouldPlaceLast.add(BlockTypes.IRON_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.ACACIA_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.BIRCH_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.DARK_OAK_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.JUNGLE_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.OAK_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.SPRUCE_TRAPDOOR); - shouldPlaceLast.add(BlockTypes.DAYLIGHT_DETECTOR); - } - - /** - * Checks to see whether a block should be placed last (when reordering - * blocks that are placed). - * - * @param type the block type - * @return true if the block should be placed last - */ - public static boolean shouldPlaceLast(BlockType type) { - return shouldPlaceLast.contains(type); - } - - /** - * HashSet for shouldPlaceLast. - */ - private static final Set shouldPlaceFinal = new HashSet<>(); - static { - shouldPlaceFinal.addAll(BlockCategories.DOORS.getAll()); - shouldPlaceFinal.addAll(BlockCategories.BANNERS.getAll()); - shouldPlaceFinal.add(BlockTypes.SIGN); - shouldPlaceFinal.add(BlockTypes.WALL_SIGN); - shouldPlaceFinal.add(BlockTypes.CACTUS); - shouldPlaceFinal.add(BlockTypes.SUGAR_CANE); - shouldPlaceFinal.add(BlockTypes.CAKE); - shouldPlaceFinal.add(BlockTypes.PISTON_HEAD); - shouldPlaceFinal.add(BlockTypes.MOVING_PISTON); - } - - /** - * Checks to see whether a block should be placed in the final queue. - * - * This applies to blocks that can be attached to other blocks that have an attachment. - * - * @param type the type of the block - * @return whether the block is in the final queue - */ - public static boolean shouldPlaceFinal(BlockType type) { - return shouldPlaceFinal.contains(type); - } - /** * Checks whether a given block is in a list of base blocks. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index a2e051493..5e4f608ed 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -126,16 +126,17 @@ public class GeneralCommands { public void reorderMode(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { String newState = args.getString(0, null); if (newState == null) { - player.print("The reorder mode is " + session.getReorderMode().getName()); + player.print("The reorder mode is " + session.getReorderMode().getDisplayName()); } else { - EditSession.ReorderMode reorderMode = EditSession.ReorderMode.getFromName(newState); - if (reorderMode == null) { + java.util.Optional reorderModeOptional = EditSession.ReorderMode.getFromDisplayName(newState); + if (!reorderModeOptional.isPresent()) { player.printError("Unknown reorder mode!"); return; } + EditSession.ReorderMode reorderMode = reorderModeOptional.get(); session.setReorderMode(reorderMode); - player.print("The reorder mode is now " + session.getReorderMode().getName()); + player.print("The reorder mode is now " + session.getReorderMode().getDisplayName()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java index 2be03cbae..f58161b7c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.extent.reorder; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.Blocks; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.operation.Operation; @@ -34,6 +33,7 @@ import com.sk89q.worldedit.util.collection.LocatedBlockList; import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.util.ArrayList; @@ -50,12 +50,112 @@ import java.util.Set; */ public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent { - private static final int STAGE_COUNT = 4; + private static Map priorityMap = new HashMap<>(); - private List stages = new ArrayList<>(); + static { + // Late + priorityMap.put(BlockTypes.WATER, PlacementPriority.LATE); + priorityMap.put(BlockTypes.LAVA, PlacementPriority.LATE); + priorityMap.put(BlockTypes.SAND, PlacementPriority.LATE); + priorityMap.put(BlockTypes.GRAVEL, PlacementPriority.LATE); + + // Late + BlockCategories.SAPLINGS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + BlockCategories.FLOWER_POTS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + BlockCategories.BUTTONS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + BlockCategories.ANVIL.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + BlockCategories.WOODEN_PRESSURE_PLATES.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + BlockCategories.CARPETS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + BlockCategories.RAILS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.LAST)); + priorityMap.put(BlockTypes.BLACK_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.BLUE_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.BROWN_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.CYAN_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.GRAY_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.GREEN_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LIGHT_BLUE_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LIGHT_GRAY_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LIME_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.MAGENTA_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.ORANGE_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.PINK_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.PURPLE_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.RED_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.WHITE_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.YELLOW_BED, PlacementPriority.LAST); + priorityMap.put(BlockTypes.GRASS, PlacementPriority.LAST); + priorityMap.put(BlockTypes.TALL_GRASS, PlacementPriority.LAST); + priorityMap.put(BlockTypes.ROSE_BUSH, PlacementPriority.LAST); + priorityMap.put(BlockTypes.DANDELION, PlacementPriority.LAST); + priorityMap.put(BlockTypes.BROWN_MUSHROOM, PlacementPriority.LAST); + priorityMap.put(BlockTypes.RED_MUSHROOM, PlacementPriority.LAST); + priorityMap.put(BlockTypes.FERN, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LARGE_FERN, PlacementPriority.LAST); + priorityMap.put(BlockTypes.OXEYE_DAISY, PlacementPriority.LAST); + priorityMap.put(BlockTypes.AZURE_BLUET, PlacementPriority.LAST); + priorityMap.put(BlockTypes.TORCH, PlacementPriority.LAST); + priorityMap.put(BlockTypes.WALL_TORCH, PlacementPriority.LAST); + priorityMap.put(BlockTypes.FIRE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.REDSTONE_WIRE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.CARROTS, PlacementPriority.LAST); + priorityMap.put(BlockTypes.POTATOES, PlacementPriority.LAST); + priorityMap.put(BlockTypes.WHEAT, PlacementPriority.LAST); + priorityMap.put(BlockTypes.BEETROOTS, PlacementPriority.LAST); + priorityMap.put(BlockTypes.COCOA, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LADDER, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LEVER, PlacementPriority.LAST); + priorityMap.put(BlockTypes.REDSTONE_TORCH, PlacementPriority.LAST); + priorityMap.put(BlockTypes.REDSTONE_WALL_TORCH, PlacementPriority.LAST); + priorityMap.put(BlockTypes.SNOW, PlacementPriority.LAST); + priorityMap.put(BlockTypes.NETHER_PORTAL, PlacementPriority.LAST); + priorityMap.put(BlockTypes.END_PORTAL, PlacementPriority.LAST); + priorityMap.put(BlockTypes.REPEATER, PlacementPriority.LAST); + priorityMap.put(BlockTypes.VINE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LILY_PAD, PlacementPriority.LAST); + priorityMap.put(BlockTypes.NETHER_WART, PlacementPriority.LAST); + priorityMap.put(BlockTypes.PISTON, PlacementPriority.LAST); + priorityMap.put(BlockTypes.STICKY_PISTON, PlacementPriority.LAST); + priorityMap.put(BlockTypes.TRIPWIRE_HOOK, PlacementPriority.LAST); + priorityMap.put(BlockTypes.TRIPWIRE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.STONE_PRESSURE_PLATE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.HEAVY_WEIGHTED_PRESSURE_PLATE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.LIGHT_WEIGHTED_PRESSURE_PLATE, PlacementPriority.LAST); + priorityMap.put(BlockTypes.COMPARATOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.IRON_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.ACACIA_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.BIRCH_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.DARK_OAK_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.JUNGLE_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.OAK_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.SPRUCE_TRAPDOOR, PlacementPriority.LAST); + priorityMap.put(BlockTypes.DAYLIGHT_DETECTOR, PlacementPriority.LAST); + + // Final + BlockCategories.DOORS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.FINAL)); + BlockCategories.BANNERS.getAll().forEach(type -> priorityMap.put(type, PlacementPriority.FINAL)); + priorityMap.put(BlockTypes.SIGN, PlacementPriority.FINAL); + priorityMap.put(BlockTypes.WALL_SIGN, PlacementPriority.FINAL); + priorityMap.put(BlockTypes.CACTUS, PlacementPriority.FINAL); + priorityMap.put(BlockTypes.SUGAR_CANE, PlacementPriority.FINAL); + priorityMap.put(BlockTypes.CAKE, PlacementPriority.FINAL); + priorityMap.put(BlockTypes.PISTON_HEAD, PlacementPriority.FINAL); + priorityMap.put(BlockTypes.MOVING_PISTON, PlacementPriority.FINAL); + } + + private Map stages = new HashMap<>(); private boolean enabled; + public enum PlacementPriority { + CLEAR_FINAL, + CLEAR_LAST, + CLEAR_LATE, + FIRST, + LATE, + LAST, + FINAL + } + /** * Create a new instance when the re-ordering is enabled. * @@ -75,8 +175,8 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder super(extent); this.enabled = enabled; - for (int i = 0; i < STAGE_COUNT; ++i) { - stages.add(new LocatedBlockList()); + for (PlacementPriority priority : PlacementPriority.values()) { + stages.put(priority, new LocatedBlockList()); } } @@ -99,7 +199,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } public boolean commitRequired() { - return enabled && stages.stream().anyMatch(stage -> stage.size() > 0); + return enabled && stages.values().stream().anyMatch(stage -> stage.size() > 0); } /** @@ -108,18 +208,8 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder * @param block The block * @return The priority */ - public int getPlacementPriority(BlockStateHolder block) { - if (Blocks.shouldPlaceLate(block.getBlockType())) { - return 1; - } else if (Blocks.shouldPlaceLast(block.getBlockType())) { - // Place torches, etc. last - return 2; - } else if (Blocks.shouldPlaceFinal(block.getBlockType())) { - // Place signs, reed, etc even later - return 3; - } else { - return 0; - } + private PlacementPriority getPlacementPriority(BlockStateHolder block) { + return priorityMap.getOrDefault(block.getBlockType(), PlacementPriority.FIRST); } @Override @@ -129,13 +219,27 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } BlockState existing = getBlock(location); - int priority = getPlacementPriority(block); - int srcPriority = getPlacementPriority(existing); + PlacementPriority priority = getPlacementPriority(block); + PlacementPriority srcPriority = getPlacementPriority(existing); - if (srcPriority == 1 || srcPriority == 2) { - // Destroy torches, etc. first - super.setBlock(location, BlockTypes.AIR.getDefaultState()); - return super.setBlock(location, block); + if (srcPriority != PlacementPriority.FIRST) { + BlockStateHolder replacement = block.getBlockType().getMaterial().isAir() ? block : BlockTypes.AIR.getDefaultState(); + + switch (srcPriority) { + case FINAL: + stages.get(PlacementPriority.CLEAR_FINAL).add(location, replacement); + break; + case LATE: + stages.get(PlacementPriority.CLEAR_LATE).add(location, replacement); + break; + case LAST: + stages.get(PlacementPriority.CLEAR_LAST).add(location, replacement); + break; + } + + if (block.getBlockType().getMaterial().isAir()) { + return !existing.equalsFuzzy(block); + } } stages.get(priority).add(location, block); @@ -144,9 +248,14 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder @Override public Operation commitBefore() { + if (!enabled) { + return null; + } List operations = new ArrayList<>(); - for (int i = 0; i < stages.size() - 1; ++i) { - operations.add(new SetLocatedBlocks(getExtent(), stages.get(i))); + for (PlacementPriority priority : PlacementPriority.values()) { + if (priority != PlacementPriority.FINAL) { + operations.add(new SetLocatedBlocks(getExtent(), stages.get(priority))); + } } operations.add(new FinalStageCommitter()); @@ -160,7 +269,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder private final Map blockTypes = new HashMap<>(); public FinalStageCommitter() { - for (LocatedBlock entry : stages.get(stages.size() - 1)) { + for (LocatedBlock entry : stages.get(PlacementPriority.FINAL)) { final BlockVector3 pt = entry.getLocation(); blocks.add(pt); blockTypes.put(pt, entry.getBlock()); @@ -171,9 +280,6 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder public Operation resume(RunContext run) throws WorldEditException { while (!blocks.isEmpty()) { BlockVector3 current = blocks.iterator().next(); - if (!blocks.contains(current)) { - continue; - } final Deque walked = new LinkedList<>(); @@ -224,14 +330,10 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } } - if (blocks.isEmpty()) { - for (LocatedBlockList stage : stages) { - stage.clear(); - } - return null; + for (LocatedBlockList stage : stages.values()) { + stage.clear(); } - - return this; + return null; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java index ad92c6a45..08ecaeaf1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java @@ -114,11 +114,14 @@ public class FastModeExtent extends AbstractDelegateExtent { } public boolean commitRequired() { - return !dirtyChunks.isEmpty() || !positions.isEmpty(); + return (enabled && !dirtyChunks.isEmpty()) || (postEditSimulation && !positions.isEmpty()); } @Override protected Operation commitBefore() { + if (!enabled && !postEditSimulation) { + return null; + } return new Operation() { @Override public Operation resume(RunContext run) throws WorldEditException { From 6f3016c7f01fb4786a2ce1d3c41718e1b5b17298 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 9 Dec 2018 15:15:34 +1000 Subject: [PATCH 09/10] Fixed up the commitRequired checks. --- .../src/main/java/com/sk89q/worldedit/EditSession.java | 2 ++ .../sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java | 4 ++-- .../com/sk89q/worldedit/extent/reorder/MultiStageReorder.java | 4 ++-- .../java/com/sk89q/worldedit/extent/world/FastModeExtent.java | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) 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 b7e2753a3..4d1bde24d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -386,7 +386,9 @@ public class EditSession implements Extent, AutoCloseable { * Returns queue status. * * @return whether the queue is enabled + * @deprecated Use {@link EditSession#getReorderMode()} with MULTI_STAGE instead. */ + @Deprecated public boolean isQueueEnabled() { return reorderMode == ReorderMode.MULTI_STAGE && reorderExtent.isEnabled(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java index 4379a0550..daeb9f0e6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java @@ -73,7 +73,7 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent { } public boolean commitRequired() { - return enabled && batches.size() > 0; + return enabled; } @Override @@ -88,7 +88,7 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent { @Override protected Operation commitBefore() { - if (!enabled) { + if (!commitRequired()) { return null; } return new Operation() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java index f58161b7c..aa1694740 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/MultiStageReorder.java @@ -199,7 +199,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder } public boolean commitRequired() { - return enabled && stages.values().stream().anyMatch(stage -> stage.size() > 0); + return enabled; } /** @@ -248,7 +248,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder @Override public Operation commitBefore() { - if (!enabled) { + if (!commitRequired()) { return null; } List operations = new ArrayList<>(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java index 08ecaeaf1..5b92a8ad3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java @@ -114,12 +114,12 @@ public class FastModeExtent extends AbstractDelegateExtent { } public boolean commitRequired() { - return (enabled && !dirtyChunks.isEmpty()) || (postEditSimulation && !positions.isEmpty()); + return enabled || postEditSimulation; } @Override protected Operation commitBefore() { - if (!enabled && !postEditSimulation) { + if (!commitRequired()) { return null; } return new Operation() { From 926f6a6ab868af69731d684104ef6fb06f15d815 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 9 Dec 2018 15:33:35 +1000 Subject: [PATCH 10/10] Flush undo/redo --- .../com/sk89q/worldedit/LocalSession.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 2dc413932..9b117c918 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -93,7 +93,7 @@ public class LocalSession { private transient Mask mask; private transient TimeZone timezone = TimeZone.getDefault(); private transient BlockVector3 cuiTemporaryBlock; - private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.FAST; + private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE; // Saved properties private String lastScript; @@ -226,12 +226,13 @@ public class LocalSession { --historyPointer; if (historyPointer >= 0) { EditSession editSession = history.get(historyPointer); - EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() - .getEditSession(editSession.getWorld(), -1, newBlockBag, player); - newEditSession.enableStandardMode(); - newEditSession.setReorderMode(reorderMode); - newEditSession.setFastMode(fastMode); - editSession.undo(newEditSession); + try (EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() + .getEditSession(editSession.getWorld(), -1, newBlockBag, player)) { + newEditSession.enableStandardMode(); + newEditSession.setReorderMode(reorderMode); + newEditSession.setFastMode(fastMode); + editSession.undo(newEditSession); + } return editSession; } else { historyPointer = 0; @@ -250,12 +251,13 @@ public class LocalSession { checkNotNull(player); if (historyPointer < history.size()) { EditSession editSession = history.get(historyPointer); - EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() - .getEditSession(editSession.getWorld(), -1, newBlockBag, player); - newEditSession.enableStandardMode(); - newEditSession.setReorderMode(reorderMode); - newEditSession.setFastMode(fastMode); - editSession.redo(newEditSession); + try (EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() + .getEditSession(editSession.getWorld(), -1, newBlockBag, player)) { + newEditSession.enableStandardMode(); + newEditSession.setReorderMode(reorderMode); + newEditSession.setFastMode(fastMode); + editSession.redo(newEditSession); + } ++historyPointer; return editSession; }