mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2024-11-25 06:36:44 +01:00
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
This commit is contained in:
parent
66b94ab9f1
commit
57af50ed49
@ -26,12 +26,11 @@
|
|||||||
package com.plotsquared.bukkit.inject;
|
package com.plotsquared.bukkit.inject;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
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.assistedinject.FactoryModuleBuilder;
|
||||||
import com.google.inject.util.Providers;
|
import com.google.inject.util.Providers;
|
||||||
import com.plotsquared.bukkit.BukkitPlatform;
|
import com.plotsquared.bukkit.BukkitPlatform;
|
||||||
import com.plotsquared.bukkit.player.BukkitPlayerManager;
|
import com.plotsquared.bukkit.player.BukkitPlayerManager;
|
||||||
|
import com.plotsquared.bukkit.queue.BukkitChunkCoordinator;
|
||||||
import com.plotsquared.bukkit.queue.BukkitQueueCoordinator;
|
import com.plotsquared.bukkit.queue.BukkitQueueCoordinator;
|
||||||
import com.plotsquared.bukkit.schematic.BukkitSchematicHandler;
|
import com.plotsquared.bukkit.schematic.BukkitSchematicHandler;
|
||||||
import com.plotsquared.bukkit.util.BukkitChunkManager;
|
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.BukkitRegionManager;
|
||||||
import com.plotsquared.bukkit.util.BukkitSetupUtils;
|
import com.plotsquared.bukkit.util.BukkitSetupUtils;
|
||||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
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.PlotPlatform;
|
||||||
import com.plotsquared.core.configuration.Settings;
|
import com.plotsquared.core.configuration.Settings;
|
||||||
import com.plotsquared.core.generator.HybridGen;
|
import com.plotsquared.core.generator.HybridGen;
|
||||||
import com.plotsquared.core.generator.IndependentPlotGenerator;
|
import com.plotsquared.core.generator.IndependentPlotGenerator;
|
||||||
import com.plotsquared.core.inject.annotations.ConsoleActor;
|
import com.plotsquared.core.inject.annotations.ConsoleActor;
|
||||||
import com.plotsquared.core.inject.annotations.DefaultGenerator;
|
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.inject.factory.HybridPlotWorldFactory;
|
||||||
import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
|
import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
|
||||||
import com.plotsquared.core.plot.world.PlotAreaManager;
|
import com.plotsquared.core.plot.world.PlotAreaManager;
|
||||||
import com.plotsquared.core.plot.world.SinglePlotAreaManager;
|
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.GlobalBlockQueue;
|
||||||
import com.plotsquared.core.queue.QueueProvider;
|
import com.plotsquared.core.queue.QueueProvider;
|
||||||
import com.plotsquared.core.util.ChunkManager;
|
import com.plotsquared.core.util.ChunkManager;
|
||||||
@ -105,6 +106,10 @@ public class BukkitModule extends AbstractModule {
|
|||||||
bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class);
|
bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class);
|
||||||
}
|
}
|
||||||
install(new FactoryModuleBuilder().build(HybridPlotWorldFactory.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() {
|
private void setupVault() {
|
||||||
|
@ -25,17 +25,19 @@
|
|||||||
*/
|
*/
|
||||||
package com.plotsquared.bukkit.queue;
|
package com.plotsquared.bukkit.queue;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.plotsquared.bukkit.BukkitPlatform;
|
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.math.BlockVector2;
|
||||||
|
import com.sk89q.worldedit.world.World;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
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.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -44,32 +46,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
||||||
* Utility that allows for the loading and coordination of chunk actions
|
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* <p>
|
|
||||||
* Usage:
|
|
||||||
* <pre>{@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();
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @author Alexander Söderberg
|
|
||||||
* @see #builder() To create a new coordinator instance
|
|
||||||
*/
|
|
||||||
public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|
||||||
|
|
||||||
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
|
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
|
||||||
|
|
||||||
@ -77,52 +54,44 @@ public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|||||||
private final Queue<Chunk> availableChunks;
|
private final Queue<Chunk> availableChunks;
|
||||||
private final long maxIterationTime;
|
private final long maxIterationTime;
|
||||||
private final Plugin plugin;
|
private final Plugin plugin;
|
||||||
private final Consumer<Chunk> chunkConsumer;
|
private final Consumer<BlockVector2> chunkConsumer;
|
||||||
private final World world;
|
private final org.bukkit.World bukkitWorld;
|
||||||
private final Runnable whenDone;
|
private final Runnable whenDone;
|
||||||
private final Consumer<Throwable> throwableConsumer;
|
private final Consumer<Throwable> throwableConsumer;
|
||||||
private final int totalSize;
|
private final int totalSize;
|
||||||
|
|
||||||
private AtomicInteger expectedSize;
|
private final AtomicInteger expectedSize;
|
||||||
private int batchSize;
|
private int batchSize;
|
||||||
|
|
||||||
private BukkitChunkCoordinator(final long maxIterationTime, final int initialBatchSize,
|
private BukkitChunkCoordinator(final long maxIterationTime, final int initialBatchSize,
|
||||||
@NotNull final Consumer<Chunk> chunkConsumer, @NotNull final World world,
|
@Nonnull final Consumer<BlockVector2> chunkConsumer, @Nonnull final World world,
|
||||||
@NotNull final Collection<BlockVector2> requestedChunks, @NotNull final Runnable whenDone,
|
@Nonnull final Collection<BlockVector2> requestedChunks, @Nonnull final Runnable whenDone,
|
||||||
@NotNull final Consumer<Throwable> throwableConsumer) {
|
@Nonnull final Consumer<Throwable> throwableConsumer) {
|
||||||
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
|
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
|
||||||
this.availableChunks = new LinkedBlockingQueue<>();
|
this.availableChunks = new LinkedBlockingQueue<>();
|
||||||
this.totalSize = requestedChunks.size();
|
this.totalSize = requestedChunks.size();
|
||||||
this.expectedSize = new AtomicInteger(this.totalSize);
|
this.expectedSize = new AtomicInteger(this.totalSize);
|
||||||
this.world = world;
|
|
||||||
this.batchSize = initialBatchSize;
|
this.batchSize = initialBatchSize;
|
||||||
this.chunkConsumer = chunkConsumer;
|
this.chunkConsumer = chunkConsumer;
|
||||||
this.maxIterationTime = maxIterationTime;
|
this.maxIterationTime = maxIterationTime;
|
||||||
this.whenDone = whenDone;
|
this.whenDone = whenDone;
|
||||||
this.throwableConsumer = throwableConsumer;
|
this.throwableConsumer = throwableConsumer;
|
||||||
this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
|
this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
|
||||||
}
|
this.bukkitWorld = Bukkit.getWorld(world.getName());
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link BukkitChunkCoordinator} instance
|
|
||||||
*
|
|
||||||
* @return Coordinator builder instance
|
|
||||||
*/
|
|
||||||
@NotNull public static ChunkCoordinatorBuilder builder() {
|
|
||||||
return new ChunkCoordinatorBuilder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the coordinator instance
|
* Start the coordinator instance
|
||||||
*/
|
*/
|
||||||
public void start() {
|
@Override public void start() {
|
||||||
// Request initial batch
|
// Request initial batch
|
||||||
this.requestBatch();
|
this.requestBatch();
|
||||||
// Wait until next tick to give the chunks a chance to be loaded
|
// 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();
|
Chunk chunk = this.availableChunks.poll();
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
return;
|
return;
|
||||||
@ -132,7 +101,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|||||||
do {
|
do {
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
this.chunkConsumer.accept(chunk);
|
this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ()));
|
||||||
} catch (final Throwable throwable) {
|
} catch (final Throwable throwable) {
|
||||||
this.throwableConsumer.accept(throwable);
|
this.throwableConsumer.accept(throwable);
|
||||||
}
|
}
|
||||||
@ -173,7 +142,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|||||||
BlockVector2 chunk;
|
BlockVector2 chunk;
|
||||||
for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) {
|
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
|
// 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) -> {
|
.whenComplete((chunkObject, throwable) -> {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
throwable.printStackTrace();
|
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()) {
|
if (!chunk.isLoaded()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ()));
|
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);
|
this.availableChunks.add(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void freeChunk(@NotNull final Chunk chunk) {
|
private void freeChunk(@Nonnull final Chunk chunk) {
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ()));
|
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
|
* @return Snapshot view of remaining chunk count
|
||||||
*/
|
*/
|
||||||
public int getRemainingChunks() {
|
@Override public int getRemainingChunks() {
|
||||||
return this.expectedSize.get();
|
return this.expectedSize.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +186,7 @@ public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|||||||
*
|
*
|
||||||
* @return Requested chunk count
|
* @return Requested chunk count
|
||||||
*/
|
*/
|
||||||
public int getTotalChunks() {
|
@Override public int getTotalChunks() {
|
||||||
return this.totalSize;
|
return this.totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,11 +196,10 @@ public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|||||||
* @param subscriber Subscriber
|
* @param subscriber Subscriber
|
||||||
*/
|
*/
|
||||||
public void subscribeToProgress(
|
public void subscribeToProgress(
|
||||||
@NotNull final BukkitChunkCoordinator.ProgressSubscriber subscriber) {
|
@Nonnull final BukkitChunkCoordinator.ProgressSubscriber subscriber) {
|
||||||
this.progressSubscribers.add(subscriber);
|
this.progressSubscribers.add(subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ProgressSubscriber {
|
public interface ProgressSubscriber {
|
||||||
|
|
||||||
@ -241,88 +209,9 @@ public final class BukkitChunkCoordinator extends BukkitRunnable {
|
|||||||
* @param coordinator Coordinator instance that triggered the notification
|
* @param coordinator Coordinator instance that triggered the notification
|
||||||
* @param progress Progress in the range [0, 1]
|
* @param progress Progress in the range [0, 1]
|
||||||
*/
|
*/
|
||||||
void notifyProgress(@NotNull final BukkitChunkCoordinator coordinator,
|
void notifyProgress(@Nonnull final BukkitChunkCoordinator coordinator,
|
||||||
final float progress);
|
final float progress);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static final class ChunkCoordinatorBuilder {
|
|
||||||
|
|
||||||
private final List<BlockVector2> requestedChunks = new LinkedList<>();
|
|
||||||
private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace;
|
|
||||||
private World world;
|
|
||||||
private Consumer<Chunk> 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<BlockVector2> chunkLocations) {
|
|
||||||
chunkLocations.forEach(this::withChunk);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public ChunkCoordinatorBuilder withConsumer(@NotNull final Consumer<Chunk> 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<Throwable> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.plotsquared.bukkit.queue;
|
package com.plotsquared.bukkit.queue;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.plotsquared.bukkit.schematic.StateWrapper;
|
import com.plotsquared.bukkit.schematic.StateWrapper;
|
||||||
import com.plotsquared.bukkit.util.BukkitBlockUtil;
|
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.BasicQueueCoordinator;
|
||||||
import com.plotsquared.core.queue.LocalChunk;
|
import com.plotsquared.core.queue.LocalChunk;
|
||||||
import com.plotsquared.core.util.BlockUtil;
|
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.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.Container;
|
import org.bukkit.block.Container;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
||||||
|
|
||||||
private final World world;
|
private final World world;
|
||||||
private final SideEffectSet sideEffectSet;
|
private final SideEffectSet sideEffectSet;
|
||||||
|
@Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
|
||||||
|
@Inject private ChunkCoordinatorFactory chunkCoordinatorFactory;
|
||||||
private Runnable whenDone;
|
private Runnable whenDone;
|
||||||
|
|
||||||
public BukkitQueueCoordinator(World world) {
|
@Inject public BukkitQueueCoordinator(World world) {
|
||||||
super(world);
|
super(world);
|
||||||
this.world = world;
|
this.world = world;
|
||||||
sideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF)
|
sideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF)
|
||||||
@ -73,19 +81,18 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean enqueue() {
|
@Override public boolean enqueue() {
|
||||||
BukkitChunkCoordinator.builder().inWorld(BukkitAdapter.adapt(world))
|
Consumer<BlockVector2> consumer = getChunkConsumer();
|
||||||
.withChunks(getBlockChunks().keySet()).withInitialBatchSize(3).withMaxIterationTime(40)
|
if (consumer == null) {
|
||||||
.withThrowableConsumer(Throwable::printStackTrace).withFinalAction(whenDone)
|
consumer = blockVector2 -> {
|
||||||
.withConsumer(chunk -> {
|
LocalChunk localChunk = getBlockChunks().get(blockVector2);
|
||||||
LocalChunk localChunk =
|
|
||||||
getBlockChunks().get(BlockVector2.at(chunk.getX(), chunk.getZ()));
|
|
||||||
if (localChunk == null) {
|
if (localChunk == null) {
|
||||||
throw new NullPointerException(
|
throw new NullPointerException(
|
||||||
"LocalChunk cannot be null when accessed from ChunkCoordinator");
|
"LocalChunk cannot be null when accessed from ChunkCoordinator");
|
||||||
}
|
}
|
||||||
World worldObj = getWorld();
|
org.bukkit.World bukkitWorld = null;
|
||||||
int sx = chunk.getX() << 4;
|
Chunk chunk = null;
|
||||||
int sz = chunk.getX() << 4;
|
int sx = blockVector2.getX() << 4;
|
||||||
|
int sz = blockVector2.getZ() << 4;
|
||||||
for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) {
|
for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) {
|
||||||
BaseBlock[] blocksLayer = localChunk.getBaseblocks()[layer];
|
BaseBlock[] blocksLayer = localChunk.getBaseblocks()[layer];
|
||||||
if (blocksLayer == null) {
|
if (blocksLayer == null) {
|
||||||
@ -100,11 +107,19 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
|||||||
int y = MainUtil.y_loc[layer][j];
|
int y = MainUtil.y_loc[layer][j];
|
||||||
int z = sz + MainUtil.z_loc[layer][j];
|
int z = sz + MainUtil.z_loc[layer][j];
|
||||||
try {
|
try {
|
||||||
worldObj.setBlock(BlockVector3.at(x, y, z), block, sideEffectSet);
|
world.setBlock(BlockVector3.at(x, y, z), block, sideEffectSet);
|
||||||
} catch (WorldEditException ignored) {
|
} catch (WorldEditException ignored) {
|
||||||
// Fallback to not so nice method
|
// Fallback to not so nice method
|
||||||
BlockData blockData = BukkitAdapter.adapt(block);
|
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);
|
Block existing = chunk.getBlock(x, y, z);
|
||||||
final BlockState existingBaseBlock =
|
final BlockState existingBaseBlock =
|
||||||
BukkitAdapter.adapt(existing.getBlockData());
|
BukkitAdapter.adapt(existing.getBlockData());
|
||||||
@ -123,7 +138,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
|||||||
CompoundTag tag = block.getNbtData();
|
CompoundTag tag = block.getNbtData();
|
||||||
StateWrapper sw = new StateWrapper(tag);
|
StateWrapper sw = new StateWrapper(tag);
|
||||||
|
|
||||||
sw.restoreTag(worldObj.getName(), existing.getX(), existing.getY(),
|
sw.restoreTag(world.getName(), existing.getX(), existing.getY(),
|
||||||
existing.getZ());
|
existing.getZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,22 +157,27 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
|||||||
int x = sx + MainUtil.x_loc[layer][j];
|
int x = sx + MainUtil.x_loc[layer][j];
|
||||||
int y = MainUtil.y_loc[layer][j];
|
int y = MainUtil.y_loc[layer][j];
|
||||||
int z = sz + MainUtil.z_loc[layer][j];
|
int z = sz + MainUtil.z_loc[layer][j];
|
||||||
worldObj.setBiome(BlockVector3.at(x, y, z), biome);
|
world.setBiome(BlockVector3.at(x, y, z), biome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (localChunk.getTiles().size() > 0) {
|
if (localChunk.getTiles().size() > 0) {
|
||||||
localChunk.getTiles().forEach(((blockVector3, tag) -> {
|
localChunk.getTiles().forEach(((blockVector3, tag) -> {
|
||||||
try {
|
try {
|
||||||
BaseBlock block = worldObj.getBlock(blockVector3).toBaseBlock(tag);
|
BaseBlock block = world.getBlock(blockVector3).toBaseBlock(tag);
|
||||||
worldObj.setBlock(blockVector3, block, sideEffectSet);
|
world.setBlock(blockVector3, block, sideEffectSet);
|
||||||
} catch (WorldEditException ignored) {
|
} catch (WorldEditException ignored) {
|
||||||
StateWrapper sw = new StateWrapper(tag);
|
StateWrapper sw = new StateWrapper(tag);
|
||||||
sw.restoreTag(worldObj.getName(), blockVector3.getX(),
|
sw.restoreTag(world.getName(), blockVector3.getX(), blockVector3.getY(),
|
||||||
blockVector3.getY(), blockVector3.getZ());
|
blockVector3.getZ());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world)
|
||||||
|
.withChunks(getBlockChunks().keySet()).withInitialBatchSize(3).withMaxIterationTime(40)
|
||||||
|
.withThrowableConsumer(Throwable::printStackTrace).withFinalAction(whenDone)
|
||||||
|
.withConsumer(consumer);
|
||||||
return super.enqueue();
|
return super.enqueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,6 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -60,13 +58,21 @@ public class GenChunk extends ScopedQueueCoordinator {
|
|||||||
public String world;
|
public String world;
|
||||||
public int chunkX;
|
public int chunkX;
|
||||||
public int chunkZ;
|
public int chunkZ;
|
||||||
@Getter @Setter private ChunkData chunkData = null;
|
private ChunkData chunkData = null;
|
||||||
|
|
||||||
public GenChunk() {
|
public GenChunk() {
|
||||||
super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15));
|
super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15));
|
||||||
this.biomes = Biome.values();
|
this.biomes = Biome.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChunkData getChunkData() {
|
||||||
|
return this.chunkData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChunkData(ChunkData chunkData) {
|
||||||
|
this.chunkData = chunkData;
|
||||||
|
}
|
||||||
|
|
||||||
public Chunk getChunk() {
|
public Chunk getChunk() {
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
World worldObj = BukkitUtil.getWorld(world);
|
World worldObj = BukkitUtil.getWorld(world);
|
||||||
|
@ -30,6 +30,8 @@ import com.google.inject.Singleton;
|
|||||||
import com.plotsquared.bukkit.BukkitPlatform;
|
import com.plotsquared.bukkit.BukkitPlatform;
|
||||||
import com.plotsquared.core.PlotSquared;
|
import com.plotsquared.core.PlotSquared;
|
||||||
import com.plotsquared.core.generator.AugmentedUtils;
|
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.Location;
|
||||||
import com.plotsquared.core.location.PlotLoc;
|
import com.plotsquared.core.location.PlotLoc;
|
||||||
import com.plotsquared.core.plot.Plot;
|
import com.plotsquared.core.plot.Plot;
|
||||||
@ -86,16 +88,17 @@ public class BukkitRegionManager extends RegionManager {
|
|||||||
private static final Logger logger =
|
private static final Logger logger =
|
||||||
LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName());
|
LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName());
|
||||||
private final WorldUtil worldUtil;
|
private final WorldUtil worldUtil;
|
||||||
|
private final ChunkCoordinatorFactory chunkCoordinatorFactory;
|
||||||
|
private final ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
|
||||||
|
|
||||||
@Inject public BukkitRegionManager(@Nonnull final ChunkManager chunkManager,
|
@Inject public BukkitRegionManager(@Nonnull final ChunkManager chunkManager,
|
||||||
@Nonnull final WorldUtil worldUtil) {
|
@Nonnull final WorldUtil worldUtil,
|
||||||
super(chunkManager, worldUtil);
|
@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory,
|
||||||
|
@Nonnull ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory) {
|
||||||
|
super(chunkManager, worldUtil, chunkCoordinatorBuilderFactory);
|
||||||
this.worldUtil = worldUtil;
|
this.worldUtil = worldUtil;
|
||||||
}
|
this.chunkCoordinatorFactory = chunkCoordinatorFactory;
|
||||||
|
this.chunkCoordinatorBuilderFactory = chunkCoordinatorBuilderFactory;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Set<BlockVector2> getChunkChunks(String world) {
|
@Override public Set<BlockVector2> getChunkChunks(String world) {
|
||||||
@ -207,37 +210,33 @@ public class BukkitRegionManager extends RegionManager {
|
|||||||
return count;
|
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 Runnable whenDone) {
|
||||||
final int relX = newPos.getX() - pos1.getX();
|
final int relX = newPos.getX() - pos1.getX();
|
||||||
final int relZ = newPos.getZ() - pos1.getZ();
|
final int relZ = newPos.getZ() - pos1.getZ();
|
||||||
|
final com.sk89q.worldedit.world.World oldWorld = worldUtil.getWeWorld(pos1.getWorldName());
|
||||||
final CuboidRegion region =
|
|
||||||
RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
|
|
||||||
final BukkitWorld oldWorld = new BukkitWorld((World) pos1.getWorld());
|
|
||||||
final BukkitWorld newWorld = new BukkitWorld((World) newPos.getWorld());
|
final BukkitWorld newWorld = new BukkitWorld((World) newPos.getWorld());
|
||||||
|
assert oldWorld.equals(newWorld);
|
||||||
final ContentMap map = new ContentMap();
|
final ContentMap map = new ContentMap();
|
||||||
final QueueCoordinator queue =
|
final QueueCoordinator queue =
|
||||||
PlotSquared.platform().getGlobalBlockQueue().getNewQueue(newWorld, false);
|
PlotSquared.platform().getGlobalBlockQueue().getNewQueue(newWorld, false);
|
||||||
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
|
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(newWorld)
|
||||||
@Override public void run(int[] value) {
|
.withRegion(pos1, pos2).withThrowableConsumer(Throwable::printStackTrace)
|
||||||
int bx = value[2];
|
.withRegion(pos1, pos2).withInitialBatchSize(4).withMaxIterationTime(45)
|
||||||
int bz = value[3];
|
.withConsumer(chunk -> {
|
||||||
int tx = value[4];
|
int cbx = chunk.getX();
|
||||||
int tz = value[5];
|
int cbz = chunk.getZ();
|
||||||
BlockVector2 loc = BlockVector2.at(value[0], value[1]);
|
int bx = Math.max(pos1.getX() & 15, 0);
|
||||||
int cxx = loc.getX() << 4;
|
int bz = Math.max(pos1.getZ() & 15, 0);
|
||||||
int czz = loc.getZ() << 4;
|
int tx = Math.min(pos2.getX() & 15, 15);
|
||||||
PaperLib.getChunkAtAsync(oldWorld, loc.getX(), loc.getZ())
|
int tz = Math.min(pos2.getZ() & 15, 15);
|
||||||
.thenAccept(chunk1 -> map.saveEntitiesIn(chunk1, region)).thenRun(() -> {
|
for (int x = bx; x <= tx; x++) {
|
||||||
for (int x = bx & 15; x <= (tx & 15); x++) {
|
for (int z = bz; z <= tz; z++) {
|
||||||
for (int z = bz & 15; z <= (tz & 15); z++) {
|
map.saveBlocks(newWorld, 256, cbx + x, cbz + z, relX, relZ);
|
||||||
map.saveBlocks(oldWorld, 256, cxx + x, czz + z, relX, relZ);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}).withFinalAction(() -> {
|
||||||
}, () -> {
|
|
||||||
for (Entry<PlotLoc, BaseBlock[]> entry : map.allBlocks.entrySet()) {
|
for (Entry<PlotLoc, BaseBlock[]> entry : map.allBlocks.entrySet()) {
|
||||||
PlotLoc loc = entry.getKey();
|
PlotLoc loc = entry.getKey();
|
||||||
BaseBlock[] blocks = entry.getValue();
|
BaseBlock[] blocks = entry.getValue();
|
||||||
@ -250,17 +249,17 @@ public class BukkitRegionManager extends RegionManager {
|
|||||||
}
|
}
|
||||||
queue.setCompleteTask(() -> {
|
queue.setCompleteTask(() -> {
|
||||||
//map.restoreBlocks(newWorld, 0, 0);
|
//map.restoreBlocks(newWorld, 0, 0);
|
||||||
map.restoreEntities((World) newPos.getWorld(), relX, relZ);
|
map.restoreEntities(Bukkit.getWorld(newPos.getWorldName()), relX, relZ);
|
||||||
TaskManager.runTask(whenDone);
|
TaskManager.runTask(whenDone);
|
||||||
});
|
});
|
||||||
queue.enqueue();
|
queue.enqueue();
|
||||||
}, 5);
|
});
|
||||||
return true;
|
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 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 p1x = pos1.getX();
|
||||||
final int p1z = pos1.getZ();
|
final int p1z = pos1.getZ();
|
||||||
@ -278,137 +277,123 @@ public class BukkitRegionManager extends RegionManager {
|
|||||||
chunks.add(BlockVector2.at(x, z));
|
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) {
|
int x = chunk.getX();
|
||||||
xxb2 = p1x - 1;
|
int z = chunk.getZ();
|
||||||
checkX1 = true;
|
int xxb = x << 4;
|
||||||
} else {
|
int zzb = z << 4;
|
||||||
xxb2 = xxb;
|
int xxt = xxb + 15;
|
||||||
}
|
int zzt = zzb + 15;
|
||||||
boolean checkX2 = false;
|
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
|
||||||
int xxt2;
|
AugmentedUtils.bypass(ignoreAugment,
|
||||||
if (x == tcx) {
|
() -> queue.regenChunkSafe(chunk.getX(), chunk.getZ()));
|
||||||
xxt2 = p2x + 1;
|
return;
|
||||||
checkX2 = true;
|
}
|
||||||
} else {
|
boolean checkX1 = false;
|
||||||
xxt2 = xxt;
|
|
||||||
}
|
int xxb2;
|
||||||
boolean checkZ1 = false;
|
|
||||||
int zzb2;
|
if (x == bcx) {
|
||||||
if (z == bcz) {
|
xxb2 = p1x - 1;
|
||||||
zzb2 = p1z - 1;
|
checkX1 = true;
|
||||||
checkZ1 = true;
|
} else {
|
||||||
} else {
|
xxb2 = xxb;
|
||||||
zzb2 = zzb;
|
}
|
||||||
}
|
boolean checkX2 = false;
|
||||||
boolean checkZ2 = false;
|
int xxt2;
|
||||||
int zzt2;
|
if (x == tcx) {
|
||||||
if (z == tcz) {
|
xxt2 = p2x + 1;
|
||||||
zzt2 = p2z + 1;
|
checkX2 = true;
|
||||||
checkZ2 = true;
|
} else {
|
||||||
} else {
|
xxt2 = xxt;
|
||||||
zzt2 = zzt;
|
}
|
||||||
}
|
boolean checkZ1 = false;
|
||||||
final ContentMap map = new ContentMap();
|
int zzb2;
|
||||||
if (checkX1) {
|
if (z == bcz) {
|
||||||
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); //
|
zzb2 = p1z - 1;
|
||||||
}
|
checkZ1 = true;
|
||||||
if (checkX2) {
|
} else {
|
||||||
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); //
|
zzb2 = zzb;
|
||||||
}
|
}
|
||||||
if (checkZ1) {
|
boolean checkZ2 = false;
|
||||||
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); //
|
int zzt2;
|
||||||
}
|
if (z == tcz) {
|
||||||
if (checkZ2) {
|
zzt2 = p2z + 1;
|
||||||
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); //
|
checkZ2 = true;
|
||||||
}
|
} else {
|
||||||
if (checkX1 && checkZ1) {
|
zzt2 = zzt;
|
||||||
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); //
|
}
|
||||||
}
|
final ContentMap map = new ContentMap();
|
||||||
if (checkX2 && checkZ1) {
|
if (checkX1) {
|
||||||
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ?
|
map.saveRegion(world, xxb, xxb2, zzb2, zzt2); //
|
||||||
}
|
}
|
||||||
if (checkX1 && checkZ2) {
|
if (checkX2) {
|
||||||
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ?
|
map.saveRegion(world, xxt2, xxt, zzb2, zzt2); //
|
||||||
}
|
}
|
||||||
if (checkX2 && checkZ2) {
|
if (checkZ1) {
|
||||||
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); //
|
map.saveRegion(world, xxb2, xxt2, zzb, zzb2); //
|
||||||
}
|
}
|
||||||
CuboidRegion currentPlotClear = RegionUtil
|
if (checkZ2) {
|
||||||
.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
|
map.saveRegion(world, xxb2, xxt2, zzt2, zzt); //
|
||||||
map.saveEntitiesOut(chunkObj, currentPlotClear);
|
}
|
||||||
AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager
|
if (checkX1 && checkZ1) {
|
||||||
.setChunkInPlotArea(null, new RunnableVal<ScopedQueueCoordinator>() {
|
map.saveRegion(world, xxb, xxb2, zzb, zzb2); //
|
||||||
@Override public void run(ScopedQueueCoordinator value) {
|
}
|
||||||
Location min = value.getMin();
|
if (checkX2 && checkZ1) {
|
||||||
int bx = min.getX();
|
map.saveRegion(world, xxt2, xxt, zzb, zzb2); // ?
|
||||||
int bz = min.getZ();
|
}
|
||||||
for (int x1 = 0; x1 < 16; x1++) {
|
if (checkX1 && checkZ2) {
|
||||||
for (int z1 = 0; z1 < 16; z1++) {
|
map.saveRegion(world, xxb, xxb2, zzt2, zzt); // ?
|
||||||
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
|
}
|
||||||
BaseBlock[] ids = map.allBlocks.get(plotLoc);
|
if (checkX2 && checkZ2) {
|
||||||
if (ids != null) {
|
map.saveRegion(world, xxt2, xxt, zzt2, zzt); //
|
||||||
for (int y = 0;
|
}
|
||||||
y < Math.min(128, ids.length); y++) {
|
CuboidRegion currentPlotClear =
|
||||||
BaseBlock id = ids[y];
|
RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
|
||||||
if (id != null) {
|
map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z),
|
||||||
value.setBlock(x1, y, z1, id);
|
currentPlotClear);
|
||||||
} else {
|
AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager
|
||||||
value.setBlock(x1, y, z1,
|
.setChunkInPlotArea(null, new RunnableVal<ScopedQueueCoordinator>() {
|
||||||
BlockTypes.AIR.getDefaultState());
|
@Override public void run(ScopedQueueCoordinator value) {
|
||||||
}
|
Location min = value.getMin();
|
||||||
}
|
int bx = min.getX();
|
||||||
for (int y = Math.min(128, ids.length);
|
int bz = min.getZ();
|
||||||
y < ids.length; y++) {
|
for (int x1 = 0; x1 < 16; x1++) {
|
||||||
BaseBlock id = ids[y];
|
for (int z1 = 0; z1 < 16; z1++) {
|
||||||
if (id != null) {
|
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
|
||||||
value.setBlock(x1, y, z1, id);
|
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);
|
}, world.getName(), chunk));
|
||||||
});
|
//map.restoreBlocks(worldObj, 0, 0);
|
||||||
}
|
map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0);
|
||||||
if (!chunks.isEmpty()) {
|
}).withFinalAction(whenDone);
|
||||||
TaskManager.runTaskLater(this, TaskTime.ticks(1L));
|
|
||||||
} else {
|
|
||||||
TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,19 +456,22 @@ public class BukkitRegionManager extends RegionManager {
|
|||||||
region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
|
region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
|
||||||
Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome,
|
Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome,
|
||||||
region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
|
region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
|
||||||
final QueueCoordinator queue =
|
final QueueCoordinator queue = PlotSquared.platform().getGlobalBlockQueue()
|
||||||
PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false);
|
.getNewQueue(worldUtil.getWeWorld(world), false);
|
||||||
|
|
||||||
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
|
final int minX = pos1.getX();
|
||||||
@Override public void run(int[] value) {
|
final int minZ = pos1.getZ();
|
||||||
BlockVector2 loc = BlockVector2.at(value[0], value[1]);
|
final int maxX = pos2.getX();
|
||||||
PlotSquared.platform().getChunkManager().loadChunk(world, loc, false)
|
final int maxZ = pos2.getZ();
|
||||||
.thenRun(() -> {
|
queue.setChunkConsumer(blockVector2 -> {
|
||||||
MainUtil.setBiome(world, value[2], value[3], value[4], value[5], biome);
|
final int cx = blockVector2.getX() << 4;
|
||||||
queue.refreshChunk(value[0], value[1]);
|
final int cz = blockVector2.getZ() << 4;
|
||||||
});
|
MainUtil
|
||||||
}
|
.setBiome(world, Math.max(minX, cx), Math.max(minZ, cz), Math.min(maxX, cx + 15),
|
||||||
}, whenDone, 5);
|
Math.min(maxZ, cz + 15), biome);
|
||||||
|
worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world);
|
||||||
|
});
|
||||||
|
queue.enqueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void count(int[] count, Entity entity) {
|
private void count(int[] count, Entity entity) {
|
||||||
|
@ -111,15 +111,18 @@ import java.util.function.IntConsumer;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
@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 String lastString = null;
|
||||||
private static World lastWorld = null;
|
private static World lastWorld = null;
|
||||||
|
|
||||||
private static Player lastPlayer = null;
|
private static Player lastPlayer = null;
|
||||||
private static BukkitPlayer lastPlotPlayer = null;
|
private static BukkitPlayer lastPlotPlayer = null;
|
||||||
|
private final Collection<BlockType> tileEntityTypes = new HashSet<>();
|
||||||
|
|
||||||
@Inject public BukkitUtil(@Nonnull final RegionManager regionManager) {
|
@Inject public BukkitUtil(@Nonnull final RegionManager regionManager) {
|
||||||
super(regionManager);
|
super(regionManager);
|
||||||
@ -139,7 +142,8 @@ import java.util.stream.Stream;
|
|||||||
final Player player = OfflinePlayerUtil.loadPlayer(op);
|
final Player player = OfflinePlayerUtil.loadPlayer(op);
|
||||||
player.loadData();
|
player.loadData();
|
||||||
return new BukkitPlayer(PlotSquared.get().getPlotAreaManager(),
|
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);
|
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.
|
* 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) {
|
public static Location getLocation(final org.bukkit.Location location) {
|
||||||
return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()),
|
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) {
|
public static Location getLocationFull(final org.bukkit.Location location) {
|
||||||
return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()),
|
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(),
|
MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()),
|
||||||
location.getPitch());
|
MathMan.roundInt(location.getZ()), location.getYaw(), location.getPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static org.bukkit.Location getLocation(@Nonnull final Location location) {
|
public static org.bukkit.Location getLocation(@Nonnull final Location location) {
|
||||||
return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), location.getX(),
|
return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(),
|
||||||
location.getY(), location.getZ());
|
location.getX(), location.getY(), location.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static World getWorld(@Nonnull final String string) {
|
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) {
|
public static Location getLocation(@Nonnull final Entity entity) {
|
||||||
final org.bukkit.Location location = entity.getLocation();
|
final org.bukkit.Location location = entity.getLocation();
|
||||||
String world = location.getWorld().getName();
|
String world = location.getWorld().getName();
|
||||||
return Location.at(world, location.getBlockX(), location.getBlockY(),
|
return Location.at(world, location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||||
location.getBlockZ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull public static Location getLocationFull(@Nonnull final Entity entity) {
|
@Nonnull public static Location getLocationFull(@Nonnull final Entity entity) {
|
||||||
@ -336,6 +328,38 @@ import java.util.stream.Stream;
|
|||||||
return BukkitAdapter.adapt(plotBlock.getBlockType());
|
return BukkitAdapter.adapt(plotBlock.getBlockType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ensureLoaded(final String world, final int x, final int z,
|
||||||
|
final Consumer<Chunk> chunkConsumer) {
|
||||||
|
PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true)
|
||||||
|
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ensureLoaded(final Location location, final Consumer<Chunk> chunkConsumer) {
|
||||||
|
PaperLib.getChunkAtAsync(getLocation(location), true)
|
||||||
|
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> void ensureMainThread(final Consumer<T> 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) {
|
@Override public boolean isBlockSame(BlockState block1, BlockState block2) {
|
||||||
if (block1.equals(block2)) {
|
if (block1.equals(block2)) {
|
||||||
return true;
|
return true;
|
||||||
@ -357,8 +381,7 @@ import java.util.stream.Stream;
|
|||||||
return BukkitAdapter.adapt(getWorld(world).getBiome(x, z));
|
return BukkitAdapter.adapt(getWorld(world).getBiome(x, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public void getHighestBlock(@Nonnull final String world, final int x, final int z,
|
||||||
public void getHighestBlock(@Nonnull final String world, final int x, final int z,
|
|
||||||
final IntConsumer result) {
|
final IntConsumer result) {
|
||||||
ensureLoaded(world, x, z, chunk -> {
|
ensureLoaded(world, x, z, chunk -> {
|
||||||
final World bukkitWorld = getWorld(world);
|
final World bukkitWorld = getWorld(world);
|
||||||
@ -437,8 +460,9 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
@Override public Location getSpawn(@Nonnull final String world) {
|
@Override public Location getSpawn(@Nonnull final String world) {
|
||||||
final org.bukkit.Location temp = getWorld(world).getSpawnLocation();
|
final org.bukkit.Location temp = getWorld(world).getSpawnLocation();
|
||||||
return Location.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(),
|
return Location
|
||||||
temp.getYaw(), temp.getPitch());
|
.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(),
|
||||||
|
temp.getPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void setSpawn(@Nonnull final Location location) {
|
@Override public void setSpawn(@Nonnull final Location location) {
|
||||||
@ -518,7 +542,8 @@ import java.util.stream.Stream;
|
|||||||
@Nonnull final BiomeType biomeType) {
|
@Nonnull final BiomeType biomeType) {
|
||||||
final World world = getWorld(worldName);
|
final World world = getWorld(worldName);
|
||||||
if (world == null) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
final Biome biome = BukkitAdapter.adapt(biomeType);
|
final Biome biome = BukkitAdapter.adapt(biomeType);
|
||||||
@ -536,6 +561,10 @@ import java.util.stream.Stream;
|
|||||||
return new BukkitWorld(Bukkit.getWorld(world));
|
return new BukkitWorld(Bukkit.getWorld(world));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void refreshChunk(int x, int z, String world) {
|
||||||
|
Bukkit.getWorld(world).refreshChunk(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getBlock(@Nonnull final Location location, final Consumer<BlockState> result) {
|
public void getBlock(@Nonnull final Location location, final Consumer<BlockState> result) {
|
||||||
ensureLoaded(location, chunk -> {
|
ensureLoaded(location, chunk -> {
|
||||||
@ -571,8 +600,7 @@ import java.util.stream.Stream;
|
|||||||
Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel);
|
Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public Set<com.sk89q.worldedit.world.entity.EntityType> getTypesInCategory(
|
||||||
public Set<com.sk89q.worldedit.world.entity.EntityType> getTypesInCategory(
|
|
||||||
final String category) {
|
final String category) {
|
||||||
final Collection<Class<?>> allowedInterfaces = new HashSet<>();
|
final Collection<Class<?>> allowedInterfaces = new HashSet<>();
|
||||||
switch (category) {
|
switch (category) {
|
||||||
@ -653,7 +681,6 @@ import java.util.stream.Stream;
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Collection<BlockType> tileEntityTypes = new HashSet<>();
|
|
||||||
@Override public Collection<BlockType> getTileEntityTypes() {
|
@Override public Collection<BlockType> getTileEntityTypes() {
|
||||||
if (this.tileEntityTypes.isEmpty()) {
|
if (this.tileEntityTypes.isEmpty()) {
|
||||||
// Categories
|
// Categories
|
||||||
@ -665,44 +692,21 @@ import java.util.stream.Stream;
|
|||||||
// Add these from strings
|
// Add these from strings
|
||||||
Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace",
|
Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace",
|
||||||
"brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest",
|
"brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest",
|
||||||
"command_block", "end_gateway", "hopper", "jigsaw", "jubekox",
|
"command_block", "end_gateway", "hopper", "jigsaw", "jubekox", "lectern",
|
||||||
"lectern", "note_block", "black_shulker_box", "blue_shulker_box",
|
"note_block", "black_shulker_box", "blue_shulker_box", "brown_shulker_box",
|
||||||
"brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box",
|
"cyan_shulker_box", "gray_shulker_box", "green_shulker_box",
|
||||||
"light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box",
|
"light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box",
|
||||||
"magenta_shulker_box", "orange_shulker_box", "pink_shulker_box",
|
"magenta_shulker_box", "orange_shulker_box", "pink_shulker_box",
|
||||||
"purple_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box",
|
"purple_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box",
|
||||||
"yellow_shulker_box", "smoker", "structure_block", "structure_void")
|
"yellow_shulker_box", "smoker", "structure_block", "structure_void")
|
||||||
.map(BlockTypes::get)
|
.map(BlockTypes::get).filter(Objects::nonNull).forEach(tileEntityTypes::add);
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.forEach(tileEntityTypes::add);
|
|
||||||
}
|
}
|
||||||
return this.tileEntityTypes;
|
return this.tileEntityTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public int getTileEntityCount(String world, BlockVector2 chunk) {
|
||||||
public int getTileEntityCount(String world, BlockVector2 chunk) {
|
|
||||||
return Bukkit.getWorld(world).getChunkAt(chunk.getBlockX(), chunk.getBlockZ())
|
return Bukkit.getWorld(world).getChunkAt(chunk.getBlockX(), chunk.getBlockZ())
|
||||||
.getTileEntities().length;
|
.getTileEntities().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ensureLoaded(final String world, final int x, final int z,
|
|
||||||
final Consumer<Chunk> chunkConsumer) {
|
|
||||||
PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true)
|
|
||||||
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ensureLoaded(final Location location, final Consumer<Chunk> chunkConsumer) {
|
|
||||||
PaperLib.getChunkAtAsync(getLocation(location), true)
|
|
||||||
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> void ensureMainThread(final Consumer<T> consumer, final T value) {
|
|
||||||
if (Bukkit.isPrimaryThread()) {
|
|
||||||
consumer.accept(value);
|
|
||||||
} else {
|
|
||||||
Bukkit.getScheduler()
|
|
||||||
.runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> consumer.accept(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ import com.plotsquared.core.util.MainUtil;
|
|||||||
import com.plotsquared.core.util.Permissions;
|
import com.plotsquared.core.util.Permissions;
|
||||||
import com.plotsquared.core.util.task.RunnableVal2;
|
import com.plotsquared.core.util.task.RunnableVal2;
|
||||||
import com.plotsquared.core.util.task.RunnableVal3;
|
import com.plotsquared.core.util.task.RunnableVal3;
|
||||||
|
import com.plotsquared.core.util.task.TaskManager;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@ -91,7 +93,7 @@ public class Clear extends Command {
|
|||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
boolean result = plot.clear(true, false, () -> {
|
boolean result = plot.clear(true, false, () -> {
|
||||||
plot.unlink();
|
plot.unlink();
|
||||||
this.blockQueue.addEmptyTask(() -> {
|
TaskManager.runTask(() -> {
|
||||||
plot.removeRunning();
|
plot.removeRunning();
|
||||||
// If the state changes, then mark it as no longer done
|
// If the state changes, then mark it as no longer done
|
||||||
if (DoneFlag.isDone(plot)) {
|
if (DoneFlag.isDone(plot)) {
|
||||||
|
@ -70,20 +70,17 @@ public class Template extends SubCommand {
|
|||||||
private final YamlConfiguration worldConfiguration;
|
private final YamlConfiguration worldConfiguration;
|
||||||
private final File worldFile;
|
private final File worldFile;
|
||||||
private final SetupUtils setupUtils;
|
private final SetupUtils setupUtils;
|
||||||
private final GlobalBlockQueue globalBlockQueue;
|
|
||||||
private final WorldUtil worldUtil;
|
private final WorldUtil worldUtil;
|
||||||
|
|
||||||
@Inject public Template(@Nonnull final PlotAreaManager plotAreaManager,
|
@Inject public Template(@Nonnull final PlotAreaManager plotAreaManager,
|
||||||
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
|
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
|
||||||
@WorldFile @Nonnull final File worldFile,
|
@WorldFile @Nonnull final File worldFile,
|
||||||
@Nonnull final SetupUtils setupUtils,
|
@Nonnull final SetupUtils setupUtils,
|
||||||
@Nonnull final GlobalBlockQueue globalBlockQueue,
|
|
||||||
@Nonnull final WorldUtil worldUtil) {
|
@Nonnull final WorldUtil worldUtil) {
|
||||||
this.plotAreaManager = plotAreaManager;
|
this.plotAreaManager = plotAreaManager;
|
||||||
this.worldConfiguration = worldConfiguration;
|
this.worldConfiguration = worldConfiguration;
|
||||||
this.worldFile = worldFile;
|
this.worldFile = worldFile;
|
||||||
this.setupUtils = setupUtils;
|
this.setupUtils = setupUtils;
|
||||||
this.globalBlockQueue = globalBlockQueue;
|
|
||||||
this.worldUtil = worldUtil;
|
this.worldUtil = worldUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +213,7 @@ public class Template extends SubCommand {
|
|||||||
.worldName(world);
|
.worldName(world);
|
||||||
|
|
||||||
this.setupUtils.setupWorld(builder);
|
this.setupUtils.setupWorld(builder);
|
||||||
this.globalBlockQueue.addEmptyTask(() -> {
|
TaskManager.runTask(() -> {
|
||||||
MainUtil.sendMessage(player, "Done!");
|
MainUtil.sendMessage(player, "Done!");
|
||||||
player.teleport(this.worldUtil.getSpawn(world), TeleportCause.COMMAND);
|
player.teleport(this.worldUtil.getSpawn(world), TeleportCause.COMMAND);
|
||||||
});
|
});
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.plotsquared.core.generator;
|
package com.plotsquared.core.generator;
|
||||||
|
|
||||||
import com.plotsquared.core.PlotSquared;
|
|
||||||
import com.plotsquared.core.configuration.Settings;
|
import com.plotsquared.core.configuration.Settings;
|
||||||
import com.plotsquared.core.location.Direction;
|
import com.plotsquared.core.location.Direction;
|
||||||
import com.plotsquared.core.location.Location;
|
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.BlockUtil;
|
||||||
import com.plotsquared.core.util.MathMan;
|
import com.plotsquared.core.util.MathMan;
|
||||||
import com.plotsquared.core.util.RegionManager;
|
import com.plotsquared.core.util.RegionManager;
|
||||||
|
import com.plotsquared.core.util.task.TaskManager;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
@ -92,7 +92,8 @@ public class ClassicPlotManager extends SquarePlotManager {
|
|||||||
.equals(classicPlotWorld.CLAIMED_WALL_BLOCK)) {
|
.equals(classicPlotWorld.CLAIMED_WALL_BLOCK)) {
|
||||||
setWall(plot.getId(), classicPlotWorld.WALL_BLOCK.toPattern());
|
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) {
|
public boolean setFloor(PlotId plotId, Pattern blocks) {
|
||||||
|
@ -510,7 +510,7 @@ public class HybridUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blockQueue.addEmptyTask(() -> TaskManager.runTaskLater(task, TaskTime.seconds(1L)));
|
TaskManager.runTaskLater(task, TaskTime.seconds(1L));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,16 @@
|
|||||||
*/
|
*/
|
||||||
package com.plotsquared.core.inject.factory;
|
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;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public interface QueueCoordinatorFactory {
|
public interface ChunkCoordinatorBuilderFactory {
|
||||||
|
|
||||||
@Nonnull QueueCoordinator create();
|
@Inject @Nonnull ChunkCoordinatorBuilder create(
|
||||||
|
@Assisted @NotNull ChunkCoordinatorFactory chunkCoordinatorFactory);
|
||||||
|
|
||||||
}
|
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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<BlockVector2> chunkConsumer,
|
||||||
|
@NotNull @Assisted final World world,
|
||||||
|
@NotNull @Assisted final Collection<BlockVector2> requestedChunks,
|
||||||
|
@NotNull @Assisted final Runnable whenDone,
|
||||||
|
@NotNull @Assisted final Consumer<Throwable> throwableConsumer);
|
||||||
|
|
||||||
|
}
|
@ -965,7 +965,7 @@ public class Plot {
|
|||||||
manager.claimPlot(current);
|
manager.claimPlot(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blockQueue.addEmptyTask(run);
|
TaskManager.runTask(run);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Plot current = queue.poll();
|
Plot current = queue.poll();
|
||||||
@ -1061,12 +1061,10 @@ public class Plot {
|
|||||||
current.setMerged(merged);
|
current.setMerged(merged);
|
||||||
}
|
}
|
||||||
if (createSign) {
|
if (createSign) {
|
||||||
blockQueue.addEmptyTask(() -> {
|
TaskManager.runTaskAsync(() -> {
|
||||||
TaskManager.runTaskAsync(() -> {
|
for (Plot current : plots) {
|
||||||
for (Plot current : plots) {
|
current.setSign(MainUtil.getName(current.getOwnerAbs()));
|
||||||
current.setSign(MainUtil.getName(current.getOwnerAbs()));
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (createRoad) {
|
if (createRoad) {
|
||||||
@ -1687,7 +1685,8 @@ public class Plot {
|
|||||||
* This should not need to be called
|
* This should not need to be called
|
||||||
*/
|
*/
|
||||||
public void refreshChunks() {
|
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<BlockVector2> chunks = new HashSet<>();
|
HashSet<BlockVector2> chunks = new HashSet<>();
|
||||||
for (CuboidRegion region : Plot.this.getRegions()) {
|
for (CuboidRegion region : Plot.this.getRegions()) {
|
||||||
for (int x = region.getMinimumPoint().getX() >> 4;
|
for (int x = region.getMinimumPoint().getX() >> 4;
|
||||||
@ -1695,7 +1694,7 @@ public class Plot {
|
|||||||
for (int z = region.getMinimumPoint().getZ() >> 4;
|
for (int z = region.getMinimumPoint().getZ() >> 4;
|
||||||
z <= region.getMaximumPoint().getZ() >> 4; z++) {
|
z <= region.getMaximumPoint().getZ() >> 4; z++) {
|
||||||
if (chunks.add(BlockVector2.at(x, 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;
|
return;
|
||||||
}
|
}
|
||||||
Location location = manager.getSignLoc(this);
|
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(),
|
queue.setBlock(location.getX(), location.getY(), location.getZ(),
|
||||||
BlockTypes.AIR.getDefaultState());
|
BlockTypes.AIR.getDefaultState());
|
||||||
queue.enqueue();
|
queue.enqueue();
|
||||||
|
@ -31,7 +31,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
|||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -39,7 +38,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator {
|
public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator {
|
||||||
|
|
||||||
@Getter private final PlotArea area;
|
private final PlotArea area;
|
||||||
|
|
||||||
public AreaBoundDelegateQueueCoordinator(@Nonnull final PlotArea area,
|
public AreaBoundDelegateQueueCoordinator(@Nonnull final PlotArea area,
|
||||||
@Nullable final QueueCoordinator parent) {
|
@Nullable final QueueCoordinator parent) {
|
||||||
@ -47,6 +46,10 @@ public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator
|
|||||||
this.area = Objects.requireNonNull(area);
|
this.area = Objects.requireNonNull(area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PlotArea getArea() {
|
||||||
|
return this.area;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
|
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
|
||||||
if (area.contains(x, z)) {
|
if (area.contains(x, z)) {
|
||||||
return super.setBlock(x, y, z, id);
|
return super.setBlock(x, y, z, id);
|
||||||
|
@ -33,22 +33,23 @@ import com.sk89q.worldedit.world.World;
|
|||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public abstract class BasicQueueCoordinator extends QueueCoordinator {
|
public abstract class BasicQueueCoordinator extends QueueCoordinator {
|
||||||
|
|
||||||
private final World world;
|
private final World world;
|
||||||
@Getter private final ConcurrentHashMap<BlockVector2, LocalChunk> blockChunks =
|
private final ConcurrentHashMap<BlockVector2, LocalChunk> blockChunks =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
private long modified;
|
private long modified;
|
||||||
private LocalChunk lastWrappedChunk;
|
private LocalChunk lastWrappedChunk;
|
||||||
private int lastX = Integer.MIN_VALUE;
|
private int lastX = Integer.MIN_VALUE;
|
||||||
private int lastZ = Integer.MIN_VALUE;
|
private int lastZ = Integer.MIN_VALUE;
|
||||||
@Getter private boolean settingBiomes = false;
|
private boolean settingBiomes = false;
|
||||||
@Getter private boolean settingTiles = false;
|
private boolean settingTiles = false;
|
||||||
|
private Consumer<BlockVector2> consumer = null;
|
||||||
|
|
||||||
private GlobalBlockQueue globalBlockQueue;
|
private GlobalBlockQueue globalBlockQueue;
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
|
|||||||
return setBlock(x, y, z, id.toBaseBlock());
|
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);
|
LocalChunk chunk = getChunk(x >> 4, z >> 4);
|
||||||
for (int y = 0; y < 256; y++) {
|
for (int y = 0; y < 256; y++) {
|
||||||
chunk.setBiome(x & 15, y, z & 15, biomeType);
|
chunk.setBiome(x & 15, y, z & 15, biomeType);
|
||||||
@ -113,17 +114,37 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
|
|||||||
return true;
|
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);
|
LocalChunk chunk = getChunk(x >> 4, z >> 4);
|
||||||
chunk.setTile(x, y, z, tag);
|
chunk.setTile(x, y, z, tag);
|
||||||
settingTiles = true;
|
settingTiles = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public boolean isSettingTiles() {
|
||||||
|
return this.settingTiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<BlockVector2, LocalChunk> getBlockChunks() {
|
||||||
|
return this.blockChunks;
|
||||||
|
}
|
||||||
|
|
||||||
public final void setChunk(LocalChunk chunk) {
|
public final void setChunk(LocalChunk chunk) {
|
||||||
this.blockChunks.put(BlockVector2.at(chunk.getX(), chunk.getZ()), chunk);
|
this.blockChunks.put(BlockVector2.at(chunk.getX(), chunk.getZ()), chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final Consumer<BlockVector2> getChunkConsumer() {
|
||||||
|
return this.consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setChunkConsumer(Consumer<BlockVector2> consumer) {
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
private LocalChunk getChunk(final int chunkX, final int chunkZ) {
|
private LocalChunk getChunk(final int chunkX, final int chunkZ) {
|
||||||
if (chunkX != lastX || chunkZ != lastZ) {
|
if (chunkX != lastX || chunkZ != lastZ) {
|
||||||
lastX = chunkX;
|
lastX = chunkX;
|
||||||
|
@ -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();
|
||||||
|
}
|
@ -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<BlockVector2> requestedChunks = new LinkedList<>();
|
||||||
|
private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace;
|
||||||
|
private World world;
|
||||||
|
private Consumer<BlockVector2> 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<BlockVector2> 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<BlockVector2> 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<BlockVector2> 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<Throwable> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -27,11 +27,14 @@ package com.plotsquared.core.queue;
|
|||||||
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class DelegateQueueCoordinator extends QueueCoordinator {
|
public class DelegateQueueCoordinator extends QueueCoordinator {
|
||||||
|
|
||||||
private final QueueCoordinator parent;
|
private final QueueCoordinator parent;
|
||||||
@ -111,4 +114,8 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
|
|||||||
@Override public void setCompleteTask(Runnable whenDone) {
|
@Override public void setCompleteTask(Runnable whenDone) {
|
||||||
parent.setCompleteTask(whenDone);
|
parent.setCompleteTask(whenDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void setChunkConsumer(Consumer<BlockVector2> consumer) {
|
||||||
|
parent.setChunkConsumer(consumer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@ package com.plotsquared.core.queue;
|
|||||||
|
|
||||||
import com.plotsquared.core.PlotSquared;
|
import com.plotsquared.core.PlotSquared;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -37,7 +35,7 @@ import java.util.concurrent.ConcurrentLinkedDeque;
|
|||||||
public class GlobalBlockQueue {
|
public class GlobalBlockQueue {
|
||||||
|
|
||||||
private final ConcurrentLinkedDeque<QueueCoordinator> activeQueues;
|
private final ConcurrentLinkedDeque<QueueCoordinator> activeQueues;
|
||||||
@Getter @Setter private QueueProvider provider;
|
private QueueProvider provider;
|
||||||
|
|
||||||
public GlobalBlockQueue(QueueProvider provider) {
|
public GlobalBlockQueue(QueueProvider provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
@ -54,6 +52,14 @@ public class GlobalBlockQueue {
|
|||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueueProvider getProvider() {
|
||||||
|
return this.provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQueueProvider(QueueProvider provider) {
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO Documentation needed.
|
* TODO Documentation needed.
|
||||||
*
|
*
|
||||||
|
@ -6,18 +6,17 @@ import com.sk89q.jnbt.CompoundTag;
|
|||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class LocalChunk {
|
public class LocalChunk {
|
||||||
@Getter private final BasicQueueCoordinator parent;
|
private final BasicQueueCoordinator parent;
|
||||||
@Getter private final int z;
|
private final int x;
|
||||||
@Getter private final int x;
|
private final int z;
|
||||||
|
|
||||||
@Getter private final BaseBlock[][] baseblocks;
|
private final BaseBlock[][] baseblocks;
|
||||||
@Getter private final BiomeType[][] biomes;
|
private final BiomeType[][] biomes;
|
||||||
@Getter private final HashMap<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
private final HashMap<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||||
|
|
||||||
public LocalChunk(BasicQueueCoordinator parent, int x, int z) {
|
public LocalChunk(BasicQueueCoordinator parent, int x, int z) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
@ -27,6 +26,30 @@ public class LocalChunk {
|
|||||||
biomes = new BiomeType[16][];
|
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<BlockVector3, CompoundTag> getTiles() {
|
||||||
|
return this.tiles;
|
||||||
|
}
|
||||||
|
|
||||||
public void setBiome(final int x, final int y, final int z, final BiomeType biomeType) {
|
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 i = MainUtil.CACHE_I[y][x][z];
|
||||||
final int j = MainUtil.CACHE_J[y][x][z];
|
final int j = MainUtil.CACHE_J[y][x][z];
|
||||||
|
@ -31,20 +31,21 @@ import com.plotsquared.core.location.Location;
|
|||||||
import com.plotsquared.core.util.PatternUtil;
|
import com.plotsquared.core.util.PatternUtil;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import lombok.Getter;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public abstract class QueueCoordinator {
|
public abstract class QueueCoordinator {
|
||||||
|
|
||||||
@Getter @Setter private boolean forceSync = false;
|
private boolean forceSync = false;
|
||||||
@Getter @Setter @Nullable private Object chunkObject;
|
@Nullable private Object chunkObject;
|
||||||
|
|
||||||
@Inject private GlobalBlockQueue blockQueue;
|
@Inject private GlobalBlockQueue blockQueue;
|
||||||
|
|
||||||
@ -63,6 +64,22 @@ public abstract class QueueCoordinator {
|
|||||||
|
|
||||||
public abstract void setModified(long modified);
|
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.
|
* 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 setCompleteTask(Runnable whenDone);
|
||||||
|
|
||||||
|
public abstract void setChunkConsumer(Consumer<BlockVector2> consumer);
|
||||||
|
|
||||||
public void setCuboid(Location pos1, Location pos2, BlockState block) {
|
public void setCuboid(Location pos1, Location pos2, BlockState block) {
|
||||||
int yMin = Math.min(pos1.getY(), pos2.getY());
|
int yMin = Math.min(pos1.getY(), pos2.getY());
|
||||||
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
|
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
|
||||||
|
@ -26,10 +26,12 @@
|
|||||||
package com.plotsquared.core.util;
|
package com.plotsquared.core.util;
|
||||||
|
|
||||||
import com.plotsquared.core.PlotSquared;
|
import com.plotsquared.core.PlotSquared;
|
||||||
|
import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
|
||||||
import com.plotsquared.core.location.Location;
|
import com.plotsquared.core.location.Location;
|
||||||
import com.plotsquared.core.plot.Plot;
|
import com.plotsquared.core.plot.Plot;
|
||||||
import com.plotsquared.core.plot.PlotArea;
|
import com.plotsquared.core.plot.PlotArea;
|
||||||
import com.plotsquared.core.plot.PlotManager;
|
import com.plotsquared.core.plot.PlotManager;
|
||||||
|
import com.plotsquared.core.queue.ChunkCoordinatorBuilder;
|
||||||
import com.plotsquared.core.queue.QueueCoordinator;
|
import com.plotsquared.core.queue.QueueCoordinator;
|
||||||
import com.plotsquared.core.util.task.RunnableVal;
|
import com.plotsquared.core.util.task.RunnableVal;
|
||||||
import com.plotsquared.core.util.task.TaskManager;
|
import com.plotsquared.core.util.task.TaskManager;
|
||||||
@ -55,7 +57,8 @@ public abstract class RegionManager {
|
|||||||
public static RegionManager manager = null;
|
public static RegionManager manager = null;
|
||||||
private final ChunkManager chunkManager;
|
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;
|
this.chunkManager = chunkManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,12 +98,13 @@ public abstract class RegionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TaskManager.getPlatformImplementation().objectTask(chunks, new RunnableVal<BlockVector2>() {
|
TaskManager.getPlatformImplementation()
|
||||||
@Override public void run(BlockVector2 value) {
|
.objectTask(chunks, new RunnableVal<BlockVector2>() {
|
||||||
chunkManager.loadChunk(world, value, false).thenRun(() -> task.run(value));
|
@Override public void run(BlockVector2 value) {
|
||||||
}
|
chunkManager.loadChunk(world, value, false).thenRun(() -> task.run(value));
|
||||||
}).thenAccept(ignore ->
|
}
|
||||||
TaskManager.getPlatformImplementation().taskLater(whenDone, TaskTime.ticks(1L)));
|
}).thenAccept(ignore -> TaskManager.getPlatformImplementation()
|
||||||
|
.taskLater(whenDone, TaskTime.ticks(1L)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +118,8 @@ public abstract class WorldUtil {
|
|||||||
|
|
||||||
public abstract com.sk89q.worldedit.world.World getWeWorld(String world);
|
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,
|
public void upload(@Nonnull final Plot plot, UUID uuid, String file,
|
||||||
RunnableVal<URL> whenDone) {
|
RunnableVal<URL> whenDone) {
|
||||||
plot.getHome(home -> MainUtil.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
|
plot.getHome(home -> MainUtil.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
|
||||||
|
Loading…
Reference in New Issue
Block a user