diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java
similarity index 65%
rename from Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java
rename to Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java
index cc5c1f72f..ecb0f3500 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java
@@ -26,7 +26,7 @@
package com.plotsquared.bukkit.queue;
import com.google.common.base.Preconditions;
-import com.plotsquared.bukkit.BukkitMain;
+import com.plotsquared.bukkit.BukkitPlatform;
import com.sk89q.worldedit.math.BlockVector2;
import io.papermc.lib.PaperLib;
import org.bukkit.Chunk;
@@ -44,34 +44,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
-/**
- * Utility that allows for the loading and coordination of chunk actions
- *
- * The coordinator takes in collection of chunk coordinates, loads them
- * and allows the caller to specify a sink for the loaded chunks. The
- * coordinator will prevent the chunks from being unloaded until the sink
- * has fully consumed the chunk
- *
- *
- * @author Alexander Söderberg
- * @see #builder() To create a new coordinator instance
- */
-public final class ChunkCoordinator extends BukkitRunnable {
-
- private final List progressSubscribers = new LinkedList<>();
+public final class BukkitChunkCoordinator extends BukkitRunnable {
private final Queue requestedChunks;
private final Queue availableChunks;
@@ -80,48 +53,32 @@ public final class ChunkCoordinator extends BukkitRunnable {
private final Consumer chunkConsumer;
private final World world;
private final Runnable whenDone;
- private final Consumer throwableConsumer;
- private final int totalSize;
private AtomicInteger expectedSize;
private int batchSize;
- private ChunkCoordinator(final long maxIterationTime, final int initialBatchSize,
+ private BukkitChunkCoordinator(final long maxIterationTime, final int initialBatchSize,
@NotNull final Consumer chunkConsumer, @NotNull final World world,
- @NotNull final Collection requestedChunks, @NotNull final Runnable whenDone,
- @NotNull final Consumer throwableConsumer) {
+ @NotNull final Collection requestedChunks, @NotNull final Runnable whenDone) {
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
this.availableChunks = new LinkedBlockingQueue<>();
- this.totalSize = requestedChunks.size();
- this.expectedSize = new AtomicInteger(this.totalSize);
+ this.expectedSize = new AtomicInteger(requestedChunks.size());
this.world = world;
this.batchSize = initialBatchSize;
this.chunkConsumer = chunkConsumer;
this.maxIterationTime = maxIterationTime;
this.whenDone = whenDone;
- this.throwableConsumer = throwableConsumer;
- this.plugin = JavaPlugin.getPlugin(BukkitMain.class);
- }
-
- /**
- * Create a new {@link ChunkCoordinator} instance
- *
- * @return Coordinator builder instance
- */
- @NotNull public static ChunkCoordinatorBuilder builder() {
- return new ChunkCoordinatorBuilder();
- }
-
- /**
- * Start the coordinator instance
- */
- public void start() {
+ this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
// Request initial batch
this.requestBatch();
// Wait until next tick to give the chunks a chance to be loaded
this.runTaskTimer(this.plugin, 1L, 1L);
}
+ @NotNull public static ChunkCoordinatorBuilder builder() {
+ return new ChunkCoordinatorBuilder();
+ }
+
@Override public void run() {
Chunk chunk = this.availableChunks.poll();
if (chunk == null) {
@@ -133,8 +90,7 @@ public final class ChunkCoordinator extends BukkitRunnable {
final long start = System.currentTimeMillis();
try {
this.chunkConsumer.accept(chunk);
- } catch (final Throwable throwable) {
- this.throwableConsumer.accept(throwable);
+ } catch (final Exception ignored) {
}
this.freeChunk(chunk);
processedChunks++;
@@ -147,19 +103,10 @@ public final class ChunkCoordinator extends BukkitRunnable {
// Adjust batch size based on the amount of processed chunks per tick
this.batchSize = processedChunks;
}
-
- final int expected = this.expectedSize.addAndGet(-processedChunks);
-
- final float progress = ((float) totalSize - (float) expected) / (float) totalSize;
- for (final ProgressSubscriber subscriber : this.progressSubscribers) {
- subscriber.notifyProgress(this, progress);
- }
-
- if (expected <= 0) {
+ if (this.expectedSize.addAndGet(-processedChunks) <= 0) {
try {
this.whenDone.run();
- } catch (final Throwable throwable) {
- this.throwableConsumer.accept(throwable);
+ } catch (final Exception ignored) {
}
this.cancel();
} else {
@@ -203,52 +150,10 @@ public final class ChunkCoordinator extends BukkitRunnable {
chunk.removePluginChunkTicket(this.plugin);
}
- /**
- * Get the amount of remaining chunks (at the time of the method call)
- *
- * @return Snapshot view of remaining chunk count
- */
- public int getRemainingChunks() {
- return this.expectedSize.get();
- }
-
- /**
- * Get the amount of requested chunks
- *
- * @return Requested chunk count
- */
- public int getTotalChunks() {
- return this.totalSize;
- }
-
- /**
- * Subscribe to coordinator progress updates
- *
- * @param subscriber Subscriber
- */
- public void subscribeToProgress(@NotNull final ChunkCoordinator.ProgressSubscriber subscriber) {
- this.progressSubscribers.add(subscriber);
- }
-
-
- @FunctionalInterface
- public interface ProgressSubscriber {
-
- /**
- * Notify about a progress update in the coordinator
- *
- * @param coordinator Coordinator instance that triggered the notification
- * @param progress Progress in the range [0, 1]
- */
- void notifyProgress(@NotNull final ChunkCoordinator coordinator, final float progress);
-
- }
-
public static final class ChunkCoordinatorBuilder {
private final List requestedChunks = new LinkedList<>();
- private Consumer throwableConsumer = Throwable::printStackTrace;
private World world;
private Consumer chunkConsumer;
private Runnable whenDone = () -> {
@@ -303,22 +208,12 @@ public final class ChunkCoordinator extends BukkitRunnable {
return this;
}
- @NotNull public ChunkCoordinatorBuilder withThrowableConsumer(
- @NotNull final Consumer throwableConsumer) {
- this.throwableConsumer =
- Preconditions.checkNotNull(throwableConsumer, "Throwable consumer may not be null");
- return this;
- }
-
- @NotNull public ChunkCoordinator build() {
+ @NotNull public BukkitChunkCoordinator build() {
Preconditions.checkNotNull(this.world, "No world was supplied");
Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied");
Preconditions.checkNotNull(this.whenDone, "No final action was supplied");
- Preconditions
- .checkNotNull(this.throwableConsumer, "No throwable consumer was supplied");
- return new ChunkCoordinator(this.maxIterationTime, this.initialBatchSize,
- this.chunkConsumer, this.world, this.requestedChunks, this.whenDone,
- this.throwableConsumer);
+ return new BukkitChunkCoordinator(this.maxIterationTime, this.initialBatchSize,
+ this.chunkConsumer, this.world, this.requestedChunks, this.whenDone);
}
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java
new file mode 100644
index 000000000..9dce356c5
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java
@@ -0,0 +1,52 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * PlotSquared plot management system for Minecraft
+ * Copyright (C) 2020 IntellectualSites
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.plotsquared.bukkit.queue;
+
+import com.plotsquared.bukkit.util.BukkitBlockUtil;
+import com.plotsquared.core.queue.BasicQueueCoordinator;
+import com.plotsquared.core.util.BlockUtil;
+import com.sk89q.worldedit.world.block.BlockState;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+
+public class BukkitQueueCoordinator extends BasicQueueCoordinator {
+
+ public BukkitQueueCoordinator(String world) {
+ super(world);
+ }
+
+ @Override public BlockState getBlock(int x, int y, int z) {
+ World worldObj = Bukkit.getWorld(getWorld());
+ if (worldObj != null) {
+ Block block = worldObj.getBlockAt(x, y, z);
+ return BukkitBlockUtil.get(block);
+ } else {
+ return BlockUtil.get(0, 0);
+ }
+ }
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/inject/annotations/QueuePipeline.java b/Core/src/main/java/com/plotsquared/core/inject/annotations/QueuePipeline.java
new file mode 100644
index 000000000..96ce1e242
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/inject/annotations/QueuePipeline.java
@@ -0,0 +1,39 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * PlotSquared plot management system for Minecraft
+ * Copyright (C) 2020 IntellectualSites
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.plotsquared.core.inject.annotations;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@BindingAnnotation
+public @interface QueuePipeline {
+}
diff --git a/Core/src/main/java/com/plotsquared/core/inject/factory/QueueCoordinatorFactory.java b/Core/src/main/java/com/plotsquared/core/inject/factory/QueueCoordinatorFactory.java
new file mode 100644
index 000000000..969ceed3b
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/inject/factory/QueueCoordinatorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * PlotSquared plot management system for Minecraft
+ * Copyright (C) 2020 IntellectualSites
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.plotsquared.core.inject.factory;
+
+import com.plotsquared.core.queue.QueueCoordinator;
+
+import javax.annotation.Nonnull;
+
+public interface QueueCoordinatorFactory {
+
+ @Nonnull QueueCoordinator create();
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
similarity index 85%
rename from Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateLocalBlockQueue.java
rename to Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
index 75de960f1..ac427471d 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateLocalBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
@@ -26,22 +26,23 @@
package com.plotsquared.core.queue;
import com.plotsquared.core.plot.PlotArea;
+import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import lombok.Getter;
-import javax.annotation.Nonnull;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
-public class AreaBoundDelegateLocalBlockQueue extends DelegateLocalBlockQueue {
+public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator {
@Getter private final PlotArea area;
- public AreaBoundDelegateLocalBlockQueue(@Nonnull final PlotArea area,
- @Nullable final LocalBlockQueue parent) {
+ public AreaBoundDelegateQueueCoordinator(@Nonnull final PlotArea area,
+ @Nullable final QueueCoordinator parent) {
super(parent);
this.area = Objects.requireNonNull(area);
}
@@ -74,4 +75,11 @@ public class AreaBoundDelegateLocalBlockQueue extends DelegateLocalBlockQueue {
return false;
}
+ @Override public boolean setTile(int x, int y, int z, CompoundTag tag) {
+ if (area.contains(x, z)) {
+ return super.setTile(x, y, z, tag);
+ }
+ return false;
+ }
+
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java
deleted file mode 100644
index e2bdd37e6..000000000
--- a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * _____ _ _ _____ _
- * | __ \| | | | / ____| | |
- * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
- * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
- * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
- * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
- * | |
- * |_|
- * PlotSquared plot management system for Minecraft
- * Copyright (C) 2020 IntellectualSites
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package com.plotsquared.core.queue;
-
-import com.plotsquared.core.util.MainUtil;
-import com.plotsquared.core.util.MathMan;
-import com.plotsquared.core.util.PatternUtil;
-import com.plotsquared.core.util.task.RunnableVal;
-import com.plotsquared.core.util.task.TaskManager;
-import com.sk89q.worldedit.function.pattern.Pattern;
-import com.sk89q.worldedit.world.biome.BiomeType;
-import com.sk89q.worldedit.world.block.BaseBlock;
-import com.sk89q.worldedit.world.block.BlockState;
-import javax.annotation.Nonnull;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedDeque;
-import java.util.concurrent.ExecutionException;
-
-public abstract class BasicLocalBlockQueue extends LocalBlockQueue {
-
- private final String world;
- private final ConcurrentHashMap blockChunks = new ConcurrentHashMap<>();
- private final ConcurrentLinkedDeque chunks = new ConcurrentLinkedDeque<>();
- private long modified;
- private LocalChunk lastWrappedChunk;
- private int lastX = Integer.MIN_VALUE;
- private int lastZ = Integer.MIN_VALUE;
- private boolean setbiome = false;
-
- private GlobalBlockQueue globalBlockQueue;
-
- public BasicLocalBlockQueue(String world) {
- super(world);
- this.world = world;
- this.modified = System.currentTimeMillis();
- }
-
- public abstract LocalChunk getLocalChunk(int x, int z);
-
- @Override public abstract BlockState getBlock(int x, int y, int z);
-
- public abstract void setComponents(LocalChunk lc)
- throws ExecutionException, InterruptedException;
-
- @Override public final String getWorld() {
- return world;
- }
-
- @Override public final boolean next() {
- lastX = Integer.MIN_VALUE;
- lastZ = Integer.MIN_VALUE;
- try {
- if (this.blockChunks.size() == 0) {
- return false;
- }
- synchronized (blockChunks) {
- LocalChunk chunk = chunks.poll();
- if (chunk != null) {
- blockChunks.remove(chunk.longHash());
- return this.execute(chunk);
- }
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- return false;
- }
-
- public final boolean execute(@Nonnull LocalChunk lc)
- throws ExecutionException, InterruptedException {
- this.setComponents(lc);
- return true;
- }
-
- @Override public void startSet(boolean parallel) {
- // Do nothing
- }
-
- @Override public void endSet(boolean parallel) {
- // Do nothing
- }
-
- @Override public final int size() {
- return chunks.size();
- }
-
- @Override public final long getModified() {
- return modified;
- }
-
- @Override public final void setModified(long modified) {
- this.modified = modified;
- }
-
- @Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
- return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z));
- }
-
- @Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
- if ((y > 255) || (y < 0)) {
- return false;
- }
- int cx = x >> 4;
- int cz = z >> 4;
- if (cx != lastX || cz != lastZ) {
- lastX = cx;
- lastZ = cz;
- long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
- lastWrappedChunk = this.blockChunks.get(pair);
- if (lastWrappedChunk == null) {
- lastWrappedChunk = this.getLocalChunk(x >> 4, z >> 4);
- lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
- LocalChunk previous = this.blockChunks.put(pair, lastWrappedChunk);
- if (previous == null) {
- return chunks.add(lastWrappedChunk);
- }
- this.blockChunks.put(pair, previous);
- lastWrappedChunk = previous;
- }
- }
- lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
- return true;
- }
-
- @Override public boolean setBlock(int x, int y, int z, BlockState id) {
- // Trying to mix BlockState and BaseBlock leads to all kinds of issues.
- // Since BaseBlock has more features than BlockState, simply convert
- // all BlockStates to BaseBlocks
- return setBlock(x, y, z, id.toBaseBlock());
- }
-
- @Override public final boolean setBiome(int x, int z, BiomeType biomeType) {
- long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
- LocalChunk result = this.blockChunks.get(pair);
- if (result == null) {
- result = this.getLocalChunk(x >> 4, z >> 4);
- LocalChunk previous = this.blockChunks.put(pair, result);
- if (previous != null) {
- this.blockChunks.put(pair, previous);
- result = previous;
- } else {
- chunks.add(result);
- }
- }
- result.setBiome(x & 15, z & 15, biomeType);
- setbiome = true;
- return true;
- }
-
- @Override public final boolean setBiome() {
- return setbiome;
- }
-
- public final void setChunk(LocalChunk chunk) {
- LocalChunk previous = this.blockChunks.put(chunk.longHash(), chunk);
- if (previous != null) {
- chunks.remove(previous);
- }
- chunks.add(chunk);
- }
-
- @Override public void flush() {
- this.globalBlockQueue.dequeue(this);
- TaskManager.getImplementation().sync(new RunnableVal