3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-11-09 13:00:05 +01:00

shift extent queue methods

Dieser Commit ist enthalten in:
Jesse Boyd 2019-07-19 02:07:31 +10:00
Ursprung 2c22f02c20
Commit 0a924915c8
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 59F1DE6293AF6E1F
15 geänderte Dateien mit 308 neuen und 699 gelöschten Zeilen

Datei anzeigen

@ -1,6 +1,7 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.boydti.fawe.beta.implementation.WorldChunkCache; import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; 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 * Interface for a queue based extent which uses chunks
*/ */
public interface IQueueExtent extends Flushable, Trimable, Extent { 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); void init(WorldChunkCache world);
/** /**

Datei anzeigen

@ -25,6 +25,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask; import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future; 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) { public <T> Future<T> async(final Runnable run, final T value) {
return forkJoinPoolSecondary.submit(run, 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) { public <T> Future<T> async(final Callable<T> call) {
return forkJoinPoolSecondary.submit(call); return forkJoinPoolSecondary.submit(call);
} }

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -28,7 +28,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class HistoryExtent extends AbstractDelegateExtent { public class HistoryExtent extends AbstractDelegateExtent {
private FaweChangeSet changeSet; private FaweChangeSet changeSet;
private final FaweQueue queue;
/** /**
* Create a new instance. * Create a new instance.
@ -36,10 +35,9 @@ public class HistoryExtent extends AbstractDelegateExtent {
* @param extent the extent * @param extent the extent
* @param changeSet the change set * @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); super(extent);
checkNotNull(changeSet); checkNotNull(changeSet);
this.queue = queue;
this.changeSet = changeSet; this.changeSet = changeSet;
} }
@ -53,7 +51,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
@Override @Override
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) throws WorldEditException { 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.getInternalId() == block.getInternalId()) {
if (!previous.hasNbtData() && (block instanceof BaseBlock && !block.hasNbtData())) { if (!previous.hasNbtData() && (block instanceof BaseBlock && !block.hasNbtData())) {
return false; return false;
@ -63,6 +61,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
return getExtent().setBlock(x, y, z, block); return getExtent().setBlock(x, y, z, block);
} }
@Override @Override
public <B extends BlockStateHolder<B>> boolean setBlock(final BlockVector3 location, final B block) throws WorldEditException { public <B extends BlockStateHolder<B>> boolean setBlock(final BlockVector3 location, final B block) throws WorldEditException {
return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block);

Datei anzeigen

@ -1,8 +1,6 @@
package com.boydti.fawe.object.brush.visualization; package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.BlockInteractEvent; 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.math.Vector3;
import com.sk89q.worldedit.world.SimpleWorld; import com.sk89q.worldedit.world.SimpleWorld;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
public interface VirtualWorld extends SimpleWorld, FaweQueue, Closeable { public interface VirtualWorld extends SimpleWorld, Closeable {
Vector3 getOrigin(); Vector3 getOrigin();
FaweChunk getSnapshot(int chunkX, int chunkZ);
@Override @Override
default BaseBlock getFullBlock(BlockVector3 position) { default BaseBlock getFullBlock(BlockVector3 position) {
return getBlock(position).toBaseBlock(); return getBlock(position).toBaseBlock();
@ -38,16 +33,6 @@ public interface VirtualWorld extends SimpleWorld, FaweQueue, Closeable {
@Override @Override
boolean setBlock(BlockVector3 pt, BlockStateHolder block) throws WorldEditException; 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(); FawePlayer getPlayer();
void update(); void update();

Datei anzeigen

@ -6,10 +6,10 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.google.common.util.concurrent.Futures;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extent.inventory.BlockBag; 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.history.changeset.ChangeSet;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.task.LinkedFuture;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -29,6 +30,8 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public abstract class FaweChangeSet implements ChangeSet { public abstract class FaweChangeSet implements ChangeSet {
@ -244,122 +247,31 @@ public abstract class FaweChangeSet implements ChangeSet {
} }
} }
public void addChangeTask(FaweQueue queue) { public Future<?> addWriteTask(Runnable writeTask) {
queue.setChangeTask(new RunnableVal2<FaweChunk, FaweChunk>() { return addWriteTask(writeTask, Fawe.isMainThread());
@Override }
public void run(final FaweChunk previous, final FaweChunk next) {
FaweChangeSet.this.waitingCombined.incrementAndGet(); public Future<?> addWriteTask(Runnable writeTask, boolean completeNow) {
Runnable run = () -> { FaweChangeSet.this.waitingCombined.incrementAndGet();
try { Runnable wrappedTask = () -> {
int cx = previous.getX(); try {
int cz = previous.getZ(); writeTask.run();
int bx = cx << 4; } finally {
int bz = cz << 4; if (FaweChangeSet.this.waitingCombined.decrementAndGet() <= 0) {
synchronized (FaweChangeSet.this) { synchronized (FaweChangeSet.this.waitingAsync) {
BiomeType[] previousBiomes = previous.getBiomeArray(); FaweChangeSet.this.waitingAsync.notifyAll();
if (previousBiomes != null) { }
BiomeType[] nextBiomes = next.getBiomeArray(); synchronized (FaweChangeSet.this.waitingCombined) {
int index = 0; FaweChangeSet.this.waitingCombined.notifyAll();
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();
} finally {
if (FaweChangeSet.this.waitingCombined.decrementAndGet() <= 0) {
synchronized (FaweChangeSet.this.waitingAsync) {
FaweChangeSet.this.waitingAsync.notifyAll();
}
synchronized (FaweChangeSet.this.waitingCombined) {
FaweChangeSet.this.waitingCombined.notifyAll();
}
}
} }
};
if (mainThread) {
run.run();
} else {
TaskManager.IMP.getPublicForkJoinPool().submit(run);
} }
} }
}); };
if (completeNow) {
wrappedTask.run();
return Futures.immediateCancelledFuture();
} else {
return Fawe.get().getQueueHandler().async(wrappedTask);
}
} }
} }

Datei anzeigen

@ -1,6 +1,7 @@
package com.boydti.fawe.object.exception; package com.boydti.fawe.object.exception;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.extent.Extent;
public class FaweException extends RuntimeException { public class FaweException extends RuntimeException {
public static final FaweChunkLoadException CHUNK = new FaweChunkLoadException(); 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_ENTITIES = new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_ENTITIES);
public static final FaweException MAX_TILES = new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES); 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) { public FaweException(BBC reason) {
this.message = reason; this(reason.format());
} }
@Override @Override
public String getMessage() { public String getMessage() {
return message == null ? null : message.format(); return message;
} }
public static FaweException get(Throwable e) { public static FaweException get(Throwable e) {

Datei anzeigen

@ -199,6 +199,11 @@ public class EditSessionBuilder {
return this; return this;
} }
public EditSessionBuilder eventBus(@Nullable EventBus eventBus) {
this.eventBus = eventBus;
return this;
}
public EditSessionBuilder event(@Nullable EditSessionEvent event) { public EditSessionBuilder event(@Nullable EditSessionEvent event) {
this.event = event; this.event = event;
return this; return this;

Datei anzeigen

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

Datei anzeigen

@ -21,12 +21,18 @@ package com.sk89q.worldedit.extent;
import static com.google.common.base.Preconditions.checkNotNull; 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.GenBase;
import com.boydti.fawe.jnbt.anvil.generator.Resource; 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.object.extent.LightingExtent;
import com.boydti.fawe.util.ExtentTraverser;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; 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.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue; import com.sk89q.worldedit.function.operation.OperationQueue;
@ -69,6 +75,58 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
return extent; 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 Bounds
*/ */

Datei anzeigen

@ -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.Resource;
import com.boydti.fawe.jnbt.anvil.generator.SchemGen; import com.boydti.fawe.jnbt.anvil.generator.SchemGen;
import com.boydti.fawe.object.clipboard.WorldCopyClipboard; import com.boydti.fawe.object.clipboard.WorldCopyClipboard;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity; 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.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Location; 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.BaseBlock;
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;
@ -133,6 +135,42 @@ public interface Extent extends InputExtent, OutputExtent {
return null; 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) { default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY) {
maxY = Math.min(maxY, Math.max(0, maxY)); maxY = Math.min(maxY, Math.max(0, maxY));
minY = Math.max(0, minY); minY = Math.max(0, minY);

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -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;
}
}

Datei anzeigen

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