Start reimplementing chunk generation.

This would either need to be one WorldEdit operation or (preferable) WorldEdit allows Extents (including EditSessions) into the regenerate adapter method
This commit is contained in:
dordsor21 2020-07-19 13:12:27 +01:00
parent 3e84f3b3a4
commit 656700b5be
No known key found for this signature in database
GPG Key ID: 1E53E88969FFCF0B
11 changed files with 223 additions and 80 deletions

View File

@ -32,11 +32,12 @@ import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import javax.annotation.Nonnull;
import javax.annotation.Nonnull;
import java.util.Random; import java.util.Random;
final class BlockStatePopulator extends BlockPopulator { final class BlockStatePopulator extends BlockPopulator {
@ -52,12 +53,11 @@ final class BlockStatePopulator extends BlockPopulator {
this.plotAreaManager = plotAreaManager; this.plotAreaManager = plotAreaManager;
} }
@Override @Override public void populate(@Nonnull final World world, @Nonnull final Random random,
public void populate(@Nonnull final World world, @Nonnull final Random random,
@Nonnull final Chunk source) { @Nonnull final Chunk source) {
if (this.queue == null) { if (this.queue == null) {
this.queue = PlotSquared.platform().getGlobalBlockQueue() this.queue =
.getNewQueue(world.getName()); PlotSquared.platform().getGlobalBlockQueue().getNewQueue(new BukkitWorld(world));
} }
final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null); final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null);
if (area == null) { if (area == null) {

View File

@ -25,6 +25,8 @@
*/ */
package com.plotsquared.bukkit.queue; package com.plotsquared.bukkit.queue;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
@ -72,10 +74,13 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
private final AtomicInteger expectedSize; private final AtomicInteger expectedSize;
private int batchSize; private int batchSize;
private BukkitChunkCoordinator(final long maxIterationTime, final int initialBatchSize, @Inject private BukkitChunkCoordinator(@Assisted final long maxIterationTime,
@Nonnull final Consumer<BlockVector2> chunkConsumer, @Nonnull final World world, @Assisted final int initialBatchSize,
@Nonnull final Collection<BlockVector2> requestedChunks, @Nonnull final Runnable whenDone, @Assisted @Nonnull final Consumer<BlockVector2> chunkConsumer,
@Nonnull final Consumer<Throwable> throwableConsumer) { @Assisted @Nonnull final World world,
@Assisted @Nonnull final Collection<BlockVector2> requestedChunks,
@Assisted @Nonnull final Runnable whenDone,
@Assisted @Nonnull final Consumer<Throwable> throwableConsumer) {
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks); this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
this.availableChunks = new LinkedBlockingQueue<>(); this.availableChunks = new LinkedBlockingQueue<>();
this.totalSize = requestedChunks.size(); this.totalSize = requestedChunks.size();

View File

@ -31,14 +31,18 @@ import com.plotsquared.bukkit.util.BukkitBlockUtil;
import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.queue.BasicQueueCoordinator; import com.plotsquared.core.queue.BasicQueueCoordinator;
import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.queue.LocalChunk; import com.plotsquared.core.queue.LocalChunk;
import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.BlockUtil;
import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MainUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -59,9 +63,11 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
private final World world; private final World world;
private final SideEffectSet sideEffectSet; private final SideEffectSet sideEffectSet;
private org.bukkit.World bukkitWorld;
@Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory; @Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
@Inject private ChunkCoordinatorFactory chunkCoordinatorFactory; @Inject private ChunkCoordinatorFactory chunkCoordinatorFactory;
private Runnable whenDone; private Runnable whenDone;
private ChunkCoordinator chunkCoordinator;
@Inject public BukkitQueueCoordinator(World world) { @Inject public BukkitQueueCoordinator(World world) {
super(world); super(world);
@ -80,17 +86,52 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
} }
} }
@Override public void start() {
chunkCoordinator.start();
}
//TODO: implement cancellation
@Override public void cancel() {
chunkCoordinator.cancel();
}
@Override public boolean enqueue() { @Override public boolean enqueue() {
final EditSession editSession;
if (isRegen()) {
editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
world.regenerate(new CuboidRegion(
BlockVector3.at(getRegenStart()[0] << 4, 0, getRegenStart()[1] << 4),
BlockVector3.at((getRegenEnd()[0] << 4) + 15, 255, (getRegenEnd()[1] << 4) + 15)),
editSession);
} else {
editSession = null;
}
Consumer<BlockVector2> consumer = getChunkConsumer(); Consumer<BlockVector2> consumer = getChunkConsumer();
if (consumer == null) { if (consumer == null) {
consumer = blockVector2 -> { consumer = blockVector2 -> {
LocalChunk localChunk = getBlockChunks().get(blockVector2); LocalChunk localChunk = getBlockChunks().get(blockVector2);
if (localChunk == null) { boolean isRegenChunk =
editSession != null && blockVector2.getBlockX() > getRegenStart()[0]
&& blockVector2.getBlockZ() > getRegenStart()[1]
&& blockVector2.getBlockX() < getRegenEnd()[0]
&& blockVector2.getBlockZ() < getRegenEnd()[1];
if (isRegenChunk) {
for (int layer = 0; layer < 16; layer++) {
for (int y = layer << 4; y < 16; y++) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
BaseBlock block =
editSession.getFullBlock(BlockVector3.at(x, y, z));
setWorldBlock(x, y, z, block, blockVector2);
}
}
}
}
return;
} else if (localChunk == null) {
throw new NullPointerException( throw new NullPointerException(
"LocalChunk cannot be null when accessed from ChunkCoordinator"); "LocalChunk cannot be null when accessed from ChunkCoordinator");
} }
org.bukkit.World bukkitWorld = null;
Chunk chunk = null;
int sx = blockVector2.getX() << 4; int sx = blockVector2.getX() << 4;
int sz = blockVector2.getZ() << 4; int sz = blockVector2.getZ() << 4;
for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) { for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) {
@ -106,42 +147,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
int x = sx + MainUtil.x_loc[layer][j]; int x = sx + MainUtil.x_loc[layer][j];
int y = MainUtil.y_loc[layer][j]; int y = MainUtil.y_loc[layer][j];
int z = sz + MainUtil.z_loc[layer][j]; int z = sz + MainUtil.z_loc[layer][j];
try { setWorldBlock(x, y, z, block, blockVector2);
world.setBlock(BlockVector3.at(x, y, z), block, sideEffectSet);
} catch (WorldEditException ignored) {
// Fallback to not so nice method
BlockData blockData = BukkitAdapter.adapt(block);
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getWorld(world.getName());
}
if (chunk == null) {
chunk = bukkitWorld
.getChunkAt(blockVector2.getX(), blockVector2.getZ());
}
Block existing = chunk.getBlock(x, y, z);
final BlockState existingBaseBlock =
BukkitAdapter.adapt(existing.getBlockData());
if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing
.getBlockData().matches(blockData)) {
continue;
}
if (existing.getState() instanceof Container) {
((Container) existing.getState()).getInventory().clear();
}
existing.setType(BukkitAdapter.adapt(block.getBlockType()), false);
existing.setBlockData(blockData, false);
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(world.getName(), existing.getX(), existing.getY(),
existing.getZ());
}
}
} }
} }
for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) { for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) {
@ -174,13 +180,48 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
} }
}; };
} }
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world) chunkCoordinator =
.withChunks(getBlockChunks().keySet()).withInitialBatchSize(3).withMaxIterationTime(40) chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world)
.withThrowableConsumer(Throwable::printStackTrace).withFinalAction(whenDone) .withChunks(getBlockChunks().keySet()).withInitialBatchSize(3)
.withConsumer(consumer); .withMaxIterationTime(40).withThrowableConsumer(Throwable::printStackTrace)
.withFinalAction(whenDone).withConsumer(consumer).build();
return super.enqueue(); return super.enqueue();
} }
private void setWorldBlock(int x, int y, int z, BaseBlock block, BlockVector2 blockVector2) {
try {
world.setBlock(BlockVector3.at(x, y, z), block, sideEffectSet);
} catch (WorldEditException ignored) {
// Fallback to not so nice method
BlockData blockData = BukkitAdapter.adapt(block);
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getWorld(world.getName());
}
Chunk chunk = bukkitWorld.getChunkAt(blockVector2.getX(), blockVector2.getZ());
Block existing = chunk.getBlock(x, y, z);
final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData());
if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData()
.matches(blockData)) {
return;
}
if (existing.getState() instanceof Container) {
((Container) existing.getState()).getInventory().clear();
}
existing.setType(BukkitAdapter.adapt(block.getBlockType()), false);
existing.setBlockData(blockData, false);
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(world.getName(), existing.getX(), existing.getY(), existing.getZ());
}
}
}
@Override public void setCompleteTask(Runnable whenDone) { @Override public void setCompleteTask(Runnable whenDone) {
this.whenDone = whenDone; this.whenDone = whenDone;
} }

