geforkt von Mirrors/FastAsyncWorldEdit
shift extent queue methods
Dieser Commit ist enthalten in:
Ursprung
2c22f02c20
Commit
0a924915c8
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
@Override
|
||||||
int hashCode();
|
int hashCode();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean isWorld() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren