Permalink
Browse files

Initial prototype for chunk batching mode

  • Loading branch information...
kenzierocks committed Jul 3, 2016
1 parent 28d4587 commit b14777209470152c5d79422bba07a3d4987eed4c
@@ -37,6 +37,7 @@
import com.sk89q.worldedit.extent.validation.BlockChangeLimiter;
import com.sk89q.worldedit.extent.validation.DataValidatorExtent;
import com.sk89q.worldedit.extent.world.BlockQuirkExtent;
import com.sk89q.worldedit.extent.world.ChunkBatchingModeExtent;
import com.sk89q.worldedit.extent.world.ChunkLoadingExtent;
import com.sk89q.worldedit.extent.world.FastModeExtent;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
@@ -115,6 +116,7 @@
private final ChangeSet changeSet = new BlockOptimizedHistory();
private @Nullable FastModeExtent fastModeExtent;
private @Nullable ChunkBatchingModeExtent chunkBatchingModeExtent;
private final SurvivalModeExtent survivalExtent;
private @Nullable ChunkLoadingExtent chunkLoadingExtent;
private @Nullable LastAccessExtentCache cacheExtent;
@@ -183,6 +185,7 @@ public EditSession(LocalWorld world, int maxBlocks, @Nullable BlockBag blockBag)
extent = survivalExtent = new SurvivalModeExtent(extent, world);
extent = quirkExtent = new BlockQuirkExtent(extent, world);
extent = chunkLoadingExtent = new ChunkLoadingExtent(extent, world);
extent = chunkBatchingModeExtent = new ChunkBatchingModeExtent(extent, world, false);
extent = cacheExtent = new LastAccessExtentCache(extent);
extent = wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
extent = validator = new DataValidatorExtent(extent, world);
@@ -345,6 +348,34 @@ public void setFastMode(boolean enabled) {
}
}
/**
* Set whether chunk batching mode is enabled.
*
* <p>Chunk batching mode will group changes and accesses
* into the chunks they touch in an attempt to speed up
* actions.</p>
*
* @param enabled true to enable
*/
public void setChunkBatchingMode(boolean enabled) {
if (chunkBatchingModeExtent != null) {
chunkBatchingModeExtent.setEnabled(enabled);
}
}
/**
* Return chunk batching mode status.
*
* <p>Chunk batching mode will group changes and accesses
* into the chunks they touch in an attempt to speed up
* actions.</p>
*
* @return true if enabled
*/
public boolean hasChunkBatchingMode() {
return chunkBatchingModeExtent != null && chunkBatchingModeExtent.isEnabled();
}
/**
* Return fast mode status.
*
@@ -82,6 +82,7 @@
private transient boolean hasCUISupport = false;
private transient int cuiVersion = -1;
private transient boolean fastMode = false;
private transient boolean chunkBatchingMode = false;
private transient Mask mask;
private transient TimeZone timezone = TimeZone.getDefault();
@@ -866,6 +867,7 @@ public EditSession createEditSession(Player player) {
.getEditSession(player.isPlayer() ? player.getWorld() : null,
getBlockChangeLimit(), blockBag, player);
editSession.setFastMode(fastMode);
editSession.setChunkBatchingMode(chunkBatchingMode);
Request.request().setEditSession(editSession);
editSession.setMask(mask);
@@ -890,6 +892,25 @@ public void setFastMode(boolean fastMode) {
this.fastMode = fastMode;
}
/**
* Checks if the session has chunk batching mode enabled.
*
* @return true if chunk batching mode is enabled
*/
public boolean hasChunkBatchingMode() {
return chunkBatchingMode;
}
/**
* Set chunk batching mode.
*
* @param fastMode true if chunk batching mode is enabled
*/
public void setChunkBatchingMode(boolean chunkBatchingMode) {
this.chunkBatchingMode = chunkBatchingMode;
}
/**
* Get the mask.
*
@@ -108,6 +108,36 @@ public void fast(Player player, LocalSession session, EditSession editSession, C
}
}
@Command(
aliases = { "/chunkbatch" },
usage = "[on|off]",
desc = "Toggle chunk batching mode",
min = 0,
max = 1
)
@CommandPermissions("worldedit.chunkbatch")
public void chunkbatch(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
String newState = args.getString(0, null);
if (session.hasChunkBatchingMode()) {
if ("on".equals(newState)) {
player.printError("Chunk batching mode already enabled.");
return;
}
session.setChunkBatchingMode(false);
player.print("Chunk batching mode disabled.");
} else {
if ("off".equals(newState)) {
player.printError("Chunk batching mode already disabled.");
return;
}
session.setChunkBatchingMode(true);
player.print("Chunk batching mode enabled. Beta feature, block placement order may be incorrect but actions should run quicker.");
}
}
@Command(
aliases = { "/gmask", "gmask" },
usage = "[mask]",
@@ -0,0 +1,125 @@
package com.sk89q.worldedit.extent.world;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.history.change.BlockChange;
import com.sk89q.worldedit.world.World;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
public class ChunkBatchingModeExtent extends AbstractDelegateExtent {
private static BlockVector2D chunkLocation(Vector location) {
return new BlockVector2D(location.getBlockX() >> 4,
location.getBlockZ() >> 4);
}
// TODO: we can totally write a more efficient version of this
// i.e. without a new BlockVector2D per block being set/retrieved
private final Multimap<BlockVector2D, BlockChange> chunkChanges =
HashMultimap.create();
private final World world;
private boolean enabled = true;
/**
* Create a new instance with fast mode enabled.
*
* @param delegate
* - the extent to delegate to
* @param world
* - the world
*/
public ChunkBatchingModeExtent(Extent delegate, World world) {
this(delegate, world, true);
}
/**
* Create a new instance.
*
* @param delegate
* - the extent to delegate to
* @param world
* - the world
* @param enabled
* - true to enable fast mode
*/
public ChunkBatchingModeExtent(Extent delegate, World world, boolean enabled) {
super(delegate);
checkNotNull(world);
this.world = world;
this.enabled = enabled;
}
/**
* Return whether chunk batching mode is enabled.
*
* @return true if chunk batching mode is enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Set chunk batching mode enable status.
*
* @param enabled
* - true to enable chunk batching mode
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public boolean setBlock(Vector location, BaseBlock block)
throws WorldEditException {
if (enabled) {
// Assume it is in position and will be set.
return this.chunkChanges.put(chunkLocation(location),
new BlockChange(new BlockVector(location), block, block));
} else {
return super.setBlock(location, block);
}
}
@Override
protected Operation commitBefore() {
return new Operation() {
@Override
public Operation resume(RunContext run) throws WorldEditException {
BlockVector2D minimumChunk = chunkLocation(getMinimumPoint());
BlockVector2D maximumChunk = chunkLocation(getMaximumPoint());
for (int z = minimumChunk.getBlockZ(); z < maximumChunk.getBlockZ(); z++) {
for (int x = minimumChunk.getBlockX(); x < maximumChunk.getBlockX(); x++) {
BlockVector2D chunkPos = new BlockVector2D(x, z);
world.checkLoadedChunk(chunkPos.toVector());
for (BlockChange change : chunkChanges.get(chunkPos)) {
getExtent().setBlock(change.getPosition(), change.getCurrent());
}
}
}
return null;
}
@Override
public void cancel() {
}
@Override
public void addStatusMessages(List<String> messages) {
}
};
}
}

0 comments on commit b147772

Please sign in to comment.