View File

@ -293,7 +293,7 @@ public class BukkitRegionManager extends RegionManager {
int zzt = zzb + 15; int zzt = zzb + 15;
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
AugmentedUtils.bypass(ignoreAugment, AugmentedUtils.bypass(ignoreAugment,
() -> queue.regenChunkSafe(chunk.getX(), chunk.getZ())); () -> queue.regenChunk(chunk.getX(), chunk.getZ()));
return; return;
} }
boolean checkX1 = false; boolean checkX1 = false;

View File

@ -25,7 +25,6 @@
*/ */
package com.plotsquared.core.inject.factory; package com.plotsquared.core.inject.factory;
import com.google.inject.assistedinject.Assisted;
import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.ChunkCoordinator;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -37,12 +36,9 @@ import java.util.function.Consumer;
public interface ChunkCoordinatorFactory { public interface ChunkCoordinatorFactory {
@Nonnull ChunkCoordinator create(@Assisted final long maxIterationTime, @Nonnull ChunkCoordinator create(final long maxIterationTime, final int initialBatchSize,
@Assisted final int initialBatchSize, @NotNull final Consumer<BlockVector2> chunkConsumer, @NotNull final World world,
@NotNull @Assisted final Consumer<BlockVector2> chunkConsumer, @NotNull final Collection<BlockVector2> requestedChunks, @NotNull final Runnable whenDone,
@NotNull @Assisted final World world, @NotNull final Consumer<Throwable> throwableConsumer);
@NotNull @Assisted final Collection<BlockVector2> requestedChunks,
@NotNull @Assisted final Runnable whenDone,
@NotNull @Assisted final Consumer<Throwable> throwableConsumer);
} }

