Skip to content

Commit eb0d854

Browse files
authored
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
1 parent d4f1042 commit eb0d854

File tree

7 files changed

+68
-10
lines changed

7 files changed

+68
-10
lines changed

Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import com.sk89q.worldedit.math.BlockVector2;
3131
import com.sk89q.worldedit.world.World;
3232
import io.papermc.lib.PaperLib;
33+
import org.apache.logging.log4j.LogManager;
34+
import org.apache.logging.log4j.Logger;
3335
import org.bukkit.Bukkit;
3436
import org.bukkit.Chunk;
3537
import org.bukkit.plugin.Plugin;
@@ -41,6 +43,7 @@
4143
import java.util.List;
4244
import java.util.Queue;
4345
import java.util.concurrent.LinkedBlockingQueue;
46+
import java.util.concurrent.TimeUnit;
4447
import java.util.concurrent.atomic.AtomicInteger;
4548
import java.util.function.Consumer;
4649

@@ -55,6 +58,8 @@
5558
**/
5659
public final class BukkitChunkCoordinator extends ChunkCoordinator {
5760

61+
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitChunkCoordinator.class.getSimpleName());
62+
5863
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
5964

6065
private final Queue<BlockVector2> requestedChunks;
@@ -70,6 +75,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
7075
private final AtomicInteger expectedSize;
7176
private final AtomicInteger loadingChunks = new AtomicInteger();
7277
private final boolean forceSync;
78+
private final boolean shouldGen;
7379

