geforkt von Mirrors/FastAsyncWorldEdit
Merge pull request #432 from sk89q/feature/multipass3
Added multi-pass fixing for MultiStageReorder, and a Fast-Mode equivalent
Dieser Commit ist enthalten in:
Commit
17f52cb228
@ -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
|
@Override
|
||||||
public BaseBiome getBiome(BlockVector2 position) {
|
public BaseBiome getBiome(BlockVector2 position) {
|
||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
|
@ -24,6 +24,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
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.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -78,6 +79,15 @@ public interface BukkitImplAdapter {
|
|||||||
*/
|
*/
|
||||||
boolean setBlock(Location location, BlockStateHolder state, boolean notifyAndLight);
|
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.
|
* Get the state for the given entity.
|
||||||
*
|
*
|
||||||
|
Binäre Datei nicht angezeigt.
Binäre Datei nicht angezeigt.
Binäre Datei nicht angezeigt.
@ -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;
|
||||||
@ -149,6 +150,38 @@ public class EditSession implements Extent, AutoCloseable {
|
|||||||
BEFORE_CHANGE
|
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 displayName;
|
||||||
|
|
||||||
|
ReorderMode(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return this.displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<ReorderMode> getFromDisplayName(String name) {
|
||||||
|
for (ReorderMode mode : values()) {
|
||||||
|
if (mode.getDisplayName().equalsIgnoreCase(name)) {
|
||||||
|
return Optional.of(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ProtectedField")
|
@SuppressWarnings("ProtectedField")
|
||||||
protected final World world;
|
protected final World world;
|
||||||
private final ChangeSet changeSet = new BlockOptimizedHistory();
|
private final ChangeSet changeSet = new BlockOptimizedHistory();
|
||||||
@ -170,6 +203,8 @@ 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.MULTI_STAGE;
|
||||||
|
|
||||||
private Mask oldMask;
|
private Mask oldMask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,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) {
|
||||||
@ -237,10 +274,13 @@ public class EditSession implements Extent, AutoCloseable {
|
|||||||
|
|
||||||
// pkg private for TracedEditSession only, may later become public API
|
// pkg private for TracedEditSession only, may later become public API
|
||||||
boolean commitRequired() {
|
boolean commitRequired() {
|
||||||
if (isQueueEnabled() && reorderExtent.commitRequired()) {
|
if (reorderExtent != null && reorderExtent.commitRequired()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (isBatchingChunks() && chunkBatchingExtent.commitRequired()) {
|
if (chunkBatchingExtent != null && chunkBatchingExtent.commitRequired()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (fastModeExtent != null && fastModeExtent.commitRequired()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -248,14 +288,63 @@ 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 #enableQueue() queuing} and {@link #setBatchingChunks(boolean)
|
* {@link #setBatchingChunks(boolean)
|
||||||
* chunk batching}.
|
* chunk batching}.
|
||||||
*/
|
*/
|
||||||
public void enableStandardMode() {
|
public void enableStandardMode() {
|
||||||
enableQueue();
|
|
||||||
setBatchingChunks(true);
|
setBatchingChunks(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link ReorderMode} of this EditSession, and flushes the session.
|
||||||
|
*
|
||||||
|
* @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!");
|
||||||
|
}
|
||||||
|
if (commitRequired()) {
|
||||||
|
flushSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
* Get the world.
|
||||||
*
|
*
|
||||||
@ -297,26 +386,35 @@ public class EditSession implements Extent, AutoCloseable {
|
|||||||
* Returns queue status.
|
* Returns queue status.
|
||||||
*
|
*
|
||||||
* @return whether the queue is enabled
|
* @return whether the queue is enabled
|
||||||
|
* @deprecated Use {@link EditSession#getReorderMode()} with MULTI_STAGE instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean isQueueEnabled() {
|
public boolean isQueueEnabled() {
|
||||||
return reorderExtent.isEnabled();
|
return reorderMode == ReorderMode.MULTI_STAGE && reorderExtent.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue certain types of block for better reproduction of those blocks.
|
* 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() {
|
public void enableQueue() {
|
||||||
reorderExtent.setEnabled(true);
|
setReorderMode(ReorderMode.MULTI_STAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable the queue. This will {@linkplain #flushSession() flush the session}.
|
* Disable the queue. This will {@linkplain #flushSession() flush the session}.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link EditSession#setReorderMode(ReorderMode)} with another mode instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void disableQueue() {
|
public void disableQueue() {
|
||||||
if (isQueueEnabled()) {
|
if (isQueueEnabled()) {
|
||||||
flushSession();
|
flushSession();
|
||||||
}
|
}
|
||||||
reorderExtent.setEnabled(false);
|
setReorderMode(ReorderMode.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,16 +534,15 @@ public class EditSession implements Extent, AutoCloseable {
|
|||||||
/**
|
/**
|
||||||
* Disable all buffering extents.
|
* Disable all buffering extents.
|
||||||
*
|
*
|
||||||
* @see #disableQueue()
|
* @see #setReorderMode(ReorderMode)
|
||||||
* @see #setBatchingChunks(boolean)
|
* @see #setBatchingChunks(boolean)
|
||||||
*/
|
*/
|
||||||
public void disableBuffering() {
|
public void disableBuffering() {
|
||||||
// We optimize here to avoid repeated calls to flushSession.
|
// We optimize here to avoid repeated calls to flushSession.
|
||||||
boolean needsFlush = isQueueEnabled() || isBatchingChunks();
|
if (commitRequired()) {
|
||||||
if (needsFlush) {
|
|
||||||
flushSession();
|
flushSession();
|
||||||
}
|
}
|
||||||
reorderExtent.setEnabled(false);
|
setReorderMode(ReorderMode.NONE);
|
||||||
if (chunkBatchingExtent != null) {
|
if (chunkBatchingExtent != null) {
|
||||||
chunkBatchingExtent.setEnabled(false);
|
chunkBatchingExtent.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,7 @@ public class LocalSession {
|
|||||||
private transient Mask mask;
|
private transient Mask mask;
|
||||||
private transient TimeZone timezone = TimeZone.getDefault();
|
private transient TimeZone timezone = TimeZone.getDefault();
|
||||||
private transient BlockVector3 cuiTemporaryBlock;
|
private transient BlockVector3 cuiTemporaryBlock;
|
||||||
|
private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE;
|
||||||
|
|
||||||
// Saved properties
|
// Saved properties
|
||||||
private String lastScript;
|
private String lastScript;
|
||||||
@ -225,11 +226,13 @@ public class LocalSession {
|
|||||||
--historyPointer;
|
--historyPointer;
|
||||||
if (historyPointer >= 0) {
|
if (historyPointer >= 0) {
|
||||||
EditSession editSession = history.get(historyPointer);
|
EditSession editSession = history.get(historyPointer);
|
||||||
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
try (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;
|
||||||
} else {
|
} else {
|
||||||
historyPointer = 0;
|
historyPointer = 0;
|
||||||
@ -248,11 +251,13 @@ public class LocalSession {
|
|||||||
checkNotNull(player);
|
checkNotNull(player);
|
||||||
if (historyPointer < history.size()) {
|
if (historyPointer < history.size()) {
|
||||||
EditSession editSession = history.get(historyPointer);
|
EditSession editSession = history.get(historyPointer);
|
||||||
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
try (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;
|
||||||
return editSession;
|
return editSession;
|
||||||
}
|
}
|
||||||
@ -853,6 +858,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);
|
||||||
|
|
||||||
@ -877,6 +883,24 @@ public class LocalSession {
|
|||||||
this.fastMode = fastMode;
|
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.
|
* Get the mask.
|
||||||
*
|
*
|
||||||
|
@ -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,121 +31,6 @@ public final class Blocks {
|
|||||||
private Blocks() {
|
private Blocks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
|
@ -115,6 +115,31 @@ 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().getDisplayName());
|
||||||
|
} else {
|
||||||
|
java.util.Optional<EditSession.ReorderMode> 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().getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "/drawsel" },
|
aliases = { "/drawsel" },
|
||||||
usage = "[on|off]",
|
usage = "[on|off]",
|
||||||
|
@ -73,7 +73,7 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean commitRequired() {
|
public boolean commitRequired() {
|
||||||
return batches.size() > 0;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -88,7 +88,7 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Operation commitBefore() {
|
protected Operation commitBefore() {
|
||||||
if (!enabled) {
|
if (!commitRequired()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Operation() {
|
return new Operation() {
|
||||||
|
@ -19,9 +19,7 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extent.reorder;
|
package com.sk89q.worldedit.extent.reorder;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
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;
|
||||||
@ -35,8 +33,10 @@ 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.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -50,11 +50,121 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
|
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
|
||||||
|
|
||||||
private LocatedBlockList stage1 = new LocatedBlockList();
|
private static Map<BlockType, PlacementPriority> priorityMap = new HashMap<>();
|
||||||
private LocatedBlockList stage2 = new LocatedBlockList();
|
|
||||||
private LocatedBlockList stage3 = new LocatedBlockList();
|
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.
|
||||||
|
*
|
||||||
|
* @param extent the extent
|
||||||
|
*/
|
||||||
|
public MultiStageReorder(Extent extent) {
|
||||||
|
this(extent, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance.
|
* Create a new instance.
|
||||||
*
|
*
|
||||||
@ -64,15 +174,10 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
|
|||||||
public MultiStageReorder(Extent extent, boolean enabled) {
|
public MultiStageReorder(Extent extent, boolean enabled) {
|
||||||
super(extent);
|
super(extent);
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
for (PlacementPriority priority : PlacementPriority.values()) {
|
||||||
* Create a new instance when the re-ordering is enabled.
|
stages.put(priority, new LocatedBlockList());
|
||||||
*
|
}
|
||||||
* @param extent the extent
|
|
||||||
*/
|
|
||||||
public MultiStageReorder(Extent extent) {
|
|
||||||
this(extent, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,63 +199,87 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean commitRequired() {
|
public boolean commitRequired() {
|
||||||
return stage1.size() > 0 || stage2.size() > 0 || stage3.size() > 0;
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the stage priority of the block.
|
||||||
|
*
|
||||||
|
* @param block The block
|
||||||
|
* @return The priority
|
||||||
|
*/
|
||||||
|
private PlacementPriority getPlacementPriority(BlockStateHolder block) {
|
||||||
|
return priorityMap.getOrDefault(block.getBlockType(), PlacementPriority.FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
|
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
|
||||||
BlockState existing = getBlock(location);
|
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return super.setBlock(location, block);
|
return super.setBlock(location, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Blocks.shouldPlaceLast(block.getBlockType())) {
|
BlockState existing = getBlock(location);
|
||||||
// Place torches, etc. last
|
PlacementPriority priority = getPlacementPriority(block);
|
||||||
stage2.add(location, block);
|
PlacementPriority srcPriority = getPlacementPriority(existing);
|
||||||
return !existing.equalsFuzzy(block);
|
|
||||||
} else if (Blocks.shouldPlaceFinal(block.getBlockType())) {
|
if (srcPriority != PlacementPriority.FIRST) {
|
||||||
// Place signs, reed, etc even later
|
BlockStateHolder replacement = block.getBlockType().getMaterial().isAir() ? block : BlockTypes.AIR.getDefaultState();
|
||||||
stage3.add(location, block);
|
|
||||||
return !existing.equalsFuzzy(block);
|
switch (srcPriority) {
|
||||||
} else if (Blocks.shouldPlaceLast(existing.getBlockType())) {
|
case FINAL:
|
||||||
// Destroy torches, etc. first
|
stages.get(PlacementPriority.CLEAR_FINAL).add(location, replacement);
|
||||||
super.setBlock(location, BlockTypes.AIR.getDefaultState());
|
break;
|
||||||
return super.setBlock(location, block);
|
case LATE:
|
||||||
} else {
|
stages.get(PlacementPriority.CLEAR_LATE).add(location, replacement);
|
||||||
stage1.add(location, block);
|
break;
|
||||||
|
case LAST:
|
||||||
|
stages.get(PlacementPriority.CLEAR_LAST).add(location, replacement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.getBlockType().getMaterial().isAir()) {
|
||||||
return !existing.equalsFuzzy(block);
|
return !existing.equalsFuzzy(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stages.get(priority).add(location, block);
|
||||||
|
return !existing.equalsFuzzy(block);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Operation commitBefore() {
|
public Operation commitBefore() {
|
||||||
return new OperationQueue(
|
if (!commitRequired()) {
|
||||||
new SetLocatedBlocks(
|
return null;
|
||||||
getExtent(),
|
}
|
||||||
Iterables.concat(stage1, stage2)),
|
List<Operation> operations = new ArrayList<>();
|
||||||
new Stage3Committer());
|
for (PlacementPriority priority : PlacementPriority.values()) {
|
||||||
|
if (priority != PlacementPriority.FINAL) {
|
||||||
|
operations.add(new SetLocatedBlocks(getExtent(), stages.get(priority)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Stage3Committer implements Operation {
|
operations.add(new FinalStageCommitter());
|
||||||
|
return new OperationQueue(operations);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private class FinalStageCommitter implements Operation {
|
||||||
public Operation resume(RunContext run) throws WorldEditException {
|
private Extent extent = getExtent();
|
||||||
Extent extent = getExtent();
|
|
||||||
|
|
||||||
final Set<BlockVector3> blocks = new HashSet<>();
|
private final Set<BlockVector3> blocks = new HashSet<>();
|
||||||
final Map<BlockVector3, BlockStateHolder> blockTypes = new HashMap<>();
|
private final Map<BlockVector3, BlockStateHolder> blockTypes = new HashMap<>();
|
||||||
for (LocatedBlock entry : stage3) {
|
|
||||||
|
public FinalStageCommitter() {
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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<>();
|
||||||
|
|
||||||
@ -201,10 +330,9 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage1.clear();
|
for (LocatedBlockList stage : stages.values()) {
|
||||||
stage2.clear();
|
stage.clear();
|
||||||
stage3.clear();
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,10 @@ import com.sk89q.worldedit.math.BlockVector2;
|
|||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -40,8 +42,10 @@ import java.util.Set;
|
|||||||
public class FastModeExtent extends AbstractDelegateExtent {
|
public class FastModeExtent extends AbstractDelegateExtent {
|
||||||
|
|
||||||
private final World world;
|
private final World world;
|
||||||
|
private final Set<BlockVector3> positions = new HashSet<>();
|
||||||
private final Set<BlockVector2> dirtyChunks = new HashSet<>();
|
private final Set<BlockVector2> dirtyChunks = new HashSet<>();
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
|
private boolean postEditSimulation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance with fast mode enabled.
|
* Create a new instance with fast mode enabled.
|
||||||
@ -83,24 +87,59 @@ public class FastModeExtent extends AbstractDelegateExtent {
|
|||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPostEditSimulationEnabled() {
|
||||||
|
return postEditSimulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPostEditSimulationEnabled(boolean enabled) {
|
||||||
|
this.postEditSimulation = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
|
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
|
||||||
if (enabled) {
|
if (enabled || postEditSimulation) {
|
||||||
dirtyChunks.add(BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4));
|
dirtyChunks.add(BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4));
|
||||||
return world.setBlock(location, block, false);
|
|
||||||
|
if (world.setBlock(location, block, false)) {
|
||||||
|
if (!enabled && postEditSimulation) {
|
||||||
|
positions.add(location);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return world.setBlock(location, block, true);
|
return world.setBlock(location, block, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean commitRequired() {
|
||||||
|
return enabled || postEditSimulation;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Operation commitBefore() {
|
protected Operation commitBefore() {
|
||||||
|
if (!commitRequired()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return new Operation() {
|
return new Operation() {
|
||||||
@Override
|
@Override
|
||||||
public Operation resume(RunContext run) throws WorldEditException {
|
public Operation resume(RunContext run) throws WorldEditException {
|
||||||
if (!dirtyChunks.isEmpty()) {
|
if (!dirtyChunks.isEmpty()) {
|
||||||
world.fixAfterFastMode(dirtyChunks);
|
world.fixAfterFastMode(dirtyChunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!enabled && postEditSimulation) {
|
||||||
|
Iterator<BlockVector3> 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;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +35,25 @@ public class ArrayListHistory implements ChangeSet {
|
|||||||
|
|
||||||
private final List<Change> changes = new ArrayList<>();
|
private final List<Change> changes = new ArrayList<>();
|
||||||
|
|
||||||
|
private boolean recordChanges = true;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(Change change) {
|
public void add(Change change) {
|
||||||
checkNotNull(change);
|
checkNotNull(change);
|
||||||
|
if (recordChanges) {
|
||||||
changes.add(change);
|
changes.add(change);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRecordingChanges() {
|
||||||
|
return recordChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRecordChanges(boolean recordChanges) {
|
||||||
|
this.recordChanges = recordChanges;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Change> backwardIterator() {
|
public Iterator<Change> backwardIterator() {
|
||||||
|
@ -36,6 +36,20 @@ public interface ChangeSet {
|
|||||||
*/
|
*/
|
||||||
void add(Change change);
|
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.
|
* Get a backward directed iterator that can be used for undo.
|
||||||
*
|
*
|
||||||
|
@ -64,6 +64,11 @@ public class NullWorld extends AbstractWorld {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBlockLightLevel(BlockVector3 position) {
|
public int getBlockLightLevel(BlockVector3 position) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -33,10 +33,13 @@ import com.sk89q.worldedit.math.Vector3;
|
|||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Direction;
|
import com.sk89q.worldedit.util.Direction;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator;
|
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.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import com.sk89q.worldedit.world.weather.WeatherType;
|
import com.sk89q.worldedit.world.weather.WeatherType;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a world (dimension).
|
* Represents a world (dimension).
|
||||||
*/
|
*/
|
||||||
@ -95,6 +98,16 @@ public interface World extends Extent {
|
|||||||
*/
|
*/
|
||||||
boolean setBlock(BlockVector3 position, BlockStateHolder block, boolean notifyAndLight) throws WorldEditException;
|
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.
|
* Get the light level at the given block.
|
||||||
*
|
*
|
||||||
|
@ -212,6 +212,12 @@ public class ForgeWorld extends AbstractWorld {
|
|||||||
return successful;
|
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
|
// Can't get the "Object" to be right for withProperty w/o this
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
private IBlockState applyProperties(BlockStateContainer stateContainer, IBlockState newState, Map<Property<?>, Object> states) {
|
private IBlockState applyProperties(BlockStateContainer stateContainer, IBlockState newState, Map<Property<?>, Object> states) {
|
||||||
|
@ -41,7 +41,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||||
import com.sk89q.worldedit.world.weather.WeatherType;
|
import com.sk89q.worldedit.world.weather.WeatherType;
|
||||||
import com.sk89q.worldedit.world.weather.WeatherTypes;
|
import com.sk89q.worldedit.world.weather.WeatherTypes;
|
||||||
|
|
||||||
import org.spongepowered.api.Sponge;
|
import org.spongepowered.api.Sponge;
|
||||||
import org.spongepowered.api.block.BlockSnapshot;
|
import org.spongepowered.api.block.BlockSnapshot;
|
||||||
import org.spongepowered.api.block.BlockState;
|
import org.spongepowered.api.block.BlockState;
|
||||||
@ -163,6 +162,12 @@ public abstract class SpongeWorld extends AbstractWorld {
|
|||||||
return true;
|
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
|
@Override
|
||||||
public boolean regenerate(Region region, EditSession editSession) {
|
public boolean regenerate(Region region, EditSession editSession) {
|
||||||
return false;
|
return false;
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren