shift extent queue methods

This commit is contained in:
Jesse Boyd
2019-07-19 02:07:31 +10:00
parent 2c22f02c20
commit 0a924915c8
15 changed files with 308 additions and 699 deletions

View File

@ -29,7 +29,6 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
@ -365,7 +364,6 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
* chunk batching}.
*/
public void enableStandardMode() {
setBatchingChunks(true);
}
/**
@ -374,17 +372,29 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
* @param reorderMode The reorder mode
*/
public void setReorderMode(ReorderMode reorderMode) {
//TODO Not working yet. - It shouldn't need to work. FAWE doesn't need reordering.
switch (reorderMode) {
case MULTI_STAGE:
enableQueue();
break;
case NONE: // Functionally the same, since FAWE doesn't perform physics
case FAST:
disableQueue();
break;
default:
throw new UnsupportedOperationException("Not implemented: " + reorderMode);
}
}
//TODO: Reorder mode.
/**
* Get the reorder mode.
*
* @return the reorder mode
*/
public ReorderMode getReorderMode() {
return null;
if (isQueueEnabled()) {
return ReorderMode.MULTI_STAGE;
}
return ReorderMode.FAST;
}
/**
@ -463,6 +473,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
*/
@Deprecated
public void enableQueue() {
super.enableQueue();
}
/**
@ -470,9 +481,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
*/
@Deprecated
public void disableQueue() {
if (isQueueEnabled()) {
this.flushQueue();
}
super.disableQueue();
}
/**
@ -730,6 +739,11 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
* @param batchingChunks {@code true} to enable, {@code false} to disable
*/
public void setBatchingChunks(boolean batchingChunks) {
if (batchingChunks) {
enableQueue();
} else {
disableQueue();
}
}
/**
@ -739,6 +753,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
* @see #setBatchingChunks(boolean)
*/
public void disableBuffering() {
disableQueue();
}
/**
@ -1028,7 +1043,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
UndoContext context = new UndoContext();
context.setExtent(editSession.bypassAll);
ChangeSet changeSet = getChangeSet();
editSession.getQueue().setChangeTask(null);
setChangeSet(null);
Operations.completeBlindly(ChangeSetExecutor.create(changeSet, context, ChangeSetExecutor.Type.UNDO, editSession.getBlockBag(), editSession.getLimit().INVENTORY_MODE));
flushQueue();
editSession.changes = 1;
@ -1052,7 +1067,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
UndoContext context = new UndoContext();
context.setExtent(editSession.bypassAll);
ChangeSet changeSet = getChangeSet();
editSession.getQueue().setChangeTask(null);
setChangeSet(null);
Operations.completeBlindly(ChangeSetExecutor.create(changeSet, context, ChangeSetExecutor.Type.REDO, editSession.getBlockBag(), editSession.getLimit().INVENTORY_MODE));
flushQueue();
editSession.changes = 1;
@ -1146,28 +1161,31 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
final int startPerformY = region.getMinimumPoint().getBlockY();
final int startCheckY = fullHeight ? 0 : startPerformY;
final int endY = region.getMaximumPoint().getBlockY();
RegionVisitor visitor = new RegionVisitor(flat, pos -> {
int x = pos.getX();
int z = pos.getZ();
int freeSpot = startCheckY;
for (int y = startCheckY; y <= endY; y++) {
if (y < startPerformY) {
if (!getBlockType(x, y, z).getMaterial().isAir()) {
freeSpot = y + 1;
RegionVisitor visitor = new RegionVisitor(flat, new RegionFunction() {
@Override
public boolean apply(BlockVector3 pos) throws WorldEditException {
int x = pos.getX();
int z = pos.getZ();
int freeSpot = startCheckY;
for (int y = startCheckY; y <= endY; y++) {
if (y < startPerformY) {
if (!getBlockType(x, y, z).getMaterial().isAir()) {
freeSpot = y + 1;
}
continue;
}
continue;
}
BlockType block = getBlockType(x, y, z);
if (!block.getMaterial().isAir()) {
if (freeSpot != y) {
setBlock(x, freeSpot, z, block);
setBlock(x, y, z, replace);
BlockType block = getBlockType(x, y, z);
if (!block.getMaterial().isAir()) {
if (freeSpot != y) {
setBlock(x, freeSpot, z, block);
setBlock(x, y, z, replace);
}
freeSpot++;
}
freeSpot++;
}
}
return true;
}, this);
return true;
}
});
Operations.completeBlindly(visitor);
return this.changes;
}
@ -1612,7 +1630,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
if (disAbs.getBlockX() < size.getBlockX() && disAbs.getBlockY() < size.getBlockY() && disAbs.getBlockZ() < size.getBlockZ()) {
// Buffer if overlapping
queue.dequeue();
disableQueue();
}
ForwardExtentCopy copy = new ForwardExtentCopy(this, region, this, to);
@ -3029,9 +3047,8 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
public boolean regenerate(final Region region, final BiomeType biome, final Long seed) {
//TODO Optimize - avoid Vector2D creation (make mutable)
final FaweQueue queue = this.getQueue();
queue.setChangeTask(null);
final FaweChangeSet fcs = (FaweChangeSet) this.getChangeSet();
this.setChangeSet(null);
final FaweRegionExtent fe = this.getRegionExtent();
final boolean cuboid = region instanceof CuboidRegion;
if (fe != null && cuboid) {
@ -3117,7 +3134,7 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
queue.regenerateChunk(cx, cz, biome, seed);
regenerateChunk(cx, cz, biome, seed);
}
});
}

View File

@ -21,12 +21,18 @@ package com.sk89q.worldedit.extent;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.jnbt.anvil.generator.GenBase;
import com.boydti.fawe.jnbt.anvil.generator.Resource;
import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.LightingExtent;
import com.boydti.fawe.util.ExtentTraverser;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue;
@ -69,6 +75,58 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
return extent;
}
/*
Queue based methods
TODO NOT IMPLEMENTED: IQueueExtent and such need to implement these
*/
public boolean isQueueEnabled() {
return extent.isQueueEnabled();
}
@Override
public void disableQueue() {
try {
if (!(extent instanceof ForgetfulExtentBuffer)) { // placeholder
extent.disableQueue();
}
} catch (FaweException disableQueue) {}
if (extent instanceof AbstractDelegateExtent) {
Extent next = ((AbstractDelegateExtent) extent).getExtent();
new ExtentTraverser(this).setNext(next);
} else {
Fawe.debug("Cannot disable queue");
}
}
@Override
public void enableQueue() {
try {
extent.enableQueue();
} catch (FaweException enableQueue) {
// TODO NOT IMPLEMENTED - THIS IS IMPORTANT (ForgetfulExtentBuffer is just a placeholder for now, it won't work)
new ExtentTraverser<>(this).setNext(new ForgetfulExtentBuffer(extent));
}
}
/*
History
*/
public void setChangeSet(FaweChangeSet changeSet) {
if (extent instanceof HistoryExtent) {
HistoryExtent history = ((HistoryExtent) extent);
if (changeSet == null) {
new ExtentTraverser(this).setNext(history.getExtent());
} else {
history.setChangeSet(changeSet);
}
}
else if (extent instanceof AbstractDelegateExtent) {
((AbstractDelegateExtent) extent).setChangeSet(changeSet);
} else if (changeSet != null) {
new ExtentTraverser<>(this).setNext(new HistoryExtent(extent, changeSet));
}
}
/*
Bounds
*/