7480
private int batchSize;
7581
private PlotSquaredTask task;
@@ -87,7 +93,8 @@ private BukkitChunkCoordinator(
8793
@Assisted final @NonNull Consumer<Throwable> throwableConsumer,
8894
@Assisted("unloadAfter") final boolean unloadAfter,
8995
@Assisted final @NonNull Collection<ProgressSubscriber> progressSubscribers,
90-
@Assisted("forceSync") final boolean forceSync
96+
@Assisted("forceSync") final boolean forceSync,
97+
@Assisted("shouldGen") final boolean shouldGen
9198
) {
9299
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
93100
this.availableChunks = new LinkedBlockingQueue<>();
@@ -103,6 +110,7 @@ private BukkitChunkCoordinator(
103110
this.bukkitWorld = Bukkit.getWorld(world.getName());
104111
this.progressSubscribers.addAll(progressSubscribers);
105112
this.forceSync = forceSync;
113+
this.shouldGen = shouldGen;
106114
}
107115

108116
@Override
@@ -212,18 +220,22 @@ public void run() {
212220
* Requests a batch of chunks to be loaded
213221
*/
214222
private void requestBatch() {
215-
BlockVector2 chunk;
216-
for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) {
223+
for (int i = 0; i < this.batchSize && this.requestedChunks.peek() != null; i++) {
217224
// This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent
225+
final BlockVector2 chunk = this.requestedChunks.poll();
218226
loadingChunks.incrementAndGet();
219227
PaperLib
220-
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true)
228+
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), shouldGen, true)
229+
.completeOnTimeout(null, 10L, TimeUnit.SECONDS)
221230
.whenComplete((chunkObject, throwable) -> {
222231
loadingChunks.decrementAndGet();
223232
if (throwable != null) {
224-
throwable.printStackTrace();
233+
LOGGER.error("Failed to load chunk {}", chunk, throwable);
225234
// We want one less because this couldn't be processed
226235
this.expectedSize.decrementAndGet();
236+
} else if (chunkObject == null) {
237+
LOGGER.warn("Timed out awaiting chunk load {}", chunk);
238+
this.requestedChunks.offer(chunk);
227239
} else if (PlotSquared.get().isMainThread(Thread.currentThread())) {
228240
this.processChunk(chunkObject);
229241
} else {

Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ public boolean enqueue() {
238238
.unloadAfter(isUnloadAfter())
239239
.withProgressSubscribers(getProgressSubscribers())
240240
.forceSync(isForceSync())
241+
.shouldGen(isShouldGen())
241242
.build();
242243
return super.enqueue();
243244
}

Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ public void run() {
432432
if (!UPDATE) {
433433
Iterator<BlockVector2> iter = chunks.iterator();
434434
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
435+
queue.setShouldGen(false);
435436
while (iter.hasNext()) {
436437
BlockVector2 chunk = iter.next();
437438
iter.remove();
@@ -474,6 +475,7 @@ public void run() {
474475
Iterator<BlockVector2> iterator = chunks.iterator();
475476
if (chunks.size() >= 32) {
476477
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
478+
queue.setShouldGen(false);
477479
for (int i = 0; i < 32; i++) {
478480
final BlockVector2 chunk = iterator.next();
479481
iterator.remove();
@@ -487,6 +489,7 @@ public void run() {
487489
return null;
488490
}
489491
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
492+
queue.setShouldGen(false);
490493
while (!chunks.isEmpty()) {
491494
final BlockVector2 chunk = iterator.next();
492495
iterator.remove();
@@ -502,15 +505,15 @@ public void run() {
502505
return;
503506
}
504507
} catch (Exception e) {
505-
e.printStackTrace();
506508
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
507509
BlockVector2 loc = iterator.next();
508510
iterator.remove();
509511
LOGGER.error(
510512
"Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)",
511513
area.getWorldHash(),
512514
loc.getX(),
513-
loc.getZ()
515+
loc.getZ(),
516+
e
514517
);
515518
}
516519
TaskManager.runTaskLater(task, TaskTime.seconds(1L));
@@ -558,7 +561,7 @@ public boolean setupRoadSchematic(Plot plot) {
558561
try {
559562
plotworld.setupSchematics();
560563
} catch (SchematicHandler.UnsupportedFormatException e) {
561-
e.printStackTrace();
564+
LOGGER.error(e);
562565
}
563566
});
564567
});

Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ public interface ChunkCoordinatorFactory {
4040
final @NonNull Consumer<Throwable> throwableConsumer,
4141
@Assisted("unloadAfter") final boolean unloadAfter,
4242
final @NonNull Collection<ProgressSubscriber> progressSubscribers,
43-
@Assisted("forceSync") final boolean forceSync
43+
@Assisted("forceSync") final boolean forceSync,
44+
@Assisted("shouldGen") final boolean shouldGen
4445
);
4546

4647
}

Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class ChunkCoordinatorBuilder {
5252
private int initialBatchSize = Settings.QUEUE.INITIAL_BATCH_SIZE;
5353
private boolean unloadAfter = true;
5454
private boolean forceSync = false;
55+
private boolean shouldGen = true;
5556

5657
@Inject
5758
public ChunkCoordinatorBuilder(@NonNull ChunkCoordinatorFactory chunkCoordinatorFactory) {
@@ -203,6 +204,19 @@ public ChunkCoordinatorBuilder(@NonNull ChunkCoordinatorFactory chunkCoordinator
203204
return this;
204205
}
205206

207+
/**
208+
* Set whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
209+
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
210+
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
211+
*
212+
* @param shouldGen should generate new chunks or not
213+
* @since TODO
214+
*/
215+
public @NonNull ChunkCoordinatorBuilder shouldGen(final boolean shouldGen) {
216+
this.shouldGen = shouldGen;
217+
return this;
218+
}
219+
206220
public @NonNull ChunkCoordinatorBuilder withProgressSubscriber(ProgressSubscriber progressSubscriber) {
207221
this.progressSubscribers.add(progressSubscriber);
208222
return this;
@@ -234,7 +248,8 @@ public ChunkCoordinatorBuilder(@NonNull ChunkCoordinatorFactory chunkCoordinator
234248
this.throwableConsumer,
235249
this.unloadAfter,
236250
this.progressSubscribers,
237-
this.forceSync
251+
this.forceSync,
252+
this.shouldGen
238253
);
239254
}
240255

Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public DelegateQueueCoordinator(QueueCoordinator parent) {
5151

5252
if (parent != null) {
5353
this.setForceSync(parent.isForceSync());
54+
this.setShouldGen(parent.isShouldGen());
5455
}
5556
}
5657

Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public abstract class QueueCoordinator {
4545

4646
private final AtomicBoolean enqueued = new AtomicBoolean();
4747
private boolean forceSync = false;
48+
private boolean shouldGen = true;
4849
@Nullable
4950
private Object chunkObject;
5051
@SuppressWarnings({"unused", "FieldCanBeLocal"})
@@ -110,6 +111,30 @@ public void setForceSync(boolean forceSync) {
110111
this.forceSync = forceSync;
111112
}
112113

114+
115+
/**
116+
* Get whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
117+
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
118+
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
119+
*
120+
* @since TODO
121+
*/
122+
public boolean isShouldGen() {
123+
return shouldGen;
124+
}
125+
126+
/**
127+
* Set whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
128+
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
129+
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
130+
*
131+
* @param shouldGen should generate new chunks or not
132+
* @since TODO
133+
*/
134+
public void setShouldGen(boolean shouldGen) {
135+
this.shouldGen = shouldGen;
136+
}
137+
113138
/**
114139
* Get the Chunk Object set to the queue
115140
*

0 commit comments

Comments
 (0)