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 9639be219..b2524201e 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,26 +19,24 @@ package com.sk89q.worldedit.extent.reorder; -import com.google.common.collect.Iterators; -import com.google.common.collect.Iterables; 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.BlockMapEntryPlacer; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.OperationQueue; import com.sk89q.worldedit.function.operation.RunContext; -//import com.sk89q.worldedit.function.operation.SetLocatedBlocks; +import com.sk89q.worldedit.function.operation.SetLocatedBlocks; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.LocatedBlock; -import com.sk89q.worldedit.util.collection.TupleArrayList; +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.BlockTypes; +import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; @@ -52,11 +50,21 @@ import java.util.Set; */ public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent { - private TupleArrayList stage1 = new TupleArrayList<>(); - private TupleArrayList stage2 = new TupleArrayList<>(); - private TupleArrayList stage3 = new TupleArrayList<>(); + 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. * @@ -66,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()); + } } /** @@ -95,74 +98,77 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder this.enabled = enabled; } + public boolean commitRequired() { + 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 -//<<<<<<< HEAD - stage2.put(location, block); - return !existing.equalsFuzzy(block); - } else if (Blocks.shouldPlaceFinal(block.getBlockType())) { - // Place signs, reed, etc even later - stage3.put(location, block); -//======= -// stage2.add(location, block); -// return !existing.equalsFuzzy(block); -// } else if (Blocks.shouldPlaceFinal(block.getBlockType())) { -// // Place signs, reed, etc even later -// stage3.add(location, block); -//>>>>>>> 399e0ad5... Refactor vector system to be cleaner - 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 { -//<<<<<<< HEAD - stage1.put(location, block); -//======= -// stage1.add(location, block); -//>>>>>>> 399e0ad5... Refactor vector system to be cleaner - return !existing.equalsFuzzy(block); } + + stages.get(priority).add(location, block); + return !existing.equalsFuzzy(block); } @Override public Operation commitBefore() { - return new OperationQueue( - new BlockMapEntryPlacer( - getExtent(), - Iterators.concat(stage1.iterator(), stage2.iterator())), - 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(); + + private final Set blocks = new HashSet<>(); + private final Map blockTypes = new HashMap<>(); + + 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 { - Extent extent = getExtent(); - -//<<<<<<< HEAD - final Set blocks = new HashSet<>(); - final Map blockTypes = new HashMap<>(); - for (Map.Entry entry : stage3) { - final BlockVector3 pt = entry.getKey(); -//======= -// final Set blocks = new HashSet<>(); -// final Map blockTypes = new HashMap<>(); -// for (LocatedBlock entry : stage3) { -// final BlockVector3 pt = entry.getLocation(); -//>>>>>>> 399e0ad5... Refactor vector system to be cleaner - blocks.add(pt); - blockTypes.put(pt, entry.getValue()); - } - while (!blocks.isEmpty()) { BlockVector3 current = blocks.iterator().next(); if (!blocks.contains(current)) { @@ -218,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/ChangeSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java index 24c4c3fe0..f0ec7eb9f 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,7 +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. *