Further work on this. Currently fast mode breaks doors, gotta work out why applying physics to doors breaks them.

This commit is contained in:
Matthew Miller 2018-12-09 15:11:11 +10:00
parent 618cbd2250
commit 5f2c77b719
6 changed files with 168 additions and 197 deletions

View File

@ -120,6 +120,7 @@ import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -161,23 +162,23 @@ public class EditSession implements Extent, AutoCloseable {
FAST("fast"), FAST("fast"),
NONE("none"); NONE("none");
private String name; private String displayName;
ReorderMode(String name) { ReorderMode(String displayName) {
this.name = name; this.displayName = displayName;
} }
public String getName() { public String getDisplayName() {
return this.name; return this.displayName;
} }
public static ReorderMode getFromName(String name) { public static Optional<ReorderMode> getFromDisplayName(String name) {
for (ReorderMode mode : values()) { for (ReorderMode mode : values()) {
if (mode.getName().equalsIgnoreCase(name)) { if (mode.getDisplayName().equalsIgnoreCase(name)) {
return mode; 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 bypassHistory;
private final Extent bypassNone; private final Extent bypassNone;
private ReorderMode reorderMode = ReorderMode.FAST; private ReorderMode reorderMode = ReorderMode.MULTI_STAGE;
private Mask oldMask; private Mask oldMask;
@ -260,6 +261,8 @@ public class EditSession implements Extent, AutoCloseable {
this.bypassHistory = extent; this.bypassHistory = extent;
this.bypassNone = extent; this.bypassNone = extent;
} }
setReorderMode(this.reorderMode);
} }
private Extent wrapExtent(Extent extent, EventBus eventBus, EditSessionEvent event, Stage stage) { 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 * Turns on specific features for a normal WorldEdit session, such as
* {@link #setReorderMode(ReorderMode)} reordering} and {@link #setBatchingChunks(boolean) * {@link #setBatchingChunks(boolean)
* chunk batching}. * chunk batching}.
*/ */
public void enableStandardMode() { public void enableStandardMode() {
setReorderMode(ReorderMode.MULTI_STAGE);
setBatchingChunks(true); setBatchingChunks(true);
} }
@ -305,7 +307,9 @@ public class EditSession implements Extent, AutoCloseable {
if (reorderMode == ReorderMode.MULTI_STAGE && reorderExtent == null) { if (reorderMode == ReorderMode.MULTI_STAGE && reorderExtent == null) {
throw new IllegalArgumentException("An EditSession without a reorder extent tried to use it for reordering!"); throw new IllegalArgumentException("An EditSession without a reorder extent tried to use it for reordering!");
} }
flushSession(); if (commitRequired()) {
flushSession();
}
this.reorderMode = reorderMode; this.reorderMode = reorderMode;
switch (reorderMode) { switch (reorderMode) {

View File

@ -229,6 +229,7 @@ public class LocalSession {
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(editSession.getWorld(), -1, newBlockBag, player); .getEditSession(editSession.getWorld(), -1, newBlockBag, player);
newEditSession.enableStandardMode(); newEditSession.enableStandardMode();
newEditSession.setReorderMode(reorderMode);
newEditSession.setFastMode(fastMode); newEditSession.setFastMode(fastMode);
editSession.undo(newEditSession); editSession.undo(newEditSession);
return editSession; return editSession;
@ -252,6 +253,7 @@ public class LocalSession {
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory() EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(editSession.getWorld(), -1, newBlockBag, player); .getEditSession(editSession.getWorld(), -1, newBlockBag, player);
newEditSession.enableStandardMode(); newEditSession.enableStandardMode();
newEditSession.setReorderMode(reorderMode);
newEditSession.setFastMode(fastMode); newEditSession.setFastMode(fastMode);
editSession.redo(newEditSession); editSession.redo(newEditSession);
++historyPointer; ++historyPointer;
@ -854,6 +856,7 @@ public class LocalSession {
.getEditSession(player.isPlayer() ? player.getWorld() : null, .getEditSession(player.isPlayer() ? player.getWorld() : null,
getBlockChangeLimit(), blockBag, player); getBlockChangeLimit(), blockBag, player);
editSession.setFastMode(fastMode); editSession.setFastMode(fastMode);
editSession.setReorderMode(reorderMode);
Request.request().setEditSession(editSession); Request.request().setEditSession(editSession);
editSession.setMask(mask); editSession.setMask(mask);

View File

@ -19,14 +19,9 @@
package com.sk89q.worldedit.blocks; 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.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/** /**
* Block-related utility methods. * Block-related utility methods.
@ -36,143 +31,6 @@ public final class Blocks {
private Blocks() { private Blocks() {
} }
/**
* HashSet for shouldPlaceLate.
*/
private static final Set<BlockType> 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<BlockType> 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<BlockType> 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. * Checks whether a given block is in a list of base blocks.
* *

View File

@ -126,16 +126,17 @@ public class GeneralCommands {
public void reorderMode(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { public void reorderMode(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
String newState = args.getString(0, null); String newState = args.getString(0, null);
if (newState == null) { if (newState == null) {
player.print("The reorder mode is " + session.getReorderMode().getName()); player.print("The reorder mode is " + session.getReorderMode().getDisplayName());
} else { } else {
EditSession.ReorderMode reorderMode = EditSession.ReorderMode.getFromName(newState); java.util.Optional<EditSession.ReorderMode> reorderModeOptional = EditSession.ReorderMode.getFromDisplayName(newState);
if (reorderMode == null) { if (!reorderModeOptional.isPresent()) {
player.printError("Unknown reorder mode!"); player.printError("Unknown reorder mode!");
return; return;
} }
EditSession.ReorderMode reorderMode = reorderModeOptional.get();
session.setReorderMode(reorderMode); session.setReorderMode(reorderMode);
player.print("The reorder mode is now " + session.getReorderMode().getName()); player.print("The reorder mode is now " + session.getReorderMode().getDisplayName());
} }
} }

View File

@ -20,7 +20,6 @@
package com.sk89q.worldedit.extent.reorder; package com.sk89q.worldedit.extent.reorder;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.Blocks;
import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation; 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.BlockCategories;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList; import java.util.ArrayList;
@ -50,12 +50,112 @@ import java.util.Set;
*/ */
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent { public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
private static final int STAGE_COUNT = 4; private static Map<BlockType, PlacementPriority> priorityMap = new HashMap<>();
private List<LocatedBlockList> 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<PlacementPriority, LocatedBlockList> stages = new HashMap<>();
private boolean enabled; 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. * Create a new instance when the re-ordering is enabled.
* *
@ -75,8 +175,8 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
super(extent); super(extent);
this.enabled = enabled; this.enabled = enabled;
for (int i = 0; i < STAGE_COUNT; ++i) { for (PlacementPriority priority : PlacementPriority.values()) {
stages.add(new LocatedBlockList()); stages.put(priority, new LocatedBlockList());
} }
} }
@ -99,7 +199,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
} }
public boolean commitRequired() { 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 * @param block The block
* @return The priority * @return The priority
*/ */
public int getPlacementPriority(BlockStateHolder block) { private PlacementPriority getPlacementPriority(BlockStateHolder block) {
if (Blocks.shouldPlaceLate(block.getBlockType())) { return priorityMap.getOrDefault(block.getBlockType(), PlacementPriority.FIRST);
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 @Override
@ -129,13 +219,27 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
} }
BlockState existing = getBlock(location); BlockState existing = getBlock(location);
int priority = getPlacementPriority(block); PlacementPriority priority = getPlacementPriority(block);
int srcPriority = getPlacementPriority(existing); PlacementPriority srcPriority = getPlacementPriority(existing);
if (srcPriority == 1 || srcPriority == 2) { if (srcPriority != PlacementPriority.FIRST) {
// Destroy torches, etc. first BlockStateHolder replacement = block.getBlockType().getMaterial().isAir() ? block : BlockTypes.AIR.getDefaultState();
super.setBlock(location, BlockTypes.AIR.getDefaultState());
return super.setBlock(location, block); 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); stages.get(priority).add(location, block);
@ -144,9 +248,14 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
@Override @Override
public Operation commitBefore() { public Operation commitBefore() {
if (!enabled) {
return null;
}
List<Operation> operations = new ArrayList<>(); List<Operation> operations = new ArrayList<>();
for (int i = 0; i < stages.size() - 1; ++i) { for (PlacementPriority priority : PlacementPriority.values()) {
operations.add(new SetLocatedBlocks(getExtent(), stages.get(i))); if (priority != PlacementPriority.FINAL) {
operations.add(new SetLocatedBlocks(getExtent(), stages.get(priority)));
}
} }
operations.add(new FinalStageCommitter()); operations.add(new FinalStageCommitter());
@ -160,7 +269,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
private final Map<BlockVector3, BlockStateHolder> blockTypes = new HashMap<>(); private final Map<BlockVector3, BlockStateHolder> blockTypes = new HashMap<>();
public FinalStageCommitter() { public FinalStageCommitter() {
for (LocatedBlock entry : stages.get(stages.size() - 1)) { for (LocatedBlock entry : stages.get(PlacementPriority.FINAL)) {
final BlockVector3 pt = entry.getLocation(); final BlockVector3 pt = entry.getLocation();
blocks.add(pt); blocks.add(pt);
blockTypes.put(pt, entry.getBlock()); blockTypes.put(pt, entry.getBlock());
@ -171,9 +280,6 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
public Operation resume(RunContext run) throws WorldEditException { public Operation resume(RunContext run) throws WorldEditException {
while (!blocks.isEmpty()) { while (!blocks.isEmpty()) {
BlockVector3 current = blocks.iterator().next(); BlockVector3 current = blocks.iterator().next();
if (!blocks.contains(current)) {
continue;
}
final Deque<BlockVector3> walked = new LinkedList<>(); final Deque<BlockVector3> walked = new LinkedList<>();
@ -224,14 +330,10 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
} }
} }
if (blocks.isEmpty()) { for (LocatedBlockList stage : stages.values()) {
for (LocatedBlockList stage : stages) { stage.clear();
stage.clear();
}
return null;
} }
return null;
return this;
} }
@Override @Override

View File

@ -114,11 +114,14 @@ public class FastModeExtent extends AbstractDelegateExtent {
} }
public boolean commitRequired() { public boolean commitRequired() {
return !dirtyChunks.isEmpty() || !positions.isEmpty(); return (enabled && !dirtyChunks.isEmpty()) || (postEditSimulation && !positions.isEmpty());
} }
@Override @Override
protected Operation commitBefore() { protected Operation commitBefore() {
if (!enabled && !postEditSimulation) {
return null;
}
return new Operation() { return new Operation() {
@Override @Override
public Operation resume(RunContext run) throws WorldEditException { public Operation resume(RunContext run) throws WorldEditException {