mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-03-04 00:59:43 +01:00
fix: allow queues to not generate chunks (#4599)
- initially apply to regenallroads - additionally add a 10s timeout for requesting a chunk before resubmitting it to the queue - addresses #4310
This commit is contained in:
parent
d4f10422e3
commit
eb0d854870
@ -30,6 +30,8 @@ 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 com.sk89q.worldedit.world.World;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@ -41,6 +43,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@ -55,6 +58,8 @@ import java.util.function.Consumer;
|
|||||||
**/
|
**/
|
||||||
public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitChunkCoordinator.class.getSimpleName());
|
||||||
|
|
||||||
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
|
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
|
||||||
|
|
||||||
private final Queue<BlockVector2> requestedChunks;
|
private final Queue<BlockVector2> requestedChunks;
|
||||||
@ -70,6 +75,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
|||||||
private final AtomicInteger expectedSize;
|
private final AtomicInteger expectedSize;
|
||||||
private final AtomicInteger loadingChunks = new AtomicInteger();
|
private final AtomicInteger loadingChunks = new AtomicInteger();
|
||||||
private final boolean forceSync;
|
private final boolean forceSync;
|
||||||
|
private final boolean shouldGen;
|
||||||
|
|
||||||
private int batchSize;
|
private int batchSize;
|
||||||
private PlotSquaredTask task;
|
private PlotSquaredTask task;
|
||||||
@ -87,7 +93,8 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
|||||||
@Assisted final @NonNull Consumer<Throwable> throwableConsumer,
|
@Assisted final @NonNull Consumer<Throwable> throwableConsumer,
|
||||||
@Assisted("unloadAfter") final boolean unloadAfter,
|
@Assisted("unloadAfter") final boolean unloadAfter,
|
||||||
@Assisted final @NonNull Collection<ProgressSubscriber> progressSubscribers,
|
@Assisted final @NonNull Collection<ProgressSubscriber> progressSubscribers,
|
||||||
@Assisted("forceSync") final boolean forceSync
|
@Assisted("forceSync") final boolean forceSync,
|
||||||
|
@Assisted("shouldGen") final boolean shouldGen
|
||||||
) {
|
) {
|
||||||
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
|
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
|
||||||
this.availableChunks = new LinkedBlockingQueue<>();
|
this.availableChunks = new LinkedBlockingQueue<>();
|
||||||
@ -103,6 +110,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
|||||||
this.bukkitWorld = Bukkit.getWorld(world.getName());
|
this.bukkitWorld = Bukkit.getWorld(world.getName());
|
||||||
this.progressSubscribers.addAll(progressSubscribers);
|
this.progressSubscribers.addAll(progressSubscribers);
|
||||||
this.forceSync = forceSync;
|
this.forceSync = forceSync;
|
||||||
|
this.shouldGen = shouldGen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -212,18 +220,22 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
|||||||
* Requests a batch of chunks to be loaded
|
* Requests a batch of chunks to be loaded
|
||||||
*/
|
*/
|
||||||
private void requestBatch() {
|
private void requestBatch() {
|
||||||
BlockVector2 chunk;
|
for (int i = 0; i < this.batchSize && this.requestedChunks.peek() != 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
|
||||||
|
final BlockVector2 chunk = this.requestedChunks.poll();
|
||||||
loadingChunks.incrementAndGet();
|
loadingChunks.incrementAndGet();
|
||||||
PaperLib
|
PaperLib
|
||||||
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true)
|
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), shouldGen, true)
|
||||||
|
.completeOnTimeout(null, 10L, TimeUnit.SECONDS)
|
||||||
.whenComplete((chunkObject, throwable) -> {
|
.whenComplete((chunkObject, throwable) -> {
|
||||||
loadingChunks.decrementAndGet();
|
loadingChunks.decrementAndGet();
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
throwable.printStackTrace();
|
LOGGER.error("Failed to load chunk {}", chunk, throwable);
|
||||||
// We want one less because this couldn't be processed
|
// We want one less because this couldn't be processed
|
||||||
this.expectedSize.decrementAndGet();
|
this.expectedSize.decrementAndGet();
|
||||||
|
} else if (chunkObject == null) {
|
||||||
|
LOGGER.warn("Timed out awaiting chunk load {}", chunk);
|
||||||
|
this.requestedChunks.offer(chunk);
|
||||||
} else if (PlotSquared.get().isMainThread(Thread.currentThread())) {
|
} else if (PlotSquared.get().isMainThread(Thread.currentThread())) {
|
||||||
this.processChunk(chunkObject);
|
this.processChunk(chunkObject);
|
||||||
} else {
|
} else {
|
||||||
|
@ -238,6 +238,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
|
|||||||
.unloadAfter(isUnloadAfter())
|
.unloadAfter(isUnloadAfter())
|
||||||
.withProgressSubscribers(getProgressSubscribers())
|
.withProgressSubscribers(getProgressSubscribers())
|
||||||
.forceSync(isForceSync())
|
.forceSync(isForceSync())
|
||||||
|
.shouldGen(isShouldGen())
|
||||||
.build();
|
.build();
|
||||||
return super.enqueue();
|
return super.enqueue();
|
||||||
}
|
}
|
||||||
|
@ -432,6 +432,7 @@ public class HybridUtils {
|
|||||||
if (!UPDATE) {
|
if (!UPDATE) {
|
||||||
Iterator<BlockVector2> iter = chunks.iterator();
|
Iterator<BlockVector2> iter = chunks.iterator();
|
||||||
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
||||||
|
queue.setShouldGen(false);
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
BlockVector2 chunk = iter.next();
|
BlockVector2 chunk = iter.next();
|
||||||
iter.remove();
|
iter.remove();
|
||||||
@ -474,6 +475,7 @@ public class HybridUtils {
|
|||||||
Iterator<BlockVector2> iterator = chunks.iterator();
|
Iterator<BlockVector2> iterator = chunks.iterator();
|
||||||
if (chunks.size() >= 32) {
|
if (chunks.size() >= 32) {
|
||||||
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
||||||
|
queue.setShouldGen(false);
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
final BlockVector2 chunk = iterator.next();
|
final BlockVector2 chunk = iterator.next();
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
@ -487,6 +489,7 @@ public class HybridUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
||||||
|
queue.setShouldGen(false);
|
||||||
while (!chunks.isEmpty()) {
|
while (!chunks.isEmpty()) {
|
||||||
final BlockVector2 chunk = iterator.next();
|
final BlockVector2 chunk = iterator.next();
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
@ -502,7 +505,6 @@ public class HybridUtils {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
|
||||||
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
|
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
|
||||||
BlockVector2 loc = iterator.next();
|
BlockVector2 loc = iterator.next();
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
@ -510,7 +512,8 @@ public class HybridUtils {
|
|||||||
"Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)",
|
"Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)",
|
||||||
area.getWorldHash(),
|
area.getWorldHash(),
|
||||||
loc.getX(),
|
loc.getX(),
|
||||||
loc.getZ()
|
loc.getZ(),
|
||||||
|
e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TaskManager.runTaskLater(task, TaskTime.seconds(1L));
|
TaskManager.runTaskLater(task, TaskTime.seconds(1L));
|
||||||
@ -558,7 +561,7 @@ public class HybridUtils {
|
|||||||
try {
|
try {
|
||||||
plotworld.setupSchematics();
|
plotworld.setupSchematics();
|
||||||
} catch (SchematicHandler.UnsupportedFormatException e) {
|
} catch (SchematicHandler.UnsupportedFormatException e) {
|
||||||
e.printStackTrace();
|
LOGGER.error(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -40,7 +40,8 @@ public interface ChunkCoordinatorFactory {
|
|||||||
final @NonNull Consumer<Throwable> throwableConsumer,
|
final @NonNull Consumer<Throwable> throwableConsumer,
|
||||||
@Assisted("unloadAfter") final boolean unloadAfter,
|
@Assisted("unloadAfter") final boolean unloadAfter,
|
||||||
final @NonNull Collection<ProgressSubscriber> progressSubscribers,
|
final @NonNull Collection<ProgressSubscriber> progressSubscribers,
|
||||||
@Assisted("forceSync") final boolean forceSync
|
@Assisted("forceSync") final boolean forceSync,
|
||||||
|
@Assisted("shouldGen") final boolean shouldGen
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ public class ChunkCoordinatorBuilder {
|
|||||||
private int initialBatchSize = Settings.QUEUE.INITIAL_BATCH_SIZE;
|
private int initialBatchSize = Settings.QUEUE.INITIAL_BATCH_SIZE;
|
||||||
private boolean unloadAfter = true;
|
private boolean unloadAfter = true;
|
||||||
private boolean forceSync = false;
|
private boolean forceSync = false;
|
||||||
|
private boolean shouldGen = true;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ChunkCoordinatorBuilder(@NonNull ChunkCoordinatorFactory chunkCoordinatorFactory) {
|
public ChunkCoordinatorBuilder(@NonNull ChunkCoordinatorFactory chunkCoordinatorFactory) {
|
||||||
@ -203,6 +204,19 @@ public class ChunkCoordinatorBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
|
||||||
|
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
|
||||||
|
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
|
||||||
|
*
|
||||||
|
* @param shouldGen should generate new chunks or not
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public @NonNull ChunkCoordinatorBuilder shouldGen(final boolean shouldGen) {
|
||||||
|
this.shouldGen = shouldGen;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public @NonNull ChunkCoordinatorBuilder withProgressSubscriber(ProgressSubscriber progressSubscriber) {
|
public @NonNull ChunkCoordinatorBuilder withProgressSubscriber(ProgressSubscriber progressSubscriber) {
|
||||||
this.progressSubscribers.add(progressSubscriber);
|
this.progressSubscribers.add(progressSubscriber);
|
||||||
return this;
|
return this;
|
||||||
@ -234,7 +248,8 @@ public class ChunkCoordinatorBuilder {
|
|||||||
this.throwableConsumer,
|
this.throwableConsumer,
|
||||||
this.unloadAfter,
|
this.unloadAfter,
|
||||||
this.progressSubscribers,
|
this.progressSubscribers,
|
||||||
this.forceSync
|
this.forceSync,
|
||||||
|
this.shouldGen
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
|
|||||||
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
this.setForceSync(parent.isForceSync());
|
this.setForceSync(parent.isForceSync());
|
||||||
|
this.setShouldGen(parent.isShouldGen());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ public abstract class QueueCoordinator {
|
|||||||
|
|
||||||
private final AtomicBoolean enqueued = new AtomicBoolean();
|
private final AtomicBoolean enqueued = new AtomicBoolean();
|
||||||
private boolean forceSync = false;
|
private boolean forceSync = false;
|
||||||
|
private boolean shouldGen = true;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Object chunkObject;
|
private Object chunkObject;
|
||||||
@SuppressWarnings({"unused", "FieldCanBeLocal"})
|
@SuppressWarnings({"unused", "FieldCanBeLocal"})
|
||||||
@ -110,6 +111,30 @@ public abstract class QueueCoordinator {
|
|||||||
this.forceSync = forceSync;
|
this.forceSync = forceSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
|
||||||
|
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
|
||||||
|
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
|
||||||
|
*
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public boolean isShouldGen() {
|
||||||
|
return shouldGen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
|
||||||
|
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
|
||||||
|
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
|
||||||
|
*
|
||||||
|
* @param shouldGen should generate new chunks or not
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public void setShouldGen(boolean shouldGen) {
|
||||||
|
this.shouldGen = shouldGen;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Chunk Object set to the queue
|
* Get the Chunk Object set to the queue
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user