mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-11-16 17:16:11 +00:00
shift extent queue methods
This commit is contained in:
parent
2c22f02c20
commit
0a924915c8
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
@ -17,6 +18,24 @@ import java.util.function.Supplier;
|
||||
* Interface for a queue based extent which uses chunks
|
||||
*/
|
||||
public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
|
||||
@Override
|
||||
default boolean isQueueEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must ensure that it is enqueued with QueueHandler
|
||||
*/
|
||||
@Override
|
||||
void enableQueue();
|
||||
|
||||
/**
|
||||
* Must ensure it is not in the queue handler
|
||||
*/
|
||||
@Override
|
||||
void disableQueue();
|
||||
|
||||
void init(WorldChunkCache world);
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.Future;
|
||||
@ -113,10 +114,26 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Future<T>> void complete(Future<T> task) {
|
||||
try {
|
||||
while (task != null) {
|
||||
task = task.get();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> Future<T> async(final Runnable run, final T value) {
|
||||
return forkJoinPoolSecondary.submit(run, value);
|
||||
}
|
||||
|
||||
public Future<?> async(final Runnable run) {
|
||||
return forkJoinPoolSecondary.submit(run);
|
||||
}
|
||||
|
||||
public <T> Future<T> async(final Callable<T> call) {
|
||||
return forkJoinPoolSecondary.submit(call);
|
||||
}
|
||||
|
@ -1,521 +0,0 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.example.NullRelighter;
|
||||
import com.boydti.fawe.example.Relighter;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A queue based Extent capable of queing chunk and region changes
|
||||
*/
|
||||
public interface FaweQueue extends HasFaweQueue, Extent {
|
||||
|
||||
enum ProgressType {
|
||||
QUEUE,
|
||||
DISPATCH,
|
||||
DONE,
|
||||
}
|
||||
|
||||
enum RelightMode {
|
||||
NONE,
|
||||
OPTIMAL,
|
||||
ALL,
|
||||
}
|
||||
|
||||
enum Capability {
|
||||
// If history can be recorded in an async task by the dispatcher
|
||||
CHANGE_TASKS,
|
||||
// If custom chunk packets can be sent
|
||||
CHUNK_PACKETS
|
||||
//
|
||||
}
|
||||
|
||||
default Relighter getRelighter() {
|
||||
return NullRelighter.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
default BlockVector3 getMinimumPoint() {
|
||||
return BlockVector3.at(-30000000, 0, -30000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
default BlockVector3 getMaximumPoint() {
|
||||
return BlockVector3.at(30000000, getMaxY(), 30000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
default BlockState getLazyBlock(int x, int y, int z) {
|
||||
int combinedId4Data = getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId());
|
||||
try {
|
||||
return BlockState.getFromInternalId(combinedId4Data);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) throws WorldEditException {
|
||||
return setBlock(x, y, z, block.getInternalId(), block instanceof BaseBlock ? block.getNbtData() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
default BaseBlock getFullBlock(BlockVector3 position) {
|
||||
int combinedId4Data = getCachedCombinedId4Data(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BlockTypes.AIR.getInternalId());
|
||||
try {
|
||||
BaseBlock block = BaseBlock.getFromInternalId(combinedId4Data, null);
|
||||
if (block.getMaterial().hasContainer()) {
|
||||
CompoundTag tile = getTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||
if (tile != null) {
|
||||
return BaseBlock.getFromInternalId(combinedId4Data, tile);
|
||||
}
|
||||
}
|
||||
return block;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default BiomeType getBiome(BlockVector2 position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
default <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block) throws WorldEditException {
|
||||
return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block);
|
||||
}
|
||||
|
||||
boolean setBlock(final int x, final int y, final int z, int combinedId);
|
||||
|
||||
default boolean setBlock(final int x, final int y, final int z, int combinedId, CompoundTag nbtData) {
|
||||
if (setBlock(x, y, z, combinedId)) {
|
||||
if (nbtData != null) setTile(x, y, z, nbtData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return setBiome(position.getBlockX(), position.getBlockZ(), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
default FaweQueue getQueue() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
default void addEditSession(EditSession session) {
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
Collection<EditSession> sessions = getEditSessions();
|
||||
sessions.add(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a progress task<br>
|
||||
* - Progress type
|
||||
* - Amount of type
|
||||
*
|
||||
* @param progressTask
|
||||
*/
|
||||
default void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
|
||||
this.setProgressTask(progressTask);
|
||||
}
|
||||
|
||||
default Collection<EditSession> getEditSessions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
default boolean supports(Capability capability) {
|
||||
return false;
|
||||
}
|
||||
|
||||
default void optimize() {}
|
||||
|
||||
default int setBlocks(CuboidRegion cuboid, int combinedId) {
|
||||
RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint());
|
||||
final int minY = cuboid.getMinimumY();
|
||||
final int maxY = cuboid.getMaximumY();
|
||||
|
||||
final FaweChunk<?> fc = getFaweChunk(0, 0);
|
||||
fc.fillCuboid(0, 15, minY, maxY, 0, 15, combinedId);
|
||||
fc.optimize();
|
||||
|
||||
MainUtil.chunkTaskSync(current, new RunnableVal<int[]>() {
|
||||
@Override
|
||||
public void run(int[] value) {
|
||||
FaweChunk newChunk;
|
||||
if (value[6] == 0) {
|
||||
newChunk = fc.copy(true);
|
||||
newChunk.setLoc(FaweQueue.this, value[0], value[1]);
|
||||
} else {
|
||||
int bx = value[2] & 15;
|
||||
int tx = value[4] & 15;
|
||||
int bz = value[3] & 15;
|
||||
int tz = value[5] & 15;
|
||||
if (bx == 0 && tx == 15 && bz == 0 && tz == 15) {
|
||||
newChunk = fc.copy(true);
|
||||
newChunk.setLoc(FaweQueue.this, value[0], value[1]);
|
||||
} else {
|
||||
newChunk = FaweQueue.this.getFaweChunk(value[0], value[1]);
|
||||
newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, combinedId);
|
||||
}
|
||||
}
|
||||
newChunk.addToQueue();
|
||||
}
|
||||
});
|
||||
return cuboid.getArea();
|
||||
}
|
||||
|
||||
void setTile(int x, int y, int z, CompoundTag tag);
|
||||
|
||||
void setEntity(int x, int y, int z, CompoundTag tag);
|
||||
|
||||
void removeEntity(int x, int y, int z, UUID uuid);
|
||||
|
||||
boolean setBiome(final int x, final int z, final BiomeType biome);
|
||||
|
||||
FaweChunk getFaweChunk(int x, int z);
|
||||
|
||||
Collection<FaweChunk> getFaweChunks();
|
||||
|
||||
default boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
|
||||
if (whileLocked != null) whileLocked.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
void setChunk(final FaweChunk chunk);
|
||||
|
||||
File getSaveFolder();
|
||||
|
||||
@Override
|
||||
default int getMaxY() {
|
||||
World weWorld = getWEWorld();
|
||||
return weWorld == null ? 255 : weWorld.getMaxY();
|
||||
}
|
||||
|
||||
default Settings getSettings() {
|
||||
return Settings.IMP;
|
||||
}
|
||||
|
||||
default void setSettings(Settings settings) {
|
||||
|
||||
}
|
||||
|
||||
void setWorld(String world);
|
||||
|
||||
World getWEWorld();
|
||||
|
||||
String getWorldName();
|
||||
|
||||
long getModified();
|
||||
|
||||
void setModified(long modified);
|
||||
|
||||
RunnableVal2<ProgressType, Integer> getProgressTask();
|
||||
|
||||
void setProgressTask(RunnableVal2<ProgressType, Integer> progressTask);
|
||||
|
||||
void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask);
|
||||
|
||||
RunnableVal2<FaweChunk, FaweChunk> getChangeTask();
|
||||
|
||||
SetQueue.QueueStage getStage();
|
||||
|
||||
void setStage(SetQueue.QueueStage stage);
|
||||
|
||||
void addNotifyTask(Runnable runnable);
|
||||
|
||||
void runTasks();
|
||||
|
||||
void addTask(Runnable whenFree);
|
||||
|
||||
default void forEachBlockInChunk(int cx, int cz, RunnableVal2<BlockVector3, BaseBlock> onEach) {
|
||||
int bx = cx << 4;
|
||||
int bz = cz << 4;
|
||||
MutableBlockVector3 mutable = new MutableBlockVector3(0, 0, 0);
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int xx = x + bx;
|
||||
mutable.mutX(xx);
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int zz = z + bz;
|
||||
mutable.mutZ(zz);
|
||||
for (int y = 0; y <= getMaxY(); y++) {
|
||||
int combined = getCombinedId4Data(xx, y, zz);
|
||||
BaseBlock block = BlockState.getFromInternalId(combined).toBaseBlock();
|
||||
BlockType type = block.getBlockType();
|
||||
if (type.getMaterial().isAir()) {
|
||||
continue;
|
||||
}
|
||||
mutable.mutY(y);
|
||||
CompoundTag tile = getTileEntity(x, y, z);
|
||||
if (tile != null) {
|
||||
onEach.run(mutable, block.toBaseBlock(tile));
|
||||
} else {
|
||||
onEach.run(mutable, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default void forEachTileInChunk(int cx, int cz, RunnableVal2<BlockVector3, BaseBlock> onEach) {
|
||||
int bx = cx << 4;
|
||||
int bz = cz << 4;
|
||||
MutableBlockVector3 mutable = new MutableBlockVector3(0, 0, 0);
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int xx = x + bx;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int zz = z + bz;
|
||||
for (int y = 0; y < getMaxY(); y++) {
|
||||
int combined = getCombinedId4Data(xx, y, zz);
|
||||
if (combined == 0) {
|
||||
continue;
|
||||
}
|
||||
BlockType type = BlockTypes.getFromStateId(combined);
|
||||
if (type.getMaterial().hasContainer()) {
|
||||
CompoundTag tile = getTileEntity(x, y, z);
|
||||
if (tile != null) {
|
||||
mutable.mutX(xx);
|
||||
mutable.mutZ(zz);
|
||||
mutable.mutY(y);
|
||||
BaseBlock block = BaseBlock.getFromInternalId(combined, tile);
|
||||
onEach.run(mutable, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default boolean regenerateChunk(int x, int z) {
|
||||
return regenerateChunk(x, z, null, null);
|
||||
}
|
||||
|
||||
boolean regenerateChunk(int x, int z, @Nullable BiomeType biome, @Nullable Long seed);
|
||||
|
||||
default void startSet(boolean parallel) {
|
||||
}
|
||||
|
||||
default void endSet(boolean parallel) {
|
||||
}
|
||||
|
||||
default int cancel() {
|
||||
clear();
|
||||
int count = 0;
|
||||
for (EditSession session : getEditSessions()) {
|
||||
if (session.cancel()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void sendBlockUpdate(FaweChunk chunk, FawePlayer... players);
|
||||
|
||||
default void sendChunkUpdate(FaweChunk chunk, FawePlayer... players) {
|
||||
sendBlockUpdate(chunk, players);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default boolean next() {
|
||||
int amount = Settings.IMP.QUEUE.PARALLEL_THREADS;
|
||||
long time = 20; // 30ms
|
||||
return next(amount, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the FaweChunk and sets the requested blocks
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean next(int amount, long time);
|
||||
|
||||
default void saveMemory() {
|
||||
MainUtil.sendAdmin(BBC.OOM.s());
|
||||
// Set memory limited
|
||||
MemUtil.memoryLimitedTask();
|
||||
// Clear block placement
|
||||
clear();
|
||||
Fawe.get().getWorldEdit().getSessionManager().clear();
|
||||
// GC
|
||||
System.gc();
|
||||
System.gc();
|
||||
// Unload chunks
|
||||
}
|
||||
|
||||
void sendChunk(FaweChunk chunk);
|
||||
|
||||
void sendChunk(int x, int z, int bitMask);
|
||||
|
||||
/**
|
||||
* This method is called when the server is < 1% available memory
|
||||
*/
|
||||
void clear();
|
||||
|
||||
default boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
return getCombinedId4Data(x, y, z) != 0;
|
||||
}
|
||||
|
||||
BiomeType getBiomeType(int x, int z) throws FaweException.FaweChunkLoadException;
|
||||
|
||||
int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
|
||||
|
||||
int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
|
||||
|
||||
default int getAdjacentLight(int x, int y, int z) {
|
||||
int light = 0;
|
||||
if ((light = Math.max(light, getSkyLight(x - 1, y, z))) == 15) {
|
||||
return light;
|
||||
}
|
||||
if ((light = Math.max(light, getSkyLight(x + 1, y, z))) == 15) {
|
||||
return light;
|
||||
}
|
||||
if ((light = Math.max(light, getSkyLight(x, y, z - 1))) == 15) {
|
||||
return light;
|
||||
}
|
||||
return Math.max(light, getSkyLight(x, y, z + 1));
|
||||
}
|
||||
|
||||
boolean hasSky();
|
||||
|
||||
int getSkyLight(int x, int y, int z);
|
||||
|
||||
default int getLight(int x, int y, int z) {
|
||||
if (!hasSky()) {
|
||||
return getEmmittedLight(x, y, z);
|
||||
}
|
||||
return Math.max(getSkyLight(x, y, z), getEmmittedLight(x, y, z));
|
||||
}
|
||||
|
||||
int getEmmittedLight(int x, int y, int z);
|
||||
|
||||
CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException;
|
||||
|
||||
default int getCombinedId4Data(int x, int y, int z, int def) {
|
||||
try {
|
||||
return getCombinedId4Data(x, y, z);
|
||||
} catch (FaweException ignore) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
default int getCachedCombinedId4Data(int x, int y, int z, int def) {
|
||||
try {
|
||||
return getCachedCombinedId4Data(x, y, z);
|
||||
} catch (FaweException ignore) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
default int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) {
|
||||
try {
|
||||
return getCombinedId4Data(x, y, z);
|
||||
} catch (FaweException ignore) {
|
||||
BBC.WORLDEDIT_FAILED_LOAD_CHUNK.send(session.getPlayer(),x >> 4, z >> 4);
|
||||
return def;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return BlockTypes.AIR.getInternalId();
|
||||
}
|
||||
}
|
||||
|
||||
default int getBrightness(int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
return BlockTypes.getFromStateId(combined).getMaterial().getLightValue();
|
||||
}
|
||||
|
||||
default int getOpacityBrightnessPair(int x, int y, int z) {
|
||||
return MathMan.pair16(Math.min(15, getOpacity(x, y, z)), getBrightness(x, y, z));
|
||||
}
|
||||
|
||||
default int getOpacity(int x, int y, int z) {
|
||||
int combined = getCombinedId4Data(x, y, z);
|
||||
if (combined == 0) {
|
||||
return 0;
|
||||
}
|
||||
return BlockTypes.getFromStateId(combined).getMaterial().getLightOpacity();
|
||||
}
|
||||
|
||||
int size();
|
||||
|
||||
default boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the thread until the queue is empty
|
||||
*/
|
||||
default void flush() {
|
||||
flush(10000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the thread until the queue is empty
|
||||
*/
|
||||
default void flush(int time) {
|
||||
if (size() > 0) {
|
||||
if (Fawe.isMainThread()) {
|
||||
SetQueue.IMP.flush(this);
|
||||
} else {
|
||||
if (enqueue()) {
|
||||
while (!isEmpty() && getStage() == SetQueue.QueueStage.ACTIVE) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
this.wait(time);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default boolean enqueue() {
|
||||
return SetQueue.IMP.enqueue(this);
|
||||
}
|
||||
|
||||
default void dequeue() {
|
||||
SetQueue.IMP.dequeue(this);
|
||||
}
|
||||
}
|
@ -28,7 +28,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
public class HistoryExtent extends AbstractDelegateExtent {
|
||||
|
||||
private FaweChangeSet changeSet;
|
||||
private final FaweQueue queue;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
@ -36,10 +35,9 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
* @param extent the extent
|
||||
* @param changeSet the change set
|
||||
*/
|
||||
public HistoryExtent(final Extent extent, final FaweChangeSet changeSet, FaweQueue queue) {
|
||||
public HistoryExtent(final Extent extent, final FaweChangeSet changeSet) {
|
||||
super(extent);
|
||||
checkNotNull(changeSet);
|
||||
this.queue = queue;
|
||||
this.changeSet = changeSet;
|
||||
}
|
||||
|
||||
@ -53,7 +51,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) throws WorldEditException {
|
||||
BaseBlock previous = queue.getFullBlock(x, y, z);
|
||||
BaseBlock previous = getFullBlock(x, y, z);
|
||||
if (previous.getInternalId() == block.getInternalId()) {
|
||||
if (!previous.hasNbtData() && (block instanceof BaseBlock && !block.hasNbtData())) {
|
||||
return false;
|
||||
@ -63,6 +61,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
return getExtent().setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(final BlockVector3 location, final B block) throws WorldEditException {
|
||||
return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block);
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.boydti.fawe.object.brush.visualization;
|
||||
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
|
||||
@ -11,17 +9,14 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.world.SimpleWorld;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface VirtualWorld extends SimpleWorld, FaweQueue, Closeable {
|
||||
public interface VirtualWorld extends SimpleWorld, Closeable {
|
||||
Vector3 getOrigin();
|
||||
|
||||
FaweChunk getSnapshot(int chunkX, int chunkZ);
|
||||
|
||||
@Override
|
||||
default BaseBlock getFullBlock(BlockVector3 position) {
|
||||
return getBlock(position).toBaseBlock();
|
||||
@ -38,16 +33,6 @@ public interface VirtualWorld extends SimpleWorld, FaweQueue, Closeable {
|
||||
@Override
|
||||
boolean setBlock(BlockVector3 pt, BlockStateHolder block) throws WorldEditException;
|
||||
|
||||
@Override
|
||||
default BlockVector3 getMaximumPoint() {
|
||||
return FaweQueue.super.getMaximumPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
default BlockVector3 getMinimumPoint() {
|
||||
return FaweQueue.super.getMinimumPoint();
|
||||
}
|
||||
|
||||
FawePlayer getPlayer();
|
||||
|
||||
void update();
|
||||
|
@ -6,10 +6,10 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
@ -20,6 +20,7 @@ import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.task.LinkedFuture;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
@ -29,6 +30,8 @@ import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class FaweChangeSet implements ChangeSet {
|
||||
@ -244,105 +247,15 @@ public abstract class FaweChangeSet implements ChangeSet {
|
||||
}
|
||||
}
|
||||
|
||||
public void addChangeTask(FaweQueue queue) {
|
||||
queue.setChangeTask(new RunnableVal2<FaweChunk, FaweChunk>() {
|
||||
@Override
|
||||
public void run(final FaweChunk previous, final FaweChunk next) {
|
||||
public Future<?> addWriteTask(Runnable writeTask) {
|
||||
return addWriteTask(writeTask, Fawe.isMainThread());
|
||||
}
|
||||
|
||||
public Future<?> addWriteTask(Runnable writeTask, boolean completeNow) {
|
||||
FaweChangeSet.this.waitingCombined.incrementAndGet();
|
||||
Runnable run = () -> {
|
||||
Runnable wrappedTask = () -> {
|
||||
try {
|
||||
int cx = previous.getX();
|
||||
int cz = previous.getZ();
|
||||
int bx = cx << 4;
|
||||
int bz = cz << 4;
|
||||
synchronized (FaweChangeSet.this) {
|
||||
BiomeType[] previousBiomes = previous.getBiomeArray();
|
||||
if (previousBiomes != null) {
|
||||
BiomeType[] nextBiomes = next.getBiomeArray();
|
||||
int index = 0;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int zz = bz + z;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
BiomeType idFrom = previousBiomes[index];
|
||||
BiomeType idTo = nextBiomes[index];
|
||||
if (idFrom != idTo && idTo != null) {
|
||||
addBiomeChange(bx + x, zz, idFrom, idTo);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Block changes
|
||||
for (int layer = 0; layer < layers; layer++) {
|
||||
int[] currentLayer = next.getIdArray(layer);
|
||||
int[] previousLayer = previous.getIdArray(layer);
|
||||
if (currentLayer == null) {
|
||||
continue;
|
||||
}
|
||||
int startY = layer << 4;
|
||||
int index = 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
int yy = y + startY;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int zz = z + bz;
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
int xx = x + bx;
|
||||
int combinedIdCurrent = currentLayer[index];
|
||||
if (combinedIdCurrent != 0) {
|
||||
int combinedIdPrevious;
|
||||
if (previousLayer != null) {
|
||||
combinedIdPrevious = previousLayer[index];
|
||||
if (combinedIdPrevious == 0) {
|
||||
combinedIdPrevious = BlockID.AIR;
|
||||
}
|
||||
} else {
|
||||
combinedIdPrevious = BlockID.AIR;
|
||||
}
|
||||
if (combinedIdCurrent != combinedIdPrevious) {
|
||||
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Tile changes
|
||||
{
|
||||
// Tiles created
|
||||
Map<Short, CompoundTag> tiles = next.getTiles();
|
||||
if (!tiles.isEmpty()) {
|
||||
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
|
||||
addTileCreate(entry.getValue());
|
||||
}
|
||||
}
|
||||
// Tiles removed
|
||||
tiles = previous.getTiles();
|
||||
if (!tiles.isEmpty()) {
|
||||
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
|
||||
addTileRemove(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Entity changes
|
||||
{
|
||||
// Entities created
|
||||
Set<CompoundTag> entities = next.getEntities();
|
||||
if (!entities.isEmpty()) {
|
||||
for (CompoundTag entityTag : entities) {
|
||||
addEntityCreate(entityTag);
|
||||
}
|
||||
}
|
||||
// Entities removed
|
||||
entities = previous.getEntities();
|
||||
if (!entities.isEmpty()) {
|
||||
for (CompoundTag entityTag : entities) {
|
||||
addEntityRemove(entityTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
writeTask.run();
|
||||
} finally {
|
||||
if (FaweChangeSet.this.waitingCombined.decrementAndGet() <= 0) {
|
||||
synchronized (FaweChangeSet.this.waitingAsync) {
|
||||
@ -354,12 +267,11 @@ public abstract class FaweChangeSet implements ChangeSet {
|
||||
}
|
||||
}
|
||||
};
|
||||
if (mainThread) {
|
||||
run.run();
|
||||
if (completeNow) {
|
||||
wrappedTask.run();
|
||||
return Futures.immediateCancelledFuture();
|
||||
} else {
|
||||
TaskManager.IMP.getPublicForkJoinPool().submit(run);
|
||||
return Fawe.get().getQueueHandler().async(wrappedTask);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.object.exception;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
public class FaweException extends RuntimeException {
|
||||
public static final FaweChunkLoadException CHUNK = new FaweChunkLoadException();
|
||||
@ -14,15 +15,33 @@ public class FaweException extends RuntimeException {
|
||||
public static final FaweException MAX_ENTITIES = new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_ENTITIES);
|
||||
public static final FaweException MAX_TILES = new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
|
||||
|
||||
private final BBC message;
|
||||
// DEBUG
|
||||
public static final FaweException _enableQueue;
|
||||
public static final FaweException _disableQueue;
|
||||
|
||||
static {
|
||||
try {
|
||||
_enableQueue = new FaweException(Extent.class.getDeclaredMethod("enableQueue").toString());
|
||||
_disableQueue = new FaweException(Extent.class.getDeclaredMethod("disableQueue").toString());
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final String message;
|
||||
|
||||
public FaweException(String reason) {
|
||||
this.message = reason;
|
||||
}
|
||||
|
||||
public FaweException(BBC reason) {
|
||||
this.message = reason;
|
||||
this(reason.format());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message == null ? null : message.format();
|
||||
return message;
|
||||
}
|
||||
|
||||
public static FaweException get(Throwable e) {
|
||||
|
@ -199,6 +199,11 @@ public class EditSessionBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public EditSessionBuilder eventBus(@Nullable EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EditSessionBuilder event(@Nullable EditSessionEvent event) {
|
||||
this.event = event;
|
||||
return this;
|
||||
|
@ -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,7 +1161,9 @@ 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 -> {
|
||||
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;
|
||||
@ -1167,7 +1184,8 @@ public class EditSession extends AbstractDelegateExtent implements SimpleWorld,
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -272,4 +272,9 @@ public interface World extends Extent {
|
||||
@Override
|
||||
int hashCode();
|
||||
|
||||
@Override
|
||||
default boolean isWorld() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user