Permalink
Browse files

Integrate the changes from the multipass2 branch.

  • Loading branch information...
me4502 committed Aug 24, 2018
1 parent 7747119 commit 384ee8c2e515da1d3e247c6930be516541ea33bc
@@ -158,6 +158,11 @@ public String getName() {
return getWorld().getName();
}
@Override
public boolean notifyAndLightBlock(Vector position) throws WorldEditException {
return false;
}
@Override
public int getBlockLightLevel(Vector pt) {
return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel();
@@ -36,6 +36,29 @@
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.
*/
@@ -19,7 +19,6 @@
package com.sk89q.worldedit.extent.reorder;
import com.google.common.collect.Iterators;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@@ -37,6 +36,7 @@
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;
@@ -50,29 +50,34 @@
*/
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
private TupleArrayList<BlockVector, BlockStateHolder> stage1 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BlockStateHolder> stage2 = new TupleArrayList<>();
private TupleArrayList<BlockVector, BlockStateHolder> stage3 = new TupleArrayList<>();
private static final int STAGE_COUNT = 4;
private final List<TupleArrayList<BlockVector, BlockStateHolder>> stages = new ArrayList<>();
private boolean enabled;
/**
* Create a new instance.
* Create a new instance when the re-ordering is enabled.
*
* @param extent the extent
* @param enabled true to enable
*/
public MultiStageReorder(Extent extent, boolean enabled) {
super(extent);
this.enabled = enabled;
public MultiStageReorder(Extent extent) {
this(extent, true);
}
/**
* Create a new instance when the re-ordering is enabled.
* Create a new instance.
*
* @param extent the extent
* @param enabled true to enable
*/
public MultiStageReorder(Extent extent) {
this(extent, true);
public MultiStageReorder(Extent extent, boolean enabled) {
super(extent);
this.enabled = enabled;
for (int i = 0; i < STAGE_COUNT; ++i) {
stages.add(new TupleArrayList<>());
}
}
/**
@@ -93,56 +98,68 @@ public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
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(Vector 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
stage2.put(location.toBlockVector(), block);
return !existing.equalsFuzzy(block);
} else if (Blocks.shouldPlaceFinal(block.getBlockType())) {
// Place signs, reed, etc even later
stage3.put(location.toBlockVector(), block);
return !existing.equalsFuzzy(block);
} else if (Blocks.shouldPlaceLast(existing.getBlockType())) {
BlockState existing = getBlock(location);
int priority = getPlacementPriority(block);
int srcPriority = getPlacementPriority(block);
// Destroy torches, water, stand, etc. first
if (srcPriority == 1 || srcPriority == 2) {
// Destroy torches, etc. first
super.setBlock(location, BlockTypes.AIR.getDefaultState());
return super.setBlock(location, block);
} else {
stage1.put(location.toBlockVector(), block);
return !existing.equalsFuzzy(block);
}
stages.get(priority).put(location.toBlockPoint(), block);
return !existing.equalsFuzzy(block);
}
@Override
public Operation commitBefore() {
return new OperationQueue(
new BlockMapEntryPlacer(
getExtent(),
Iterators.concat(stage1.iterator(), stage2.iterator())),
new Stage3Committer());
List<Operation> operations = new ArrayList<>();
for (int i = 0; i < stages.size() - 1; ++i) {
operations.add(new BlockMapEntryPlacer(getExtent(), stages.get(i).iterator()));
}
operations.add(new FinalStageCommitter());
return new OperationQueue(operations);
}
private class Stage3Committer implements Operation {
private class FinalStageCommitter implements Operation {
private Extent extent = getExtent();
@Override
public Operation resume(RunContext run) throws WorldEditException {
Extent extent = getExtent();
private final Set<BlockVector> blocks = new HashSet<>();
private final Map<BlockVector, BlockStateHolder> blockTypes = new HashMap<>();
final Set<BlockVector> blocks = new HashSet<>();
final Map<BlockVector, BlockStateHolder> blockTypes = new HashMap<>();
for (Map.Entry<BlockVector, BlockStateHolder> entry : stage3) {
public FinalStageCommitter() {
for (Map.Entry<BlockVector, BlockStateHolder> entry : stages.get(stages.size() - 1)) {
final BlockVector pt = entry.getKey();
blocks.add(pt);
blockTypes.put(pt, entry.getValue());
}
}
while (!blocks.isEmpty()) {
@Override
public Operation resume(RunContext run) throws WorldEditException {
while (run.shouldContinue() && !blocks.isEmpty()) {
BlockVector current = blocks.iterator().next();
if (!blocks.contains(current)) {
continue;
@@ -197,11 +214,14 @@ public Operation resume(RunContext run) throws WorldEditException {
}
}
stage1.clear();
stage2.clear();
stage3.clear();
if (blocks.isEmpty()) {
for (TupleArrayList<BlockVector, BlockStateHolder> stage : stages) {
stage.clear();
}
return null;
}
return null;
return this;
}
@Override
@@ -30,8 +30,10 @@
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Set;
/**
@@ -40,8 +42,9 @@
public class FastModeExtent extends AbstractDelegateExtent {
private final World world;
private final Queue<Vector> positions = new ArrayDeque<>();
private final Set<BlockVector2D> dirtyChunks = new HashSet<>();
private boolean enabled = true;
private boolean enabled;
/**
* Create a new instance with fast mode enabled.
@@ -85,33 +88,47 @@ public void setEnabled(boolean enabled) {
@Override
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
if (enabled) {
dirtyChunks.add(new BlockVector2D(location.getBlockX() >> 4, location.getBlockZ() >> 4));
return world.setBlock(location, block, false);
} else {
return world.setBlock(location, block, true);
dirtyChunks.add(new BlockVector2D(location.getBlockX() >> 4, location.getBlockZ() >> 4));
if (world.setBlock(location, block, false)) {
if (!enabled) {
positions.offer(location);
}
return true;
}
return false;
}
@Override
protected Operation commitBefore() {
return new Operation() {
@Override
public Operation resume(RunContext run) throws WorldEditException {
return new CommitOperation();
}
private class CommitOperation implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
if (!enabled) {
if (!dirtyChunks.isEmpty()) {
world.fixAfterFastMode(dirtyChunks);
dirtyChunks.clear();
}
return null;
}
@Override
public void cancel() {
}
while (run.shouldContinue() && !positions.isEmpty()) {
Vector position = positions.poll(); // Remove from queue
world.notifyAndLightBlock(position);
}
@Override
public void addStatusMessages(List<String> messages) {
return !positions.isEmpty() ? this : null;
}
};
}
return null;
}
@Override
public void cancel() {
}
@Override
public void addStatusMessages(List<String> messages) {
}
}
}
@@ -55,12 +55,12 @@ public BlockMapEntryPlacer(Extent extent, Iterator<Map.Entry<BlockVector, BlockS
@Override
public Operation resume(RunContext run) throws WorldEditException {
while (iterator.hasNext()) {
while (iterator.hasNext() && run.shouldContinue()) {
Map.Entry<BlockVector, BlockStateHolder> entry = iterator.next();
extent.setBlock(entry.getKey(), entry.getValue());
}
return null;
return iterator.hasNext() ? this : null;
}
@Override
@@ -97,7 +97,7 @@ public Task(Operation... operation) {
return this;
}
public Task<T> onExcept(Consumer<WorldEditException> exceptionConsumer) {
public Task<T> withExceptionConsumer(Consumer<WorldEditException> exceptionConsumer) {
checkNotNull(exceptionConsumer);
this.exceptionConsumer = exceptionConsumer;
return this;
@@ -123,11 +123,22 @@ public Task(Operation... operation) {
*/
public Task<T> addActorConsumers(Actor actor) {
checkNotNull(actor);
onExcept(e -> actor.printError(e.getMessage()));
withExceptionConsumer(e -> actor.printError(e.getMessage()));
withStatusConsumer(actor::print);
return this;
}
private void notifyStatusConsumer() {
if (statusConsumer != null && current != null) {
statusMessageList.clear();
current.addStatusMessages(statusMessageList);
for (String message : statusMessageList) {
statusConsumer.accept(message);
}
}
}
/**
* Resume the task with a given context.
*
@@ -137,17 +148,11 @@ public Task(Operation... operation) {
public boolean resumeTask(RunContext run) {
if (current == null && !queue.isEmpty()) {
current = queue.poll();
notifyStatusConsumer();
}
if (current != null) {
if (statusConsumer != null) {
statusMessageList.clear();
current.addStatusMessages(statusMessageList);
for (String message : statusMessageList) {
statusConsumer.accept(message);
}
}
try {
current = current.resume(run);
} catch (WorldEditException e) {
@@ -159,6 +164,8 @@ public boolean resumeTask(RunContext run) {
if (current == null) {
current = queue.poll();
notifyStatusConsumer();
}
}
@@ -167,7 +167,7 @@ public Operation resume(RunContext run) throws WorldEditException {
if (function.apply(position)) {
affected++;
if (System.currentTimeMillis() - startTime > 50) { // 20TPS 1 tick time.
if (affected % 100 == 0 && System.currentTimeMillis() - startTime > 50) { // 20TPS 1 tick time.
return this;
}
}
Oops, something went wrong.

0 comments on commit 384ee8c

Please sign in to comment.