View File

@ -25,6 +25,7 @@ import com.boydti.fawe.jnbt.anvil.generator.OreGen;
import com.boydti.fawe.jnbt.anvil.generator.Resource;
import com.boydti.fawe.jnbt.anvil.generator.SchemGen;
import com.boydti.fawe.object.clipboard.WorldCopyClipboard;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
@ -51,6 +52,7 @@ import com.sk89q.worldedit.registry.state.PropertyGroup;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -133,6 +135,42 @@ public interface Extent extends InputExtent, OutputExtent {
return null;
}
/*
Queue based methods
TODO NOT IMPLEMENTED:
*/
default boolean isQueueEnabled() {
return false;
}
default void enableQueue() {
if (!isQueueEnabled()) throw FaweException._enableQueue;
}
default void disableQueue() {
if (isQueueEnabled()) throw FaweException._disableQueue;
}
/*
World based methods
TODO NOT IMPLEMENTED:
*/
default boolean isWorld() {
return false;
}
default boolean regenerateChunk(int x, int z, @Nullable BiomeType type, @Nullable Long seed) {
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED: " + isWorld());
}
/*
Shifting operations down the pipeline from EditSession -> Extent
- This allows certain extents (e.g. multithreaded extent) to override and optimize as needed
- The EditSession shouldn't need to worry about implementation details
- TODO: actually optimize these
*/
default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY) {
maxY = Math.min(maxY, Math.max(0, maxY));
minY = Math.max(0, minY);

View File

@ -62,6 +62,11 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
this(delegate, Masks.alwaysTrue());
}
@Override
public boolean isQueueEnabled() {
return true;
}
/**
* Create a new extent buffer that will buffer changes that meet the criteria
* of the given mask.

View File

@ -19,16 +19,12 @@
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.object.HasFaweQueue;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3;
import java.util.Collection;
/**
* Visits adjacent points on the same X-Z plane as long as the points
* pass the given mask, and then executes the provided region
@ -48,11 +44,11 @@ public class DownwardVisitor extends RecursiveVisitor {
* @param baseY the base Y
*/
public DownwardVisitor(Mask mask, RegionFunction function, int baseY) {
this(mask, function, baseY, Integer.MAX_VALUE, null);
this(mask, function, baseY, Integer.MAX_VALUE);
}
public DownwardVisitor(Mask mask, RegionFunction function, int baseY, int depth, HasFaweQueue hasFaweQueue) {
super(mask, function, depth, hasFaweQueue);
public DownwardVisitor(Mask mask, RegionFunction function, int baseY, int depth) {
super(mask, function, depth);
checkNotNull(mask);
this.baseY = baseY;

View File

@ -0,0 +1,55 @@
package com.sk89q.worldedit.util.task;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class LinkedFuture<T extends Future<T>> implements Future<T> {
private Future<T> task;
public LinkedFuture(Future<T> task) {
this.task = task;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return task.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return task.isCancelled();
}
@Override
public boolean isDone() {
return task.isDone();
}
@Override
public synchronized T get() throws InterruptedException, ExecutionException {
if (task != null) {
task = task.get();
if (task != null) {
return (T) this;
}
}
return null;
}
@Override
public synchronized T get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
if (task != null) {
T result = task.get(timeout, unit);
if (task != null || !task.isDone()) {
return (T) this;
}
task = null;
}
return null;
}
}

View File

@ -272,4 +272,9 @@ public interface World extends Extent {
@Override
int hashCode();
@Override
default boolean isWorld() {
return true;
}
}