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 - *

- * Usage: - *

{@code
- * final ChunkCoordinator chunkCoordinator = ChunkCoordinator.builder()
- *     .inWorld(Objects.requireNonNull(Bukkit.getWorld("world"))).withChunk(BlockVector2.at(0, 0))
- *     .withConsumer(chunk -> System.out.printf("Got chunk %d;%d", chunk.getX(), chunk.getZ()))
- *     .withFinalAction(() -> System.out.println("All chunks have been loaded"))
- *     .withThrowableConsumer(throwable -> System.err.println("Something went wrong... =("))
- *     .withMaxIterationTime(25L)
- *     .build();
- * chunkCoordinator.subscribeToProgress((coordinator, progress) ->
- *     System.out.printf("Progress: %.1f", progress * 100.0f));
- * chunkCoordinator.start();
- * }
- * - * @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() { - @Override public void run(Object value) { - while (next()) { - } - } - }); - } - - - public abstract class LocalChunk { - public final BasicLocalBlockQueue parent; - public final int z; - public final int x; - - public BaseBlock[][] baseblocks; - public BiomeType[][] biomes; - - public LocalChunk(BasicLocalBlockQueue parent, int x, int z) { - this.parent = parent; - this.x = x; - this.z = z; - } - - /** - * Get the parent queue this chunk belongs to - * - * @return - */ - public BasicLocalBlockQueue getParent() { - return parent; - } - - public int getX() { - return x; - } - - public int getZ() { - return z; - } - - public abstract void setBlock(final int x, final int y, final int z, final BaseBlock block); - - public void setBiome(int x, int z, BiomeType biomeType) { - if (this.biomes == null) { - this.biomes = new BiomeType[16][]; - } - BiomeType[] index = this.biomes[x]; - if (index == null) { - index = this.biomes[x] = new BiomeType[16]; - } - index[z] = biomeType; - } - - public long longHash() { - return MathMan.pairInt(x, z); - } - - @Override public int hashCode() { - return MathMan.pair((short) x, (short) z); - } - } - - - public class BasicLocalChunk extends LocalChunk { - - public BasicLocalChunk(BasicLocalBlockQueue parent, int x, int z) { - super(parent, x, z); - baseblocks = new BaseBlock[16][]; - } - - @Override public void setBlock(int x, int y, int z, BaseBlock block) { - this.setInternal(x, y, z, block); - } - - private void setInternal(final int x, final int y, final int z, final BaseBlock baseBlock) { - final int i = MainUtil.CACHE_I[y][x][z]; - final int j = MainUtil.CACHE_J[y][x][z]; - BaseBlock[] array = baseblocks[i]; - if (array == null) { - array = (baseblocks[i] = new BaseBlock[4096]); - } - array[j] = baseBlock; - } - } -} diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java new file mode 100644 index 000000000..e22376fd3 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java @@ -0,0 +1,135 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.PatternUtil; +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 javax.annotation.Nonnull; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class BasicQueueCoordinator extends QueueCoordinator { + + private final String world; + private final ConcurrentHashMap blockChunks = new ConcurrentHashMap<>(); + 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 BasicQueueCoordinator(String world) { + this.world = world; + this.modified = System.currentTimeMillis(); + } + + public LocalChunk getLocalChunk(int x, int z) { + return new LocalChunk(this, x, z) { + // Allow implementation-specific custom stuff here + }; + } + + @Override public abstract BlockState getBlock(int x, int y, int z); + + @Override public final String getWorld() { + return world; + } + + @Override public final int size() { + return blockChunks.size(); + } + + @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; + } + LocalChunk chunk = getChunk(x >> 4, z >> 4); + chunk.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) { + LocalChunk chunk = getChunk(x >> 4, z >> 4); + chunk.setBiome(x & 15, z & 15, biomeType); + setbiome = true; + return true; + } + + @Override public final boolean setTile(int x, int y, int z, CompoundTag tag) { + LocalChunk chunk = getChunk(x >> 4, z >> 4); + chunk.setTile(x, y, z, tag); + return true; + } + + @Override public final boolean settingBiome() { + return setbiome; + } + + public final void setChunk(LocalChunk chunk) { + this.blockChunks.put(chunk.longHash(), chunk); + } + + private LocalChunk getChunk(final int chunkX, final int ChunkZ) { + if (chunkX != lastX || ChunkZ != lastZ) { + lastX = chunkX; + lastZ = ChunkZ; + long pair = (long) (chunkX) << 32 | (ChunkZ) & 0xFFFFFFFFL; + lastWrappedChunk = this.blockChunks.get(pair); + if (lastWrappedChunk == null) { + lastWrappedChunk = this.getLocalChunk(chunkX, ChunkZ); + LocalChunk previous = this.blockChunks.put(pair, lastWrappedChunk); + if (previous == null) { + return lastWrappedChunk; + } + lastWrappedChunk = previous; + } + } + return lastWrappedChunk; + } + + +} diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java similarity index 95% rename from Core/src/main/java/com/plotsquared/core/queue/ChunkBlockQueue.java rename to Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java index fcd40d26e..59daca67c 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/ChunkBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java @@ -31,26 +31,24 @@ import com.sk89q.worldedit.math.BlockVector3; 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 javax.annotation.Nullable; - import java.util.Arrays; -public class ChunkBlockQueue extends ScopedLocalBlockQueue { +public class ChunkQueueCoordinator extends ScopedQueueCoordinator { public final BiomeType[] biomeGrid; public final BlockState[][][] result; private final int width; private final int length; - @Deprecated private final int area; private final BlockVector3 bot; private final BlockVector3 top; - public ChunkBlockQueue(BlockVector3 bot, BlockVector3 top, boolean biomes) { + public ChunkQueueCoordinator(BlockVector3 bot, BlockVector3 top, boolean biomes) { super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15)); this.width = top.getX() - bot.getX() + 1; this.length = top.getZ() - bot.getZ() + 1; - this.area = width * length; this.result = new BlockState[256][][]; this.biomeGrid = biomes ? new BiomeType[width * length] : null; this.bot = bot; diff --git a/Core/src/main/java/com/plotsquared/core/queue/DelegateLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java similarity index 64% rename from Core/src/main/java/com/plotsquared/core/queue/DelegateLocalBlockQueue.java rename to Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java index 22176671c..5712d5694 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/DelegateLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java @@ -25,45 +25,32 @@ */ package com.plotsquared.core.queue; +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 lombok.Setter; -public class DelegateLocalBlockQueue extends LocalBlockQueue { +import javax.annotation.Nullable; - private final LocalBlockQueue parent; +public class DelegateQueueCoordinator extends QueueCoordinator { - public DelegateLocalBlockQueue(LocalBlockQueue parent) { - super(parent == null ? null : parent.getWorld()); + private final QueueCoordinator parent; + + public DelegateQueueCoordinator(QueueCoordinator parent) { this.parent = parent; if (parent != null) { this.setForceSync(parent.isForceSync()); - this.setChunkObject(parent.getChunkObject()); } } - public LocalBlockQueue getParent() { + public QueueCoordinator getParent() { return parent; } - @Override public boolean next() { - return parent.next(); - } - - @Override public void startSet(boolean parallel) { - if (parent != null) { - parent.startSet(parallel); - } - } - - @Override public void endSet(boolean parallel) { - if (parent != null) { - parent.endSet(parallel); - } - } - @Override public int size() { if (parent != null) { return parent.size(); @@ -71,19 +58,6 @@ public class DelegateLocalBlockQueue extends LocalBlockQueue { return 0; } - @Override public void optimize() { - if (parent != null) { - parent.optimize(); - } - } - - @Override public long getModified() { - if (parent != null) { - return parent.getModified(); - } - return 0; - } - @Override public void setModified(long modified) { if (parent != null) { parent.setModified(modified); @@ -110,36 +84,16 @@ public class DelegateLocalBlockQueue extends LocalBlockQueue { return parent.setBiome(x, z, biome); } - @Override public boolean setBiome() { - return parent.setBiome(); + @Override public boolean settingBiome() { + return parent.settingBiome(); } @Override public String getWorld() { return parent.getWorld(); } - @Override public void flush() { - if (parent != null) { - parent.flush(); - } - } - - @Override public void refreshChunk(int x, int z) { - if (parent != null) { - parent.refreshChunk(x, z); - } - } - - @Override public void fixChunkLighting(int x, int z) { - if (parent != null) { - parent.fixChunkLighting(x, z); - } - } - - @Override public void regenChunk(int x, int z) { - if (parent != null) { - parent.regenChunk(x, z); - } + @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { + return parent.setTile(x, y, z, tag); } @Override public boolean enqueue() { diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 9f79102b0..a450ef045 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -25,169 +25,21 @@ */ package com.plotsquared.core.queue; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.util.task.RunnableVal2; -import com.plotsquared.core.util.task.TaskManager; +import lombok.Getter; +import lombok.Setter; import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.atomic.AtomicBoolean; public class GlobalBlockQueue { - private final int PARALLEL_THREADS; - private final ConcurrentLinkedDeque activeQueues; - private final ConcurrentLinkedDeque inactiveQueues; - private final ConcurrentLinkedDeque runnables; - private final AtomicBoolean running; - private final int targetTime; - private QueueProvider provider; - /** - * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the - * server - */ - private long last; - private long secondLast; - private long lastSuccess; - private double lastPeriod = 0; - private final RunnableVal2 SET_TASK = - new RunnableVal2() { - @Override public void run(Long free, LocalBlockQueue queue) { - do { - boolean more = queue.next(); - if (!more) { - lastSuccess = last; - if (inactiveQueues.size() == 0 && activeQueues.size() == 0) { - runEmptyTasks(); - } - return; - } - } while ((lastPeriod = - ((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last)) < free); - } - }; + private final ConcurrentLinkedDeque activeQueues; + @Getter @Setter private QueueProvider provider; - public GlobalBlockQueue(QueueProvider provider, int threads, int targetTime) { + public GlobalBlockQueue(QueueProvider provider) { this.provider = provider; this.activeQueues = new ConcurrentLinkedDeque<>(); - this.inactiveQueues = new ConcurrentLinkedDeque<>(); - this.runnables = new ConcurrentLinkedDeque<>(); - this.running = new AtomicBoolean(); - this.targetTime = targetTime; - this.PARALLEL_THREADS = threads; - } - - public QueueProvider getProvider() { - return provider; - } - - public void setProvider(QueueProvider provider) { - this.provider = provider; - } - - public LocalBlockQueue getNewQueue(String world, boolean autoQueue) { - LocalBlockQueue queue = provider.getNewQueue(world); - // Auto-inject into the queue - PlotSquared.platform().getInjector().injectMembers(queue); - if (autoQueue) { - inactiveQueues.add(queue); - } - return queue; - } - - public boolean stop() { - if (!running.get()) { - return false; - } - running.set(false); - return true; - } - - public boolean runTask() { - if (running.get()) { - return false; - } - running.set(true); - TaskManager.runTaskRepeat(new Runnable() { - @Override public void run() { - if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { - lastSuccess = System.currentTimeMillis(); - lastPeriod = 0; - GlobalBlockQueue.this.runEmptyTasks(); - return; - } - // Server laggy? Skip. - if (lastPeriod > targetTime) { - lastPeriod -= targetTime; - return; - } - SET_TASK.value1 = 50 + Math.min( - (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = - System.currentTimeMillis()), - GlobalBlockQueue.this.secondLast - System.currentTimeMillis()); - SET_TASK.value2 = GlobalBlockQueue.this.getNextQueue(); - if (SET_TASK.value2 == null) { - return; - } - if (!PlotSquared.get().isMainThread(Thread.currentThread())) { - throw new IllegalStateException( - "This shouldn't be possible for placement to occur off the main thread"); - } - // Disable the async catcher as it can't discern async vs parallel - SET_TASK.value2.startSet(true); - try { - if (PARALLEL_THREADS <= 1) { - SET_TASK.run(); - } else { - ArrayList threads = new ArrayList<>(); - for (int i = 0; i < PARALLEL_THREADS; i++) { - threads.add(new Thread(SET_TASK)); - } - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } catch (Throwable e) { - e.printStackTrace(); - } finally { - // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(true); - } - } - }, 1); - return true; - } - - public QueueStage getStage(LocalBlockQueue queue) { - if (activeQueues.contains(queue)) { - return QueueStage.ACTIVE; - } else if (inactiveQueues.contains(queue)) { - return QueueStage.INACTIVE; - } - return QueueStage.NONE; - } - - public boolean isStage(LocalBlockQueue queue, QueueStage stage) { - switch (stage) { - case ACTIVE: - return activeQueues.contains(queue); - case INACTIVE: - return inactiveQueues.contains(queue); - case NONE: - return !activeQueues.contains(queue) && !inactiveQueues.contains(queue); - } - return false; } /** @@ -196,155 +48,23 @@ public class GlobalBlockQueue { * @param queue todo * @return true if added to queue, false otherwise */ - public boolean enqueue(LocalBlockQueue queue) { + public boolean enqueue(QueueCoordinator queue) { boolean success = false; - success = inactiveQueues.remove(queue); if (queue.size() > 0 && !activeQueues.contains(queue)) { - queue.optimize(); success = activeQueues.add(queue); } return success; } - public void dequeue(LocalBlockQueue queue) { - inactiveQueues.remove(queue); + public void dequeue(QueueCoordinator queue) { activeQueues.remove(queue); } - public List getAllQueues() { - ArrayList list = - new ArrayList<>(activeQueues.size() + inactiveQueues.size()); - list.addAll(inactiveQueues); - list.addAll(activeQueues); - return list; - } - - public List getActiveQueues() { + public List getActiveQueues() { return new ArrayList<>(activeQueues); } - public List getInactiveQueues() { - return new ArrayList<>(inactiveQueues); - } - - public void flush(LocalBlockQueue queue) { - SET_TASK.value1 = Long.MAX_VALUE; - SET_TASK.value2 = queue; - if (SET_TASK.value2 == null) { - return; - } - if (PlotSquared.get().isMainThread(Thread.currentThread())) { - throw new IllegalStateException("Must be flushed on the main thread!"); - } - // Disable the async catcher as it can't discern async vs parallel - SET_TASK.value2.startSet(true); - try { - if (PARALLEL_THREADS <= 1) { - SET_TASK.run(); - } else { - ArrayList threads = new ArrayList<>(); - for (int i = 0; i < PARALLEL_THREADS; i++) { - Thread thread = new Thread(SET_TASK); - thread.setName("PlotSquared Flush Task"); - threads.add(thread); - } - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } catch (Throwable e) { - e.printStackTrace(); - } finally { - // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(true); - dequeue(queue); - } - } - - public LocalBlockQueue getNextQueue() { - long now = System.currentTimeMillis(); - while (!activeQueues.isEmpty()) { - LocalBlockQueue queue = activeQueues.peek(); - if (queue != null && queue.size() > 0) { - queue.setModified(now); - return queue; - } else { - activeQueues.poll(); - } - } - int size = inactiveQueues.size(); - if (size > 0) { - Iterator iter = inactiveQueues.iterator(); - try { - int total = 0; - LocalBlockQueue firstNonEmpty = null; - while (iter.hasNext()) { - LocalBlockQueue queue = iter.next(); - long age = now - queue.getModified(); - total += queue.size(); - if (queue.size() == 0) { - if (age > 60000) { - iter.remove(); - } - continue; - } - if (firstNonEmpty == null) { - firstNonEmpty = queue; - } - if (total > 64) { - firstNonEmpty.setModified(now); - return firstNonEmpty; - } - if (age > 1000) { - queue.setModified(now); - return queue; - } - } - } catch (ConcurrentModificationException e) { - e.printStackTrace(); - } - } - return null; - } - public boolean isDone() { - return activeQueues.size() == 0 && inactiveQueues.size() == 0; - } - - public boolean addEmptyTask(final Runnable whenDone) { - if (this.isDone()) { - // Run - this.runEmptyTasks(); - if (whenDone != null) { - whenDone.run(); - } - return true; - } - if (whenDone != null) { - this.runnables.add(whenDone); - } - return false; - } - - private synchronized void runEmptyTasks() { - if (this.runnables.isEmpty()) { - return; - } - final ConcurrentLinkedDeque tmp = new ConcurrentLinkedDeque<>(this.runnables); - this.runnables.clear(); - for (final Runnable runnable : tmp) { - runnable.run(); - } - } - - public enum QueueStage { - INACTIVE, ACTIVE, NONE + return activeQueues.size() == 0; } } diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java b/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java new file mode 100644 index 000000000..99975cae6 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java @@ -0,0 +1,80 @@ +package com.plotsquared.core.queue; + +import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; + +import java.util.HashMap; + +public class LocalChunk { + public final BasicQueueCoordinator parent; + public final int z; + public final int x; + + public BaseBlock[][] baseblocks; + public BiomeType[][] biomes; + public HashMap tiles = null; + + public LocalChunk(BasicQueueCoordinator parent, int x, int z) { + this.parent = parent; + this.x = x; + this.z = z; + baseblocks = new BaseBlock[16][]; + } + + /** + * Get the parent queue this chunk belongs to + * + * @return + */ + public BasicQueueCoordinator getParent() { + return parent; + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } + + public void setBiome(int x, int z, BiomeType biomeType) { + if (this.biomes == null) { + this.biomes = new BiomeType[16][]; + } + BiomeType[] index = this.biomes[x]; + if (index == null) { + index = this.biomes[x] = new BiomeType[16]; + } + index[z] = biomeType; + } + + public long longHash() { + return MathMan.pairInt(x, z); + } + + @Override public int hashCode() { + return MathMan.pair((short) x, (short) z); + } + + public void setBlock(final int x, final int y, final int z, final BaseBlock baseBlock) { + final int i = MainUtil.CACHE_I[y][x][z]; + final int j = MainUtil.CACHE_J[y][x][z]; + BaseBlock[] array = baseblocks[i]; + if (array == null) { + array = (baseblocks[i] = new BaseBlock[4096]); + } + array[j] = baseBlock; + } + + public void setTile(final int x, final int y, final int z, final CompoundTag tag) { + if (tiles == null) { + tiles = new HashMap<>(); + } + tiles.put(BlockVector3.at(x, y, z), tag); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateQueueCoordinator.java similarity index 83% rename from Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateLocalBlockQueue.java rename to Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateQueueCoordinator.java index eefae99d3..3b067e8ca 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateQueueCoordinator.java @@ -25,6 +25,7 @@ */ package com.plotsquared.core.queue; +import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -35,16 +36,17 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -public class LocationOffsetDelegateLocalBlockQueue extends DelegateLocalBlockQueue { +public class LocationOffsetDelegateQueueCoordinator extends DelegateQueueCoordinator { - private static final Logger logger = LoggerFactory.getLogger("P2/" + LocationOffsetDelegateLocalBlockQueue.class.getSimpleName()); + private static final Logger logger = LoggerFactory + .getLogger("P2/" + LocationOffsetDelegateQueueCoordinator.class.getSimpleName()); private final boolean[][] canPlace; private final int blockX; private final int blockZ; - public LocationOffsetDelegateLocalBlockQueue(final boolean[][] canPlace, final int blockX, - final int blockZ, @Nullable LocalBlockQueue parent) { + public LocationOffsetDelegateQueueCoordinator(final boolean[][] canPlace, final int blockX, + final int blockZ, @Nullable QueueCoordinator parent) { super(parent); this.canPlace = canPlace; this.blockX = blockX; @@ -78,4 +80,7 @@ public class LocationOffsetDelegateLocalBlockQueue extends DelegateLocalBlockQue return super.setBiome(x, y, biome); } + @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { + return super.setTile(x, y, z, tag); + } } diff --git a/Core/src/main/java/com/plotsquared/core/queue/OffsetLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/OffsetQueueCoordinator.java similarity index 77% rename from Core/src/main/java/com/plotsquared/core/queue/OffsetLocalBlockQueue.java rename to Core/src/main/java/com/plotsquared/core/queue/OffsetQueueCoordinator.java index 06233277d..78b945c7b 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/OffsetLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/OffsetQueueCoordinator.java @@ -25,15 +25,17 @@ */ package com.plotsquared.core.queue; +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; -public class OffsetLocalBlockQueue extends DelegateLocalBlockQueue { +public class OffsetQueueCoordinator extends DelegateQueueCoordinator { private final int ox; private final int oy; private final int oz; - public OffsetLocalBlockQueue(LocalBlockQueue parent, int ox, int oy, int oz) { + public OffsetQueueCoordinator(QueueCoordinator parent, int ox, int oy, int oz) { super(parent); this.ox = ox; this.oy = oy; @@ -47,4 +49,12 @@ public class OffsetLocalBlockQueue extends DelegateLocalBlockQueue { @Override public boolean setBlock(int x, int y, int z, BaseBlock id) { return super.setBlock(ox + x, oy + y, oz + z, id); } + + @Override public boolean setBlock(int x, int y, int z, Pattern pattern) { + return super.setBlock(ox + x, oy + y, oz + z, pattern); + } + + @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { + return super.setTile(ox + x, oy + y, oz + z, tag); + } } diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java similarity index 68% rename from Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java rename to Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java index 1f2ccb995..df537d909 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java @@ -28,59 +28,31 @@ package com.plotsquared.core.queue; import com.google.inject.Inject; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.location.Location; -import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.PatternUtil; -import com.plotsquared.core.util.SchematicHandler; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.WorldUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.math.BlockVector2; 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 lombok.Setter; + import javax.annotation.Nonnull; import javax.annotation.Nullable; -public abstract class LocalBlockQueue { +public abstract class QueueCoordinator { @Getter @Setter private boolean forceSync = false; @Getter @Setter @Nullable private Object chunkObject; - @Inject private SchematicHandler schematicHandler; - @Inject private WorldUtil worldUtil; @Inject private GlobalBlockQueue blockQueue; - /** - * Needed for compatibility with FAWE. - * - * @param world unused - */ - @Deprecated public LocalBlockQueue(String world) { + public QueueCoordinator() { PlotSquared.platform().getInjector().injectMembers(this); } - public ScopedLocalBlockQueue getForChunk(int x, int z) { - int bx = x << 4; - int bz = z << 4; - return new ScopedLocalBlockQueue(this, Location.at(getWorld(), bx, 0, bz), - Location.at(getWorld(), bx + 15, 255, bz + 255)); - } - - public abstract boolean next(); - - public abstract void startSet(boolean parallel); - - public abstract void endSet(boolean parallel); - public abstract int size(); - public abstract void optimize(); - - public abstract long getModified(); - public abstract void setModified(long modified); /** @@ -99,48 +71,22 @@ public abstract class LocalBlockQueue { return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z)); } - public boolean setTile(int x, int y, int z, CompoundTag tag) { - this.schematicHandler.restoreTile(this, tag, x, y, z); - return true; - } + public abstract boolean setTile(int x, int y, int z, CompoundTag tag); public abstract BlockState getBlock(int x, int y, int z); public abstract boolean setBiome(int x, int z, BiomeType biome); - public abstract boolean setBiome(); + public abstract boolean settingBiome(); public abstract String getWorld(); - public abstract void flush(); - public final void setModified() { setModified(System.currentTimeMillis()); } - public abstract void refreshChunk(int x, int z); - - public abstract void fixChunkLighting(int x, int z); - - public abstract void regenChunk(int x, int z); - - public final void regenChunkSafe(int x, int z) { - regenChunk(x, z); - fixChunkLighting(x, z); - BlockVector2 loc = BlockVector2.at(x, z); - - for (final PlotPlayer pp : PlotSquared.platform().getPlayerManager().getPlayers()) { - Location pLoc = pp.getLocation(); - if (!StringMan.isEqual(getWorld(), pLoc.getWorldName()) || !pLoc.getChunkLocation() - .equals(loc)) { - continue; - } - pp.teleport(pLoc.withY(this.worldUtil.getHighestBlockSynchronous(getWorld(), pLoc.getX(), pLoc.getZ()))); - } - } - public boolean enqueue() { - return blockQueue.enqueue(this); + return this.blockQueue.enqueue(this); } public void setCuboid(Location pos1, Location pos2, BlockState block) { diff --git a/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java b/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java index 2fee2fa99..207b29ee0 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java +++ b/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java @@ -26,23 +26,23 @@ package com.plotsquared.core.queue; public abstract class QueueProvider { - public static QueueProvider of(final Class primary, - final Class fallback) { + public static QueueProvider of(final Class primary, + final Class fallback) { return new QueueProvider() { private boolean failed = false; - @Override public LocalBlockQueue getNewQueue(String world) { + @Override public QueueCoordinator getNewQueue(String world) { if (!failed) { try { - return (LocalBlockQueue) primary.getConstructors()[0].newInstance(world); + return (QueueCoordinator) primary.getConstructors()[0].newInstance(world); } catch (Throwable e) { e.printStackTrace(); failed = true; } } try { - return (LocalBlockQueue) fallback.getConstructors()[0].newInstance(world); + return (QueueCoordinator) fallback.getConstructors()[0].newInstance(world); } catch (Throwable e) { e.printStackTrace(); } @@ -51,5 +51,5 @@ public abstract class QueueProvider { }; } - public abstract LocalBlockQueue getNewQueue(String world); + public abstract QueueCoordinator getNewQueue(String world); } diff --git a/Core/src/main/java/com/plotsquared/core/queue/ScopedLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/ScopedQueueCoordinator.java similarity index 89% rename from Core/src/main/java/com/plotsquared/core/queue/ScopedLocalBlockQueue.java rename to Core/src/main/java/com/plotsquared/core/queue/ScopedQueueCoordinator.java index fc43e1ce0..49631dceb 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/ScopedLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/ScopedQueueCoordinator.java @@ -26,12 +26,13 @@ package com.plotsquared.core.queue; import com.plotsquared.core.location.Location; +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; -public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue { +public class ScopedQueueCoordinator extends DelegateQueueCoordinator { private final int minX; private final int minY; private final int minZ; @@ -44,7 +45,7 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue { private final int dy; private final int dz; - public ScopedLocalBlockQueue(LocalBlockQueue parent, Location min, Location max) { + public ScopedQueueCoordinator(QueueCoordinator parent, Location min, Location max) { super(parent); this.minX = min.getX(); this.minY = min.getY(); @@ -86,6 +87,11 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue { .setBlock(x + minX, y + minY, z + minZ, pattern); } + @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { + return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super + .setTile(x + minX, y + minY, z + minZ, tag); + } + public Location getMin() { return Location.at(this.getWorld(), this.minX, this.minY, this.minZ); }