View File

@ -27,6 +27,7 @@ package com.plotsquared.core.plot;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.collection.QuadMap; import com.plotsquared.core.collection.QuadMap;
import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.CaptionUtility;
import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Captions;

View File

@ -49,6 +49,9 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
private int lastZ = Integer.MIN_VALUE; private int lastZ = Integer.MIN_VALUE;
private boolean settingBiomes = false; private boolean settingBiomes = false;
private boolean settingTiles = false; private boolean settingTiles = false;
private boolean regen = false;
private int[] regenStart;
private int[] regenEnd;
private Consumer<BlockVector2> consumer = null; private Consumer<BlockVector2> consumer = null;
private GlobalBlockQueue globalBlockQueue; private GlobalBlockQueue globalBlockQueue;
@ -129,6 +132,40 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
return this.settingTiles; return this.settingTiles;
} }
@Override public void regenChunk(int x, int z) {
regen = true;
// There will never only be one nullified coordinate pair
if (regenStart == null) {
regenStart = new int[]{x, z};
regenEnd = new int[]{x, z};
return;
}
if (x < regenStart[0]) {
regenStart[0] = x;
}
if (z < regenStart[1]) {
regenStart[1] = z;
}
if (x > regenEnd[0]) {
regenEnd[0] = x;
}
if (z > regenEnd[1]) {
regenEnd[1] = z;
}
}
public int[] getRegenStart() {
return regenStart;
}
public int[] getRegenEnd() {
return regenEnd;
}
public boolean isRegen() {
return regen;
}
public ConcurrentHashMap<BlockVector2, LocalChunk> getBlockChunks() { public ConcurrentHashMap<BlockVector2, LocalChunk> getBlockChunks() {
return this.blockChunks; return this.blockChunks;
} }

View File

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -18,6 +19,7 @@ import java.util.function.Consumer;
public class ChunkCoordinatorBuilder { public class ChunkCoordinatorBuilder {
private final List<BlockVector2> requestedChunks = new LinkedList<>(); private final List<BlockVector2> requestedChunks = new LinkedList<>();
private final ChunkCoordinatorFactory chunkCoordinatorFactory;
private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace; private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace;
private World world; private World world;
private Consumer<BlockVector2> chunkConsumer; private Consumer<BlockVector2> chunkConsumer;
@ -25,9 +27,9 @@ public class ChunkCoordinatorBuilder {
}; };
private long maxIterationTime = 60; // A little over 1 tick; private long maxIterationTime = 60; // A little over 1 tick;
private int initialBatchSize = 4; private int initialBatchSize = 4;
private final ChunkCoordinatorFactory chunkCoordinatorFactory;
@Inject public ChunkCoordinatorBuilder(@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory) { @Inject
public ChunkCoordinatorBuilder(@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory) {
this.chunkCoordinatorFactory = chunkCoordinatorFactory; this.chunkCoordinatorFactory = chunkCoordinatorFactory;
} }
@ -105,9 +107,9 @@ public class ChunkCoordinatorBuilder {
Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied"); Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied");
Preconditions.checkNotNull(this.whenDone, "No final action was supplied"); Preconditions.checkNotNull(this.whenDone, "No final action was supplied");
Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied"); Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied");
return chunkCoordinatorFactory.create(this.maxIterationTime, this.initialBatchSize, return chunkCoordinatorFactory
this.chunkConsumer, this.world, this.requestedChunks, this.whenDone, .create(this.maxIterationTime, this.initialBatchSize, this.chunkConsumer, this.world,
this.throwableConsumer); this.requestedChunks, this.whenDone, this.throwableConsumer);
} }
} }

View File

