From 57af50ed4930c9ea08607f3775c14df27f072010 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 18 Jul 2020 12:07:56 +0100 Subject: [PATCH] Continue implementation of new queue system - Move ChunkCoordinatorBuild to Core - Add core ChunkCoordinator - Add Factories for ChunkCoordinator and its Builder - Reimplement refreshChunk but in WorldUtil - Allow custom Consumers to be used by the Queue when sent to the ChunkCoordinator - Start switching ChunkTasks to use the new ChunkCoordinator system - Replace GlobalBlockQueue's "empty task" system with normal sync TaskManager - Remove lombok from the queue system - Add back forceSync and chunkObject from LocalBlockQueue --- .../bukkit/inject/BukkitModule.java | 13 +- .../bukkit/queue/BukkitChunkCoordinator.java | 163 ++------- .../bukkit/queue/BukkitQueueCoordinator.java | 56 ++- .../plotsquared/bukkit/queue/GenChunk.java | 12 +- .../bukkit/util/BukkitRegionManager.java | 330 +++++++++--------- .../plotsquared/bukkit/util/BukkitUtil.java | 120 ++++--- .../com/plotsquared/core/command/Clear.java | 4 +- .../plotsquared/core/command/Template.java | 5 +- .../core/generator/ClassicPlotManager.java | 5 +- .../core/generator/HybridUtils.java | 2 +- ...va => ChunkCoordinatorBuilderFactory.java} | 10 +- .../factory/ChunkCoordinatorFactory.java | 48 +++ .../java/com/plotsquared/core/plot/Plot.java | 20 +- .../AreaBoundDelegateQueueCoordinator.java | 7 +- .../core/queue/BasicQueueCoordinator.java | 33 +- .../core/queue/ChunkCoordinator.java | 22 ++ .../core/queue/ChunkCoordinatorBuilder.java | 113 ++++++ .../core/queue/DelegateQueueCoordinator.java | 7 + .../core/queue/GlobalBlockQueue.java | 12 +- .../plotsquared/core/queue/LocalChunk.java | 37 +- .../core/queue/QueueCoordinator.java | 27 +- .../plotsquared/core/util/RegionManager.java | 18 +- .../com/plotsquared/core/util/WorldUtil.java | 2 + 23 files changed, 625 insertions(+), 441 deletions(-) rename Core/src/main/java/com/plotsquared/core/inject/factory/{QueueCoordinatorFactory.java => ChunkCoordinatorBuilderFactory.java} (79%) create mode 100644 Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java create mode 100644 Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java create mode 100644 Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java index 8f644dc25..3361add35 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java @@ -26,12 +26,11 @@ package com.plotsquared.bukkit.inject; import com.google.inject.AbstractModule; -import com.google.inject.Provides; -import com.google.inject.Singleton; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.util.Providers; import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.player.BukkitPlayerManager; +import com.plotsquared.bukkit.queue.BukkitChunkCoordinator; import com.plotsquared.bukkit.queue.BukkitQueueCoordinator; import com.plotsquared.bukkit.schematic.BukkitSchematicHandler; import com.plotsquared.bukkit.util.BukkitChunkManager; @@ -41,18 +40,20 @@ import com.plotsquared.bukkit.util.BukkitPermHandler; import com.plotsquared.bukkit.util.BukkitRegionManager; import com.plotsquared.bukkit.util.BukkitSetupUtils; import com.plotsquared.bukkit.util.BukkitUtil; -import com.plotsquared.bukkit.util.task.PaperTimeConverter; -import com.plotsquared.bukkit.util.task.SpigotTimeConverter; import com.plotsquared.core.PlotPlatform; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.generator.HybridGen; import com.plotsquared.core.generator.IndependentPlotGenerator; import com.plotsquared.core.inject.annotations.ConsoleActor; import com.plotsquared.core.inject.annotations.DefaultGenerator; +import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; +import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; import com.plotsquared.core.plot.world.DefaultPlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager; +import com.plotsquared.core.queue.ChunkCoordinator; +import com.plotsquared.core.queue.ChunkCoordinatorBuilder; import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.QueueProvider; import com.plotsquared.core.util.ChunkManager; @@ -105,6 +106,10 @@ public class BukkitModule extends AbstractModule { bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class); } install(new FactoryModuleBuilder().build(HybridPlotWorldFactory.class)); + install(new FactoryModuleBuilder() + .implement(ChunkCoordinator.class, BukkitChunkCoordinator.class) + .build(ChunkCoordinatorFactory.class)); + install(new FactoryModuleBuilder().build(ChunkCoordinatorBuilderFactory.class)); } private void setupVault() { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java index 5cc5de1b1..04f6083b4 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java @@ -25,17 +25,19 @@ */ package com.plotsquared.bukkit.queue; -import com.google.common.base.Preconditions; import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.core.queue.ChunkCoordinator; +import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.world.World; import io.papermc.lib.PaperLib; +import org.bukkit.Bukkit; import org.bukkit.Chunk; -import org.bukkit.World; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnull; import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -44,32 +46,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 BukkitChunkCoordinator extends BukkitRunnable { +public final class BukkitChunkCoordinator extends ChunkCoordinator { private final List progressSubscribers = new LinkedList<>(); @@ -77,52 +54,44 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { private final Queue availableChunks; private final long maxIterationTime; private final Plugin plugin; - private final Consumer chunkConsumer; - private final World world; + private final Consumer chunkConsumer; + private final org.bukkit.World bukkitWorld; private final Runnable whenDone; private final Consumer throwableConsumer; private final int totalSize; - private AtomicInteger expectedSize; + private final AtomicInteger expectedSize; private int batchSize; 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) { + @Nonnull final Consumer chunkConsumer, @Nonnull final World world, + @Nonnull final Collection requestedChunks, @Nonnull final Runnable whenDone, + @Nonnull final Consumer throwableConsumer) { this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks); this.availableChunks = new LinkedBlockingQueue<>(); this.totalSize = requestedChunks.size(); this.expectedSize = new AtomicInteger(this.totalSize); - this.world = world; this.batchSize = initialBatchSize; this.chunkConsumer = chunkConsumer; this.maxIterationTime = maxIterationTime; this.whenDone = whenDone; this.throwableConsumer = throwableConsumer; this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class); - } - - /** - * Create a new {@link BukkitChunkCoordinator} instance - * - * @return Coordinator builder instance - */ - @NotNull public static ChunkCoordinatorBuilder builder() { - return new ChunkCoordinatorBuilder(); + this.bukkitWorld = Bukkit.getWorld(world.getName()); } /** * Start the coordinator instance */ - public void start() { + @Override public void start() { // Request initial batch this.requestBatch(); // Wait until next tick to give the chunks a chance to be loaded - this.runTaskTimer(this.plugin, 1L, 1L); + TaskManager.runTaskLater(() -> TaskManager.runTaskRepeat(this, TaskTime.ticks(1)), + TaskTime.ticks(1)); } - @Override public void run() { + @Override public void runTask() { Chunk chunk = this.availableChunks.poll(); if (chunk == null) { return; @@ -132,7 +101,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { do { final long start = System.currentTimeMillis(); try { - this.chunkConsumer.accept(chunk); + this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ())); } catch (final Throwable throwable) { this.throwableConsumer.accept(throwable); } @@ -173,7 +142,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { BlockVector2 chunk; for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) { // This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent - PaperLib.getChunkAtAsync(this.world, chunk.getX(), chunk.getZ(), true, true) + PaperLib.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true) .whenComplete((chunkObject, throwable) -> { if (throwable != null) { throwable.printStackTrace(); @@ -186,7 +155,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { } } - private void processChunk(@NotNull final Chunk chunk) { + private void processChunk(@Nonnull final Chunk chunk) { if (!chunk.isLoaded()) { throw new IllegalArgumentException( String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ())); @@ -195,7 +164,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { this.availableChunks.add(chunk); } - private void freeChunk(@NotNull final Chunk chunk) { + private void freeChunk(@Nonnull final Chunk chunk) { if (!chunk.isLoaded()) { throw new IllegalArgumentException( String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ())); @@ -208,7 +177,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { * * @return Snapshot view of remaining chunk count */ - public int getRemainingChunks() { + @Override public int getRemainingChunks() { return this.expectedSize.get(); } @@ -217,7 +186,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { * * @return Requested chunk count */ - public int getTotalChunks() { + @Override public int getTotalChunks() { return this.totalSize; } @@ -227,11 +196,10 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { * @param subscriber Subscriber */ public void subscribeToProgress( - @NotNull final BukkitChunkCoordinator.ProgressSubscriber subscriber) { + @Nonnull final BukkitChunkCoordinator.ProgressSubscriber subscriber) { this.progressSubscribers.add(subscriber); } - @FunctionalInterface public interface ProgressSubscriber { @@ -241,88 +209,9 @@ public final class BukkitChunkCoordinator extends BukkitRunnable { * @param coordinator Coordinator instance that triggered the notification * @param progress Progress in the range [0, 1] */ - void notifyProgress(@NotNull final BukkitChunkCoordinator coordinator, + void notifyProgress(@Nonnull final BukkitChunkCoordinator 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 = () -> { - }; - private long maxIterationTime = 60; // A little over 1 tick; - private int initialBatchSize = 4; - - private ChunkCoordinatorBuilder() { - } - - @NotNull public ChunkCoordinatorBuilder inWorld(@NotNull final World world) { - this.world = Preconditions.checkNotNull(world, "World may not be null"); - return this; - } - - @NotNull - public ChunkCoordinatorBuilder withChunk(@NotNull final BlockVector2 chunkLocation) { - this.requestedChunks - .add(Preconditions.checkNotNull(chunkLocation, "Chunk location may not be null")); - return this; - } - - @NotNull public ChunkCoordinatorBuilder withChunks( - @NotNull final Collection chunkLocations) { - chunkLocations.forEach(this::withChunk); - return this; - } - - @NotNull - public ChunkCoordinatorBuilder withConsumer(@NotNull final Consumer chunkConsumer) { - this.chunkConsumer = - Preconditions.checkNotNull(chunkConsumer, "Chunk consumer may not be null"); - return this; - } - - @NotNull public ChunkCoordinatorBuilder withFinalAction(@NotNull final Runnable whenDone) { - this.whenDone = Preconditions.checkNotNull(whenDone, "Final action may not be null"); - return this; - } - - @NotNull public ChunkCoordinatorBuilder withMaxIterationTime(final long maxIterationTime) { - Preconditions - .checkArgument(maxIterationTime > 0, "Max iteration time must be positive"); - this.maxIterationTime = maxIterationTime; - return this; - } - - @NotNull public ChunkCoordinatorBuilder withInitialBatchSize(final int initialBatchSize) { - Preconditions - .checkArgument(initialBatchSize > 0, "Initial batch size must be positive"); - this.initialBatchSize = initialBatchSize; - 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 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 BukkitChunkCoordinator(this.maxIterationTime, this.initialBatchSize, - this.chunkConsumer, this.world, this.requestedChunks, this.whenDone, - this.throwableConsumer); - } - - } - } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java index 64fa07c0a..075359e26 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java @@ -25,8 +25,11 @@ */ package com.plotsquared.bukkit.queue; +import com.google.inject.Inject; import com.plotsquared.bukkit.schematic.StateWrapper; import com.plotsquared.bukkit.util.BukkitBlockUtil; +import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; +import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.queue.BasicQueueCoordinator; import com.plotsquared.core.queue.LocalChunk; import com.plotsquared.core.util.BlockUtil; @@ -42,20 +45,25 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Container; import org.bukkit.block.data.BlockData; import javax.annotation.Nonnull; +import java.util.function.Consumer; public class BukkitQueueCoordinator extends BasicQueueCoordinator { private final World world; private final SideEffectSet sideEffectSet; + @Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory; + @Inject private ChunkCoordinatorFactory chunkCoordinatorFactory; private Runnable whenDone; - public BukkitQueueCoordinator(World world) { + @Inject public BukkitQueueCoordinator(World world) { super(world); this.world = world; sideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF) @@ -73,19 +81,18 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { } @Override public boolean enqueue() { - BukkitChunkCoordinator.builder().inWorld(BukkitAdapter.adapt(world)) - .withChunks(getBlockChunks().keySet()).withInitialBatchSize(3).withMaxIterationTime(40) - .withThrowableConsumer(Throwable::printStackTrace).withFinalAction(whenDone) - .withConsumer(chunk -> { - LocalChunk localChunk = - getBlockChunks().get(BlockVector2.at(chunk.getX(), chunk.getZ())); + Consumer consumer = getChunkConsumer(); + if (consumer == null) { + consumer = blockVector2 -> { + LocalChunk localChunk = getBlockChunks().get(blockVector2); if (localChunk == null) { throw new NullPointerException( "LocalChunk cannot be null when accessed from ChunkCoordinator"); } - World worldObj = getWorld(); - int sx = chunk.getX() << 4; - int sz = chunk.getX() << 4; + org.bukkit.World bukkitWorld = null; + Chunk chunk = null; + int sx = blockVector2.getX() << 4; + int sz = blockVector2.getZ() << 4; for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) { BaseBlock[] blocksLayer = localChunk.getBaseblocks()[layer]; if (blocksLayer == null) { @@ -100,11 +107,19 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { int y = MainUtil.y_loc[layer][j]; int z = sz + MainUtil.z_loc[layer][j]; try { - worldObj.setBlock(BlockVector3.at(x, y, z), block, sideEffectSet); + 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()); @@ -123,7 +138,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { CompoundTag tag = block.getNbtData(); StateWrapper sw = new StateWrapper(tag); - sw.restoreTag(worldObj.getName(), existing.getX(), existing.getY(), + sw.restoreTag(world.getName(), existing.getX(), existing.getY(), existing.getZ()); } } @@ -142,22 +157,27 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { int x = sx + MainUtil.x_loc[layer][j]; int y = MainUtil.y_loc[layer][j]; int z = sz + MainUtil.z_loc[layer][j]; - worldObj.setBiome(BlockVector3.at(x, y, z), biome); + world.setBiome(BlockVector3.at(x, y, z), biome); } } if (localChunk.getTiles().size() > 0) { localChunk.getTiles().forEach(((blockVector3, tag) -> { try { - BaseBlock block = worldObj.getBlock(blockVector3).toBaseBlock(tag); - worldObj.setBlock(blockVector3, block, sideEffectSet); + BaseBlock block = world.getBlock(blockVector3).toBaseBlock(tag); + world.setBlock(blockVector3, block, sideEffectSet); } catch (WorldEditException ignored) { StateWrapper sw = new StateWrapper(tag); - sw.restoreTag(worldObj.getName(), blockVector3.getX(), - blockVector3.getY(), blockVector3.getZ()); + sw.restoreTag(world.getName(), blockVector3.getX(), blockVector3.getY(), + blockVector3.getZ()); } })); } - }); + }; + } + chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world) + .withChunks(getBlockChunks().keySet()).withInitialBatchSize(3).withMaxIterationTime(40) + .withThrowableConsumer(Throwable::printStackTrace).withFinalAction(whenDone) + .withConsumer(consumer); return super.enqueue(); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java index 6a67c83e1..e79545493 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java @@ -39,8 +39,6 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; -import lombok.Getter; -import lombok.Setter; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; @@ -60,13 +58,21 @@ public class GenChunk extends ScopedQueueCoordinator { public String world; public int chunkX; public int chunkZ; - @Getter @Setter private ChunkData chunkData = null; + private ChunkData chunkData = null; public GenChunk() { super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15)); this.biomes = Biome.values(); } + public ChunkData getChunkData() { + return this.chunkData; + } + + public void setChunkData(ChunkData chunkData) { + this.chunkData = chunkData; + } + public Chunk getChunk() { if (chunk == null) { World worldObj = BukkitUtil.getWorld(world); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java index c078fe174..2b3f72764 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java @@ -30,6 +30,8 @@ import com.google.inject.Singleton; import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.generator.AugmentedUtils; +import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; +import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.location.Location; import com.plotsquared.core.location.PlotLoc; import com.plotsquared.core.plot.Plot; @@ -86,16 +88,17 @@ public class BukkitRegionManager extends RegionManager { private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName()); private final WorldUtil worldUtil; + private final ChunkCoordinatorFactory chunkCoordinatorFactory; + private final ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory; @Inject public BukkitRegionManager(@Nonnull final ChunkManager chunkManager, - @Nonnull final WorldUtil worldUtil) { - super(chunkManager, worldUtil); + @Nonnull final WorldUtil worldUtil, + @Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory, + @Nonnull ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory) { + super(chunkManager, worldUtil, chunkCoordinatorBuilderFactory); this.worldUtil = worldUtil; - } - - public static boolean isIn(CuboidRegion region, int x, int z) { - return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX() - && z >= region.getMinimumPoint().getZ() && z <= region.getMaximumPoint().getZ(); + this.chunkCoordinatorFactory = chunkCoordinatorFactory; + this.chunkCoordinatorBuilderFactory = chunkCoordinatorBuilderFactory; } @Override public Set getChunkChunks(String world) { @@ -207,37 +210,33 @@ public class BukkitRegionManager extends RegionManager { return count; } - @Override public boolean copyRegion(Location pos1, Location pos2, Location newPos, + @Override @Inject + public boolean copyRegion(final Location pos1, final Location pos2, final Location newPos, final Runnable whenDone) { final int relX = newPos.getX() - pos1.getX(); final int relZ = newPos.getZ() - pos1.getZ(); - - final CuboidRegion region = - RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); - final BukkitWorld oldWorld = new BukkitWorld((World) pos1.getWorld()); + final com.sk89q.worldedit.world.World oldWorld = worldUtil.getWeWorld(pos1.getWorldName()); final BukkitWorld newWorld = new BukkitWorld((World) newPos.getWorld()); + assert oldWorld.equals(newWorld); final ContentMap map = new ContentMap(); final QueueCoordinator queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(newWorld, false); - ChunkManager.chunkTask(pos1, pos2, new RunnableVal() { - @Override public void run(int[] value) { - int bx = value[2]; - int bz = value[3]; - int tx = value[4]; - int tz = value[5]; - BlockVector2 loc = BlockVector2.at(value[0], value[1]); - int cxx = loc.getX() << 4; - int czz = loc.getZ() << 4; - PaperLib.getChunkAtAsync(oldWorld, loc.getX(), loc.getZ()) - .thenAccept(chunk1 -> map.saveEntitiesIn(chunk1, region)).thenRun(() -> { - for (int x = bx & 15; x <= (tx & 15); x++) { - for (int z = bz & 15; z <= (tz & 15); z++) { - map.saveBlocks(oldWorld, 256, cxx + x, czz + z, relX, relZ); - } + chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(newWorld) + .withRegion(pos1, pos2).withThrowableConsumer(Throwable::printStackTrace) + .withRegion(pos1, pos2).withInitialBatchSize(4).withMaxIterationTime(45) + .withConsumer(chunk -> { + int cbx = chunk.getX(); + int cbz = chunk.getZ(); + int bx = Math.max(pos1.getX() & 15, 0); + int bz = Math.max(pos1.getZ() & 15, 0); + int tx = Math.min(pos2.getX() & 15, 15); + int tz = Math.min(pos2.getZ() & 15, 15); + for (int x = bx; x <= tx; x++) { + for (int z = bz; z <= tz; z++) { + map.saveBlocks(newWorld, 256, cbx + x, cbz + z, relX, relZ); } - }); - } - }, () -> { + } + }).withFinalAction(() -> { for (Entry entry : map.allBlocks.entrySet()) { PlotLoc loc = entry.getKey(); BaseBlock[] blocks = entry.getValue(); @@ -250,17 +249,17 @@ public class BukkitRegionManager extends RegionManager { } queue.setCompleteTask(() -> { //map.restoreBlocks(newWorld, 0, 0); - map.restoreEntities((World) newPos.getWorld(), relX, relZ); + map.restoreEntities(Bukkit.getWorld(newPos.getWorldName()), relX, relZ); TaskManager.runTask(whenDone); }); queue.enqueue(); - }, 5); + }); return true; } - @Override public boolean regenerateRegion(final Location pos1, final Location pos2, + @Override @Inject public boolean regenerateRegion(final Location pos1, final Location pos2, final boolean ignoreAugment, final Runnable whenDone) { - final String world = pos1.getWorldName(); + final BukkitWorld world = new BukkitWorld((World) pos1.getWorld()); final int p1x = pos1.getX(); final int p1z = pos1.getZ(); @@ -278,137 +277,123 @@ public class BukkitRegionManager extends RegionManager { chunks.add(BlockVector2.at(x, z)); } } - final World worldObj = Bukkit.getWorld(world); - checkNotNull(worldObj, "Critical error during regeneration."); - final BukkitWorld bukkitWorldObj = new BukkitWorld(worldObj); - TaskManager.runTask(new Runnable() { - @Override public void run() { - long start = System.currentTimeMillis(); - while (!chunks.isEmpty() && System.currentTimeMillis() - start < 5) { - final BlockVector2 chunk = chunks.remove(0); - int x = chunk.getX(); - int z = chunk.getZ(); - int xxb = x << 4; - int zzb = z << 4; - int xxt = xxb + 15; - int zzt = zzb + 15; - PaperLib.getChunkAtAsync(worldObj, x, z, false).thenAccept(chunkObj -> { - if (chunkObj == null) { - return; - } - final QueueCoordinator queue = - PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false); - if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { - AugmentedUtils.bypass(ignoreAugment, - () -> queue.regenChunkSafe(chunk.getX(), chunk.getZ())); - return; - } - boolean checkX1 = false; - int xxb2; + final QueueCoordinator queue = + PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false); + chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world) + .withRegion(pos1, pos2).withThrowableConsumer(Throwable::printStackTrace) + .withRegion(pos1, pos2).withInitialBatchSize(4).withMaxIterationTime(45) + .withConsumer(chunk -> { - if (x == bcx) { - xxb2 = p1x - 1; - checkX1 = true; - } else { - xxb2 = xxb; - } - boolean checkX2 = false; - int xxt2; - if (x == tcx) { - xxt2 = p2x + 1; - checkX2 = true; - } else { - xxt2 = xxt; - } - boolean checkZ1 = false; - int zzb2; - if (z == bcz) { - zzb2 = p1z - 1; - checkZ1 = true; - } else { - zzb2 = zzb; - } - boolean checkZ2 = false; - int zzt2; - if (z == tcz) { - zzt2 = p2z + 1; - checkZ2 = true; - } else { - zzt2 = zzt; - } - final ContentMap map = new ContentMap(); - if (checkX1) { - map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); // - } - if (checkX2) { - map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); // - } - if (checkZ1) { - map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); // - } - if (checkZ2) { - map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); // - } - if (checkX1 && checkZ1) { - map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); // - } - if (checkX2 && checkZ1) { - map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ? - } - if (checkX1 && checkZ2) { - map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ? - } - if (checkX2 && checkZ2) { - map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); // - } - CuboidRegion currentPlotClear = RegionUtil - .createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); - map.saveEntitiesOut(chunkObj, currentPlotClear); - AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager - .setChunkInPlotArea(null, new RunnableVal() { - @Override public void run(ScopedQueueCoordinator value) { - Location min = value.getMin(); - int bx = min.getX(); - int bz = min.getZ(); - for (int x1 = 0; x1 < 16; x1++) { - for (int z1 = 0; z1 < 16; z1++) { - PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); - BaseBlock[] ids = map.allBlocks.get(plotLoc); - if (ids != null) { - for (int y = 0; - y < Math.min(128, ids.length); y++) { - BaseBlock id = ids[y]; - if (id != null) { - value.setBlock(x1, y, z1, id); - } else { - value.setBlock(x1, y, z1, - BlockTypes.AIR.getDefaultState()); - } - } - for (int y = Math.min(128, ids.length); - y < ids.length; y++) { - BaseBlock id = ids[y]; - if (id != null) { - value.setBlock(x1, y, z1, id); - } - } + int x = chunk.getX(); + int z = chunk.getZ(); + int xxb = x << 4; + int zzb = z << 4; + int xxt = xxb + 15; + int zzt = zzb + 15; + if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { + AugmentedUtils.bypass(ignoreAugment, + () -> queue.regenChunkSafe(chunk.getX(), chunk.getZ())); + return; + } + boolean checkX1 = false; + + int xxb2; + + if (x == bcx) { + xxb2 = p1x - 1; + checkX1 = true; + } else { + xxb2 = xxb; + } + boolean checkX2 = false; + int xxt2; + if (x == tcx) { + xxt2 = p2x + 1; + checkX2 = true; + } else { + xxt2 = xxt; + } + boolean checkZ1 = false; + int zzb2; + if (z == bcz) { + zzb2 = p1z - 1; + checkZ1 = true; + } else { + zzb2 = zzb; + } + boolean checkZ2 = false; + int zzt2; + if (z == tcz) { + zzt2 = p2z + 1; + checkZ2 = true; + } else { + zzt2 = zzt; + } + final ContentMap map = new ContentMap(); + if (checkX1) { + map.saveRegion(world, xxb, xxb2, zzb2, zzt2); // + } + if (checkX2) { + map.saveRegion(world, xxt2, xxt, zzb2, zzt2); // + } + if (checkZ1) { + map.saveRegion(world, xxb2, xxt2, zzb, zzb2); // + } + if (checkZ2) { + map.saveRegion(world, xxb2, xxt2, zzt2, zzt); // + } + if (checkX1 && checkZ1) { + map.saveRegion(world, xxb, xxb2, zzb, zzb2); // + } + if (checkX2 && checkZ1) { + map.saveRegion(world, xxt2, xxt, zzb, zzb2); // ? + } + if (checkX1 && checkZ2) { + map.saveRegion(world, xxb, xxb2, zzt2, zzt); // ? + } + if (checkX2 && checkZ2) { + map.saveRegion(world, xxt2, xxt, zzt2, zzt); // + } + CuboidRegion currentPlotClear = + RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); + map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z), + currentPlotClear); + AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager + .setChunkInPlotArea(null, new RunnableVal() { + @Override public void run(ScopedQueueCoordinator value) { + Location min = value.getMin(); + int bx = min.getX(); + int bz = min.getZ(); + for (int x1 = 0; x1 < 16; x1++) { + for (int z1 = 0; z1 < 16; z1++) { + PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); + BaseBlock[] ids = map.allBlocks.get(plotLoc); + if (ids != null) { + for (int y = 0; y < Math.min(128, ids.length); y++) { + BaseBlock id = ids[y]; + if (id != null) { + value.setBlock(x1, y, z1, id); + } else { + value.setBlock(x1, y, z1, + BlockTypes.AIR.getDefaultState()); + } + } + for (int y = Math.min(128, ids.length); + y < ids.length; y++) { + BaseBlock id = ids[y]; + if (id != null) { + value.setBlock(x1, y, z1, id); } } } } - }, world, chunk)); - //map.restoreBlocks(worldObj, 0, 0); - map.restoreEntities(worldObj, 0, 0); - }); - } - if (!chunks.isEmpty()) { - TaskManager.runTaskLater(this, TaskTime.ticks(1L)); - } else { - TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L)); - } - } - }); + } + } + }, world.getName(), chunk)); + //map.restoreBlocks(worldObj, 0, 0); + map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0); + }).withFinalAction(whenDone); return true; } @@ -471,19 +456,22 @@ public class BukkitRegionManager extends RegionManager { region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome); Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome, region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome); - final QueueCoordinator queue = - PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false); + final QueueCoordinator queue = PlotSquared.platform().getGlobalBlockQueue() + .getNewQueue(worldUtil.getWeWorld(world), false); - ChunkManager.chunkTask(pos1, pos2, new RunnableVal() { - @Override public void run(int[] value) { - BlockVector2 loc = BlockVector2.at(value[0], value[1]); - PlotSquared.platform().getChunkManager().loadChunk(world, loc, false) - .thenRun(() -> { - MainUtil.setBiome(world, value[2], value[3], value[4], value[5], biome); - queue.refreshChunk(value[0], value[1]); - }); - } - }, whenDone, 5); + final int minX = pos1.getX(); + final int minZ = pos1.getZ(); + final int maxX = pos2.getX(); + final int maxZ = pos2.getZ(); + queue.setChunkConsumer(blockVector2 -> { + final int cx = blockVector2.getX() << 4; + final int cz = blockVector2.getZ() << 4; + MainUtil + .setBiome(world, Math.max(minX, cx), Math.max(minZ, cz), Math.min(maxX, cx + 15), + Math.min(maxZ, cz + 15), biome); + worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world); + }); + queue.enqueue(); } private void count(int[] count, Entity entity) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 75ac9a1be..393a88982 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -111,15 +111,18 @@ import java.util.function.IntConsumer; import java.util.stream.Stream; @SuppressWarnings({"unused", "WeakerAccess"}) -@Singleton public class BukkitUtil extends WorldUtil { +@Singleton +public class BukkitUtil extends WorldUtil { - private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitUtil.class.getSimpleName()); + private static final Logger logger = + LoggerFactory.getLogger("P2/" + BukkitUtil.class.getSimpleName()); private static String lastString = null; private static World lastWorld = null; private static Player lastPlayer = null; private static BukkitPlayer lastPlotPlayer = null; + private final Collection tileEntityTypes = new HashSet<>(); @Inject public BukkitUtil(@Nonnull final RegionManager regionManager) { super(regionManager); @@ -139,7 +142,8 @@ import java.util.stream.Stream; final Player player = OfflinePlayerUtil.loadPlayer(op); player.loadData(); return new BukkitPlayer(PlotSquared.get().getPlotAreaManager(), - PlotSquared.get().getEventDispatcher(), player, true, PlotSquared.platform().getEconHandler()); + PlotSquared.get().getEventDispatcher(), player, true, + PlotSquared.platform().getEconHandler()); } /** @@ -194,18 +198,6 @@ import java.util.stream.Stream; return PlotPlayer.wrap(player); } - /** - * Gets the PlotPlayer for a UUID. The PlotPlayer is usually cached and - * will provide useful functions relating to players. - * - * @param uuid the uuid to wrap - * @return a {@code PlotPlayer} - * @see PlotPlayer#wrap(Object) - */ - @Override public PlotPlayer wrapPlayer(UUID uuid) { - return PlotPlayer.wrap(Bukkit.getOfflinePlayer(uuid)); - } - /** * Gets the number of plots, which the player is able to build in. * @@ -287,18 +279,19 @@ import java.util.stream.Stream; public static Location getLocation(final org.bukkit.Location location) { return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), - MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ())); + MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), + MathMan.roundInt(location.getZ())); } public static Location getLocationFull(final org.bukkit.Location location) { return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), - MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()), location.getYaw(), - location.getPitch()); + MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), + MathMan.roundInt(location.getZ()), location.getYaw(), location.getPitch()); } public static org.bukkit.Location getLocation(@Nonnull final Location location) { - return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), location.getX(), - location.getY(), location.getZ()); + return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), + location.getX(), location.getY(), location.getZ()); } public static World getWorld(@Nonnull final String string) { @@ -321,8 +314,7 @@ import java.util.stream.Stream; public static Location getLocation(@Nonnull final Entity entity) { final org.bukkit.Location location = entity.getLocation(); String world = location.getWorld().getName(); - return Location.at(world, location.getBlockX(), location.getBlockY(), - location.getBlockZ()); + return Location.at(world, location.getBlockX(), location.getBlockY(), location.getBlockZ()); } @Nonnull public static Location getLocationFull(@Nonnull final Entity entity) { @@ -336,6 +328,38 @@ import java.util.stream.Stream; return BukkitAdapter.adapt(plotBlock.getBlockType()); } + private static void ensureLoaded(final String world, final int x, final int z, + final Consumer chunkConsumer) { + PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true) + .thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk)); + } + + private static void ensureLoaded(final Location location, final Consumer chunkConsumer) { + PaperLib.getChunkAtAsync(getLocation(location), true) + .thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk)); + } + + private static void ensureMainThread(final Consumer consumer, final T value) { + if (Bukkit.isPrimaryThread()) { + consumer.accept(value); + } else { + Bukkit.getScheduler().runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), + () -> consumer.accept(value)); + } + } + + /** + * Gets the PlotPlayer for a UUID. The PlotPlayer is usually cached and + * will provide useful functions relating to players. + * + * @param uuid the uuid to wrap + * @return a {@code PlotPlayer} + * @see PlotPlayer#wrap(Object) + */ + @Override public PlotPlayer wrapPlayer(UUID uuid) { + return PlotPlayer.wrap(Bukkit.getOfflinePlayer(uuid)); + } + @Override public boolean isBlockSame(BlockState block1, BlockState block2) { if (block1.equals(block2)) { return true; @@ -357,8 +381,7 @@ import java.util.stream.Stream; return BukkitAdapter.adapt(getWorld(world).getBiome(x, z)); } - @Override - public void getHighestBlock(@Nonnull final String world, final int x, final int z, + @Override public void getHighestBlock(@Nonnull final String world, final int x, final int z, final IntConsumer result) { ensureLoaded(world, x, z, chunk -> { final World bukkitWorld = getWorld(world); @@ -437,8 +460,9 @@ import java.util.stream.Stream; @Override public Location getSpawn(@Nonnull final String world) { final org.bukkit.Location temp = getWorld(world).getSpawnLocation(); - return Location.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), - temp.getYaw(), temp.getPitch()); + return Location + .at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(), + temp.getPitch()); } @Override public void setSpawn(@Nonnull final Location location) { @@ -518,7 +542,8 @@ import java.util.stream.Stream; @Nonnull final BiomeType biomeType) { final World world = getWorld(worldName); if (world == null) { - logger.warn("[P2] An error occured while setting the biome because the world was null", new RuntimeException()); + logger.warn("[P2] An error occured while setting the biome because the world was null", + new RuntimeException()); return; } final Biome biome = BukkitAdapter.adapt(biomeType); @@ -536,6 +561,10 @@ import java.util.stream.Stream; return new BukkitWorld(Bukkit.getWorld(world)); } + @Override public void refreshChunk(int x, int z, String world) { + Bukkit.getWorld(world).refreshChunk(x, z); + } + @Override public void getBlock(@Nonnull final Location location, final Consumer result) { ensureLoaded(location, chunk -> { @@ -571,8 +600,7 @@ import java.util.stream.Stream; Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel); } - @Override - public Set getTypesInCategory( + @Override public Set getTypesInCategory( final String category) { final Collection> allowedInterfaces = new HashSet<>(); switch (category) { @@ -653,7 +681,6 @@ import java.util.stream.Stream; return types; } - private final Collection tileEntityTypes = new HashSet<>(); @Override public Collection getTileEntityTypes() { if (this.tileEntityTypes.isEmpty()) { // Categories @@ -665,44 +692,21 @@ import java.util.stream.Stream; // Add these from strings Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace", "brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest", - "command_block", "end_gateway", "hopper", "jigsaw", "jubekox", - "lectern", "note_block", "black_shulker_box", "blue_shulker_box", - "brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box", + "command_block", "end_gateway", "hopper", "jigsaw", "jubekox", "lectern", + "note_block", "black_shulker_box", "blue_shulker_box", "brown_shulker_box", + "cyan_shulker_box", "gray_shulker_box", "green_shulker_box", "light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box", "magenta_shulker_box", "orange_shulker_box", "pink_shulker_box", "purple_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box", "yellow_shulker_box", "smoker", "structure_block", "structure_void") - .map(BlockTypes::get) - .filter(Objects::nonNull) - .forEach(tileEntityTypes::add); + .map(BlockTypes::get).filter(Objects::nonNull).forEach(tileEntityTypes::add); } return this.tileEntityTypes; } - @Override - public int getTileEntityCount(String world, BlockVector2 chunk) { + @Override public int getTileEntityCount(String world, BlockVector2 chunk) { return Bukkit.getWorld(world).getChunkAt(chunk.getBlockX(), chunk.getBlockZ()) .getTileEntities().length; } - private static void ensureLoaded(final String world, final int x, final int z, - final Consumer chunkConsumer) { - PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true) - .thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk)); - } - - private static void ensureLoaded(final Location location, final Consumer chunkConsumer) { - PaperLib.getChunkAtAsync(getLocation(location), true) - .thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk)); - } - - private static void ensureMainThread(final Consumer consumer, final T value) { - if (Bukkit.isPrimaryThread()) { - consumer.accept(value); - } else { - Bukkit.getScheduler() - .runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> consumer.accept(value)); - } - } - } diff --git a/Core/src/main/java/com/plotsquared/core/command/Clear.java b/Core/src/main/java/com/plotsquared/core/command/Clear.java index 1eee3a26c..2f7c48bcd 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Clear.java +++ b/Core/src/main/java/com/plotsquared/core/command/Clear.java @@ -42,6 +42,8 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import com.plotsquared.core.util.task.TaskManager; + import javax.annotation.Nonnull; import java.util.concurrent.CompletableFuture; @@ -91,7 +93,7 @@ public class Clear extends Command { final long start = System.currentTimeMillis(); boolean result = plot.clear(true, false, () -> { plot.unlink(); - this.blockQueue.addEmptyTask(() -> { + TaskManager.runTask(() -> { plot.removeRunning(); // If the state changes, then mark it as no longer done if (DoneFlag.isDone(plot)) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Template.java b/Core/src/main/java/com/plotsquared/core/command/Template.java index 5e90d5a90..3dd97eecb 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Template.java +++ b/Core/src/main/java/com/plotsquared/core/command/Template.java @@ -70,20 +70,17 @@ public class Template extends SubCommand { private final YamlConfiguration worldConfiguration; private final File worldFile; private final SetupUtils setupUtils; - private final GlobalBlockQueue globalBlockQueue; private final WorldUtil worldUtil; @Inject public Template(@Nonnull final PlotAreaManager plotAreaManager, @WorldConfig @Nonnull final YamlConfiguration worldConfiguration, @WorldFile @Nonnull final File worldFile, @Nonnull final SetupUtils setupUtils, - @Nonnull final GlobalBlockQueue globalBlockQueue, @Nonnull final WorldUtil worldUtil) { this.plotAreaManager = plotAreaManager; this.worldConfiguration = worldConfiguration; this.worldFile = worldFile; this.setupUtils = setupUtils; - this.globalBlockQueue = globalBlockQueue; this.worldUtil = worldUtil; } @@ -216,7 +213,7 @@ public class Template extends SubCommand { .worldName(world); this.setupUtils.setupWorld(builder); - this.globalBlockQueue.addEmptyTask(() -> { + TaskManager.runTask(() -> { MainUtil.sendMessage(player, "Done!"); player.teleport(this.worldUtil.getSpawn(world), TeleportCause.COMMAND); }); diff --git a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java index b046da010..c6dfe69e3 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java @@ -25,7 +25,6 @@ */ package com.plotsquared.core.generator; -import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Direction; import com.plotsquared.core.location.Location; @@ -37,6 +36,7 @@ import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.RegionManager; +import com.plotsquared.core.util.task.TaskManager; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.block.BlockTypes; @@ -92,7 +92,8 @@ public class ClassicPlotManager extends SquarePlotManager { .equals(classicPlotWorld.CLAIMED_WALL_BLOCK)) { setWall(plot.getId(), classicPlotWorld.WALL_BLOCK.toPattern()); } - return PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(whenDone); + TaskManager.runTask(whenDone); + return true; } public boolean setFloor(PlotId plotId, Pattern blocks) { diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java index ef20a88b6..ba2576395 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java @@ -510,7 +510,7 @@ public class HybridUtils { } } } - blockQueue.addEmptyTask(() -> TaskManager.runTaskLater(task, TaskTime.seconds(1L))); + TaskManager.runTaskLater(task, TaskTime.seconds(1L)); }); } } diff --git a/Core/src/main/java/com/plotsquared/core/inject/factory/QueueCoordinatorFactory.java b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorBuilderFactory.java similarity index 79% rename from Core/src/main/java/com/plotsquared/core/inject/factory/QueueCoordinatorFactory.java rename to Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorBuilderFactory.java index 969ceed3b..bfcbe206d 100644 --- a/Core/src/main/java/com/plotsquared/core/inject/factory/QueueCoordinatorFactory.java +++ b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorBuilderFactory.java @@ -25,12 +25,16 @@ */ package com.plotsquared.core.inject.factory; -import com.plotsquared.core.queue.QueueCoordinator; +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import com.plotsquared.core.queue.ChunkCoordinatorBuilder; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; -public interface QueueCoordinatorFactory { +public interface ChunkCoordinatorBuilderFactory { - @Nonnull QueueCoordinator create(); + @Inject @Nonnull ChunkCoordinatorBuilder create( + @Assisted @NotNull ChunkCoordinatorFactory chunkCoordinatorFactory); } diff --git a/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java new file mode 100644 index 000000000..463f58bb1 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java @@ -0,0 +1,48 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.google.inject.assistedinject.Assisted; +import com.plotsquared.core.queue.ChunkCoordinator; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.world.World; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.function.Consumer; + +public interface ChunkCoordinatorFactory { + + @Nonnull ChunkCoordinator create(@Assisted final long maxIterationTime, + @Assisted final int initialBatchSize, + @NotNull @Assisted final Consumer chunkConsumer, + @NotNull @Assisted final World world, + @NotNull @Assisted final Collection requestedChunks, + @NotNull @Assisted final Runnable whenDone, + @NotNull @Assisted final Consumer throwableConsumer); + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 827aa2c70..22b57da4d 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -965,7 +965,7 @@ public class Plot { manager.claimPlot(current); } } - blockQueue.addEmptyTask(run); + TaskManager.runTask(run); return; } Plot current = queue.poll(); @@ -1061,12 +1061,10 @@ public class Plot { current.setMerged(merged); } if (createSign) { - blockQueue.addEmptyTask(() -> { - TaskManager.runTaskAsync(() -> { - for (Plot current : plots) { - current.setSign(MainUtil.getName(current.getOwnerAbs())); - } - }); + TaskManager.runTaskAsync(() -> { + for (Plot current : plots) { + current.setSign(MainUtil.getName(current.getOwnerAbs())); + } }); } if (createRoad) { @@ -1687,7 +1685,8 @@ public class Plot { * This should not need to be called */ public void refreshChunks() { - QueueCoordinator queue = this.blockQueue.getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(getWorldName()), false); + QueueCoordinator queue = this.blockQueue + .getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(getWorldName()), false); HashSet chunks = new HashSet<>(); for (CuboidRegion region : Plot.this.getRegions()) { for (int x = region.getMinimumPoint().getX() >> 4; @@ -1695,7 +1694,7 @@ public class Plot { for (int z = region.getMinimumPoint().getZ() >> 4; z <= region.getMaximumPoint().getZ() >> 4; z++) { if (chunks.add(BlockVector2.at(x, z))) { - queue.refreshChunk(x, z); + worldUtil.refreshChunk(x, z, getWorldName()); } } } @@ -1711,7 +1710,8 @@ public class Plot { return; } Location location = manager.getSignLoc(this); - QueueCoordinator queue = this.blockQueue.getNewQueue(getWorldName(), false); + QueueCoordinator queue = + this.blockQueue.getNewQueue(worldUtil.getWeWorld(getWorldName()), false); queue.setBlock(location.getX(), location.getY(), location.getZ(), BlockTypes.AIR.getDefaultState()); queue.enqueue(); diff --git a/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java index 2d13a70e3..87fe6d634 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java +++ b/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java @@ -31,7 +31,6 @@ 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.Nullable; @@ -39,7 +38,7 @@ import java.util.Objects; public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator { - @Getter private final PlotArea area; + private final PlotArea area; public AreaBoundDelegateQueueCoordinator(@Nonnull final PlotArea area, @Nullable final QueueCoordinator parent) { @@ -47,6 +46,10 @@ public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator this.area = Objects.requireNonNull(area); } + public PlotArea getArea() { + return this.area; + } + @Override public boolean setBlock(int x, int y, int z, BlockState id) { if (area.contains(x, z)) { return super.setBlock(x, y, z, id); diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java index 3e3e8c4cf..7abc64bc4 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java +++ b/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java @@ -33,22 +33,23 @@ import com.sk89q.worldedit.world.World; 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 java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; public abstract class BasicQueueCoordinator extends QueueCoordinator { private final World world; - @Getter private final ConcurrentHashMap blockChunks = + private final ConcurrentHashMap blockChunks = new ConcurrentHashMap<>(); private long modified; private LocalChunk lastWrappedChunk; private int lastX = Integer.MIN_VALUE; private int lastZ = Integer.MIN_VALUE; - @Getter private boolean settingBiomes = false; - @Getter private boolean settingTiles = false; + private boolean settingBiomes = false; + private boolean settingTiles = false; + private Consumer consumer = null; private GlobalBlockQueue globalBlockQueue; @@ -97,7 +98,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator { return setBlock(x, y, z, id.toBaseBlock()); } - @Override public final boolean setBiome(int x, int z, BiomeType biomeType) { + @Override public boolean setBiome(int x, int z, BiomeType biomeType) { LocalChunk chunk = getChunk(x >> 4, z >> 4); for (int y = 0; y < 256; y++) { chunk.setBiome(x & 15, y, z & 15, biomeType); @@ -113,17 +114,37 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator { return true; } - @Override public final boolean setTile(int x, int y, int z, CompoundTag tag) { + @Override public boolean isSettingBiomes() { + return this.settingBiomes; + } + + @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { LocalChunk chunk = getChunk(x >> 4, z >> 4); chunk.setTile(x, y, z, tag); settingTiles = true; return true; } + @Override public boolean isSettingTiles() { + return this.settingTiles; + } + + public ConcurrentHashMap getBlockChunks() { + return this.blockChunks; + } + public final void setChunk(LocalChunk chunk) { this.blockChunks.put(BlockVector2.at(chunk.getX(), chunk.getZ()), chunk); } + public final Consumer getChunkConsumer() { + return this.consumer; + } + + public final void setChunkConsumer(Consumer consumer) { + this.consumer = consumer; + } + private LocalChunk getChunk(final int chunkX, final int chunkZ) { if (chunkX != lastX || chunkZ != lastZ) { lastX = chunkX; diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java new file mode 100644 index 000000000..d596d27dc --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java @@ -0,0 +1,22 @@ +package com.plotsquared.core.queue; + +import com.plotsquared.core.util.task.PlotSquaredTask; + +public abstract class ChunkCoordinator implements PlotSquaredTask { + + @Override public abstract void runTask(); + + @Override public boolean isCancelled() { + return false; + } + + @Override public void cancel() { + // Do nothing + } + + public abstract void start(); + + public abstract int getRemainingChunks(); + + public abstract int getTotalChunks(); +} diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java new file mode 100644 index 000000000..a968e1992 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java @@ -0,0 +1,113 @@ +package com.plotsquared.core.queue; + +import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; +import com.plotsquared.core.location.Location; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.world.World; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Consumer; + +public class ChunkCoordinatorBuilder { + + private final List requestedChunks = new LinkedList<>(); + private Consumer throwableConsumer = Throwable::printStackTrace; + private World world; + private Consumer chunkConsumer; + private Runnable whenDone = () -> { + }; + private long maxIterationTime = 60; // A little over 1 tick; + private int initialBatchSize = 4; + private final ChunkCoordinatorFactory chunkCoordinatorFactory; + + @Inject public ChunkCoordinatorBuilder(@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory) { + this.chunkCoordinatorFactory = chunkCoordinatorFactory; + } + + @NotNull public ChunkCoordinatorBuilder inWorld(@NotNull final World world) { + this.world = Preconditions.checkNotNull(world, "World may not be null"); + return this; + } + + @NotNull public ChunkCoordinatorBuilder withChunk(@NotNull final BlockVector2 chunkLocation) { + this.requestedChunks + .add(Preconditions.checkNotNull(chunkLocation, "Chunk location may not be null")); + return this; + } + + @NotNull public ChunkCoordinatorBuilder withChunks( + @NotNull final Collection chunkLocations) { + chunkLocations.forEach(this::withChunk); + return this; + } + + @NotNull public ChunkCoordinatorBuilder withRegion(Location pos1, Location pos2) { + final int p1x = pos1.getX(); + final int p1z = pos1.getZ(); + final int p2x = pos2.getX(); + final int p2z = pos2.getZ(); + final int bcx = p1x >> 4; + final int bcz = p1z >> 4; + final int tcx = p2x >> 4; + final int tcz = p2z >> 4; + final ArrayList chunks = new ArrayList<>(); + + for (int x = bcx; x <= tcx; x++) { + for (int z = bcz; z <= tcz; z++) { + chunks.add(BlockVector2.at(x, z)); + } + } + + chunks.forEach(this::withChunk); + return this; + } + + @NotNull public ChunkCoordinatorBuilder withConsumer( + @NotNull final Consumer chunkConsumer) { + this.chunkConsumer = + Preconditions.checkNotNull(chunkConsumer, "Chunk consumer may not be null"); + return this; + } + + @NotNull public ChunkCoordinatorBuilder withFinalAction(@NotNull final Runnable whenDone) { + this.whenDone = Preconditions.checkNotNull(whenDone, "Final action may not be null"); + return this; + } + + @NotNull public ChunkCoordinatorBuilder withMaxIterationTime(final long maxIterationTime) { + Preconditions.checkArgument(maxIterationTime > 0, "Max iteration time must be positive"); + this.maxIterationTime = maxIterationTime; + return this; + } + + @NotNull public ChunkCoordinatorBuilder withInitialBatchSize(final int initialBatchSize) { + Preconditions.checkArgument(initialBatchSize > 0, "Initial batch size must be positive"); + this.initialBatchSize = initialBatchSize; + 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() { + 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 chunkCoordinatorFactory.create(this.maxIterationTime, this.initialBatchSize, + this.chunkConsumer, this.world, this.requestedChunks, this.whenDone, + this.throwableConsumer); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java index 790ad2a51..76cffc3be 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java +++ b/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java @@ -27,11 +27,14 @@ package com.plotsquared.core.queue; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; +import java.util.function.Consumer; + public class DelegateQueueCoordinator extends QueueCoordinator { private final QueueCoordinator parent; @@ -111,4 +114,8 @@ public class DelegateQueueCoordinator extends QueueCoordinator { @Override public void setCompleteTask(Runnable whenDone) { parent.setCompleteTask(whenDone); } + + @Override public void setChunkConsumer(Consumer consumer) { + parent.setChunkConsumer(consumer); + } } 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 56437f0cd..0e2775b6d 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -27,8 +27,6 @@ package com.plotsquared.core.queue; import com.plotsquared.core.PlotSquared; import com.sk89q.worldedit.world.World; -import lombok.Getter; -import lombok.Setter; import java.util.ArrayList; import java.util.List; @@ -37,7 +35,7 @@ import java.util.concurrent.ConcurrentLinkedDeque; public class GlobalBlockQueue { private final ConcurrentLinkedDeque activeQueues; - @Getter @Setter private QueueProvider provider; + private QueueProvider provider; public GlobalBlockQueue(QueueProvider provider) { this.provider = provider; @@ -54,6 +52,14 @@ public class GlobalBlockQueue { return queue; } + public QueueProvider getProvider() { + return this.provider; + } + + public void setQueueProvider(QueueProvider provider) { + this.provider = provider; + } + /** * TODO Documentation needed. * diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java b/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java index e638fe4ef..af6a30fe3 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java +++ b/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java @@ -6,18 +6,17 @@ 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 lombok.Getter; import java.util.HashMap; public class LocalChunk { - @Getter private final BasicQueueCoordinator parent; - @Getter private final int z; - @Getter private final int x; + private final BasicQueueCoordinator parent; + private final int x; + private final int z; - @Getter private final BaseBlock[][] baseblocks; - @Getter private final BiomeType[][] biomes; - @Getter private final HashMap tiles = new HashMap<>(); + private final BaseBlock[][] baseblocks; + private final BiomeType[][] biomes; + private final HashMap tiles = new HashMap<>(); public LocalChunk(BasicQueueCoordinator parent, int x, int z) { this.parent = parent; @@ -27,6 +26,30 @@ public class LocalChunk { biomes = new BiomeType[16][]; } + public BasicQueueCoordinator getParent() { + return this.parent; + } + + public int getX() { + return this.x; + } + + public int getZ() { + return this.z; + } + + public BaseBlock[][] getBaseblocks() { + return this.baseblocks; + } + + public BiomeType[][] getBiomes() { + return this.biomes; + } + + public HashMap getTiles() { + return this.tiles; + } + public void setBiome(final int x, final int y, final int z, final BiomeType biomeType) { final int i = MainUtil.CACHE_I[y][x][z]; final int j = MainUtil.CACHE_J[y][x][z]; diff --git a/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java index ca8b3a7c9..91194e25f 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java +++ b/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java @@ -31,20 +31,21 @@ import com.plotsquared.core.location.Location; import com.plotsquared.core.util.PatternUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.world.World; 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 org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.function.Consumer; public abstract class QueueCoordinator { - @Getter @Setter private boolean forceSync = false; - @Getter @Setter @Nullable private Object chunkObject; + private boolean forceSync = false; + @Nullable private Object chunkObject; @Inject private GlobalBlockQueue blockQueue; @@ -63,6 +64,22 @@ public abstract class QueueCoordinator { public abstract void setModified(long modified); + public boolean isForceSync() { + return forceSync; + } + + public void setForceSync(boolean forceSync) { + this.forceSync = forceSync; + } + + @Nullable public Object getChunkObject() { + return chunkObject; + } + + public void setChunkObject(@NotNull Object chunkObject) { + this.chunkObject = chunkObject; + } + /** * Sets the block at the coordinates provided to the given id. * @@ -103,6 +120,8 @@ public abstract class QueueCoordinator { public abstract void setCompleteTask(Runnable whenDone); + public abstract void setChunkConsumer(Consumer consumer); + public void setCuboid(Location pos1, Location pos2, BlockState block) { int yMin = Math.min(pos1.getY(), pos2.getY()); int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index 9b9bd9a7d..e94548d0e 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java @@ -26,10 +26,12 @@ package com.plotsquared.core.util; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotManager; +import com.plotsquared.core.queue.ChunkCoordinatorBuilder; import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; @@ -55,7 +57,8 @@ public abstract class RegionManager { public static RegionManager manager = null; private final ChunkManager chunkManager; - public RegionManager(@Nonnull final ChunkManager chunkManager, @Nonnull WorldUtil worldUtil) { + public RegionManager(@Nonnull final ChunkManager chunkManager, @Nonnull WorldUtil worldUtil, + @Nonnull ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory) { this.chunkManager = chunkManager; } @@ -95,12 +98,13 @@ public abstract class RegionManager { } } } - TaskManager.getPlatformImplementation().objectTask(chunks, new RunnableVal() { - @Override public void run(BlockVector2 value) { - chunkManager.loadChunk(world, value, false).thenRun(() -> task.run(value)); - } - }).thenAccept(ignore -> - TaskManager.getPlatformImplementation().taskLater(whenDone, TaskTime.ticks(1L))); + TaskManager.getPlatformImplementation() + .objectTask(chunks, new RunnableVal() { + @Override public void run(BlockVector2 value) { + chunkManager.loadChunk(world, value, false).thenRun(() -> task.run(value)); + } + }).thenAccept(ignore -> TaskManager.getPlatformImplementation() + .taskLater(whenDone, TaskTime.ticks(1L))); }); } diff --git a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java index 5d58c1c19..2b2f091bc 100644 --- a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java @@ -118,6 +118,8 @@ public abstract class WorldUtil { public abstract com.sk89q.worldedit.world.World getWeWorld(String world); + public abstract void refreshChunk(int x, int z, String world); + public void upload(@Nonnull final Plot plot, UUID uuid, String file, RunnableVal whenDone) { plot.getHome(home -> MainUtil.upload(uuid, file, "zip", new RunnableVal() {