From 5f2c77b7190b814f8794c9f04ce04a57aca00d84 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 9 Dec 2018 15:11:11 +1000 Subject: [PATCH] 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 {