@ -65,43 +65,79 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
} }
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) { @Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
return parent.setBlock(x, y, z, pattern); if (parent != null) {
return parent.setBlock(x, y, z, pattern);
}
return false;
} }
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) { @Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
return parent.setBlock(x, y, z, id); if (parent != null) {
return parent.setBlock(x, y, z, id);
}
return false;
} }
@Override public boolean setBlock(int x, int y, int z, BlockState id) { @Override public boolean setBlock(int x, int y, int z, BlockState id) {
return parent.setBlock(x, y, z, id); if (parent != null) {
return parent.setBlock(x, y, z, id);
}
return false;
} }
@Override public BlockState getBlock(int x, int y, int z) { @Override public BlockState getBlock(int x, int y, int z) {
return parent.getBlock(x, y, z); if (parent != null) {
return parent.getBlock(x, y, z);
}
return null;
} }
@Override public boolean setBiome(int x, int z, BiomeType biome) { @Override public boolean setBiome(int x, int z, BiomeType biome) {
return parent.setBiome(x, z, biome); if (parent != null) {
return parent.setBiome(x, z, biome);
}
return false;
} }
@Override public boolean setBiome(int x, int y, int z, BiomeType biome) { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) {
return parent.setBiome(x, y, z, biome); if (parent != null) {
return parent.setBiome(x, y, z, biome);
}
return false;
} }
@Override public boolean isSettingBiomes() { @Override public boolean isSettingBiomes() {
return parent.isSettingBiomes(); if (parent != null) {
return parent.isSettingBiomes();
}
return false;
}
@Override public void regenChunk(int x, int z) {
if (parent != null) {
parent.regenChunk(x, z);
}
} }
@Override public World getWorld() { @Override public World getWorld() {
return parent.getWorld(); if (parent != null) {
return parent.getWorld();
}
return null;
} }
@Override public boolean setTile(int x, int y, int z, CompoundTag tag) { @Override public boolean setTile(int x, int y, int z, CompoundTag tag) {
return parent.setTile(x, y, z, tag); if (parent != null) {
return parent.setTile(x, y, z, tag);
}
return false;
} }
@Override public boolean isSettingTiles() { @Override public boolean isSettingTiles() {
return parent.isSettingTiles(); if (parent != null) {
return parent.isSettingTiles();
}
return false;
} }
@Override public boolean enqueue() { @Override public boolean enqueue() {
@ -111,11 +147,27 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
return false; return false;
} }
@Override public void start() {
if (parent != null) {
parent.start();
}
}
@Override public void cancel() {
if (parent != null) {
parent.cancel();
}
}
@Override public void setCompleteTask(Runnable whenDone) { @Override public void setCompleteTask(Runnable whenDone) {
parent.setCompleteTask(whenDone); if (parent != null) {
parent.setCompleteTask(whenDone);
}
} }
@Override public void setChunkConsumer(Consumer<BlockVector2> consumer) { @Override public void setChunkConsumer(Consumer<BlockVector2> consumer) {
parent.setChunkConsumer(consumer); if (parent != null) {
parent.setChunkConsumer(consumer);
}
} }
} }

View File

@ -58,20 +58,23 @@ public class GlobalBlockQueue {
} }
/** /**
* TODO Documentation needed. * Place an instance of {@link QueueCoordinator} into a list incase access is needed
* and then start it.
* *
* @param queue todo * @param queue {@link QueueCoordinator} instance to start.
* @return true if added to queue, false otherwise * @return true if added to queue, false otherwise
*/ */
public boolean enqueue(QueueCoordinator queue) { public boolean enqueue(QueueCoordinator queue) {
boolean success = false; boolean success = false;
if (queue.size() > 0 && !activeQueues.contains(queue)) { if (queue.size() > 0 && !activeQueues.contains(queue)) {
success = activeQueues.add(queue); success = activeQueues.add(queue);
queue.start();
} }
return success; return success;
} }
public void dequeue(QueueCoordinator queue) { public void dequeue(QueueCoordinator queue) {
queue.cancel();
activeQueues.remove(queue); activeQueues.remove(queue);
} }

View File

@ -108,6 +108,8 @@ public abstract class QueueCoordinator {
public abstract boolean isSettingBiomes(); public abstract boolean isSettingBiomes();
public abstract void regenChunk(int x, int z);
public abstract World getWorld(); public abstract World getWorld();
public final void setModified() { public final void setModified() {
@ -118,6 +120,10 @@ public abstract class QueueCoordinator {
return blockQueue.enqueue(this); return blockQueue.enqueue(this);
} }
public abstract void start();
public abstract void cancel();
public abstract void setCompleteTask(Runnable whenDone); public abstract void setCompleteTask(Runnable whenDone);
public abstract void setChunkConsumer(Consumer<BlockVector2> consumer); public abstract void setChunkConsumer(Consumer<BlockVector2> consumer);