From 5ce7eae7c012f3905619e4e435754e325c842a82 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 14 Sep 2025 08:11:47 -0500 Subject: [PATCH] Fix DH world gen missing structures --- .../BatchGenerationEnvironment.java | 35 ++++++++---- .../step/AbstractWorldGenStep.java | 54 ++++++++++++++++++ .../worldGeneration/step/StepBiomes.java | 45 +++++++-------- .../worldGeneration/step/StepFeatures.java | 20 ++++++- .../worldGeneration/step/StepNoise.java | 21 +++++-- .../step/StepStructureReference.java | 22 ++++++-- .../step/StepStructureStart.java | 55 ++++++------------- .../worldGeneration/step/StepSurface.java | 20 ++++++- 8 files changed, 186 insertions(+), 86 deletions(-) create mode 100644 common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java index 46e982f15..98392ecc5 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java @@ -32,6 +32,7 @@ import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.objects.EventTimer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; @@ -84,6 +85,7 @@ import net.minecraft.world.level.chunk.ChunkStatus; import org.jetbrains.annotations.Nullable; #else import net.minecraft.world.level.chunk.status.ChunkStatus; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; #endif @@ -174,6 +176,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv // constructors // //==============// + @NotNull public static final ImmutableMap WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP; public static final int MAX_WORLD_GEN_CHUNK_BORDER_NEEDED; @@ -205,11 +208,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv builder.put(EDhApiWorldGenerationStep.LIGHT, 0); WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP = builder.build(); - // TODO this is a test to see if the additional boarder is actually necessary or not. - // If world generators end up having infinite loops or other unexplained issues, - // this should be set back to the commented out logic below + // in James' testing as of 2025-09-13 a border here of 2 + // and a getChunkPosToGenerateStream() radius of 14 provided more accurate + // structure generation, however it also caused extreme server lag + // a border of 0 here and a getChunkPosToGenerateStream() radius of 8 provided + // good-enough structure generation while not lagging the server MAX_WORLD_GEN_CHUNK_BORDER_NEEDED = 0; - //MAX_WORLD_GEN_CHUNK_BORDER_NEEDED = WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.values().stream().mapToInt(Integer::intValue).max().getAsInt(); } public BatchGenerationEnvironment(IDhServerLevel serverlevel) @@ -387,7 +391,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv CompletableFuture.allOf(readFutures).join(); // future chain for generation - return CompletableFuture.runAsync(() -> + return CompletableFuture.runAsync(() -> + { + try { // offset 1 chunk in both X and Z direction so we can generate an even number of chunks wide // while still submitting an odd number width to MC's internal generators @@ -410,10 +416,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv int centerZ = refPosZ + radius + zOffset; // get/create the list of chunks we're going to generate - IEmptyChunkRetrievalFunc fallbackFunc = + IEmptyChunkRetrievalFunc fallbackFunc = (chunkPosX, chunkPosZ) -> Objects.requireNonNull( - generatedChunkByDhPos.get(new DhChunkPos(chunkPosX, chunkPosZ)), - () -> String.format("Requested chunk [%d, %d] unavailable during world generation", chunkPosX, chunkPosZ)); + generatedChunkByDhPos.get(new DhChunkPos(chunkPosX, chunkPosZ)), + () -> String.format("Requested chunk [%d, %d] unavailable during world generation", chunkPosX, chunkPosZ)); ArrayGridList regionChunks = new ArrayGridList<>( refSize, @@ -435,7 +441,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv // this method shouldn't be necessary since we're passing in a pre-populated // list of chunks, but just in case fallbackFunc - ); + ); lightGetterAdaptor.setRegion(region); genEvent.threadedParam.makeStructFeat(region, this.params); @@ -524,7 +530,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv genEvent.threadedParam.perf.recordEvent(genEvent.timer); PREF_LOGGER.debugInc(genEvent.timer.toString()); } - }, executor); + } + catch (Exception e) + { + EVENT_LOGGER.error("Unexpected error during world gen for min chunk pos ["+genEvent.minPos+"], error: ["+e.getMessage()+"].", e); + } + }, executor); } /** @param extraRadius in both the positive and negative directions */ private static Stream getChunkPosToGenerateStream(int genMinX, int genMinZ, int width, int extraRadius) @@ -1078,8 +1089,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv } } private static ArrayGridList GetCutoutFrom(ArrayGridList total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); } - //private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, MaxBorderNeeded - WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); } - private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, 0); } + private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); } + //private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, 0); } @Override diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java new file mode 100644 index 000000000..fb8b41977 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java @@ -0,0 +1,54 @@ +package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; + +import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; +import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ProtoChunk; + +import java.util.ArrayList; +import java.util.List; + +#if MC_VER <= MC_1_20_4 +import net.minecraft.world.level.chunk.ChunkStatus; +#else +import net.minecraft.world.level.chunk.status.ChunkStatus; +#endif + +public abstract class AbstractWorldGenStep +{ + public abstract void generateGroup( + ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, + ArrayGridList chunkWrappers); + + public abstract ChunkStatus getChunkStatus(); + + + + /** @return the list of chunks that have an earlier status and can be generated */ + protected ArrayList getChunksToGenerate(List chunkWrappers) + { + ArrayList chunksToGenerate = new ArrayList<>(); + + for (ChunkWrapper chunkWrapper : chunkWrappers) + { + ChunkAccess chunk = chunkWrapper.getChunk(); + if (chunkWrapper.getStatus().isOrAfter(this.getChunkStatus())) + { + // this chunk has already generated this step + continue; + } + else if (chunk instanceof ProtoChunk) + { + chunkWrapper.trySetStatus(this.getChunkStatus()); + chunksToGenerate.add(chunk); + } + } + + return chunksToGenerate; + } + + + +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java index 2192d5baa..8a0bcb819 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java @@ -20,12 +20,13 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; import java.util.ArrayList; -import java.util.List; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; +import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; @@ -40,39 +41,35 @@ import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus; #endif -public final class StepBiomes +public final class StepBiomes extends AbstractWorldGenStep { - public static final ChunkStatus STATUS = ChunkStatus.BIOMES; - private final BatchGenerationEnvironment environment; + public static final ChunkStatus STATUS = ChunkStatus.BIOMES; + + + + //=============// + // constructor // + //=============// public StepBiomes(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; } + //==================// + // abstract methods // + //==================// + + @Override + public ChunkStatus getChunkStatus() { return STATUS; } + + @Override public void generateGroup( - ThreadedParameters tParams, WorldGenRegion worldGenRegion, - List chunkWrappers) + ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, + ArrayGridList chunkWrappers) { - - ArrayList chunksToDo = new ArrayList<>(); - - for (ChunkWrapper chunkWrapper : chunkWrappers) - { - ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunkWrapper.getStatus().isOrAfter(STATUS)) - { - // this chunk has already generated this step - continue; - } - else if (chunk instanceof ProtoChunk) - { - chunkWrapper.trySetStatus(STATUS); - chunksToDo.add(chunk); - } - } - + ArrayList chunksToDo = this.getChunksToGenerate(chunkWrappers); for (ChunkAccess chunk : chunksToDo) { #if MC_VER < MC_1_18_2 diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java index ef9c845c6..6830462e0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java @@ -37,8 +37,10 @@ import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus; #endif +import java.util.ConcurrentModificationException; -public final class StepFeatures + +public final class StepFeatures extends AbstractWorldGenStep { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); @@ -48,10 +50,22 @@ public final class StepFeatures + //=============// + // constructor // + //=============// + public StepFeatures(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; } + //==================// + // abstract methods // + //==================// + + @Override + public ChunkStatus getChunkStatus() { return STATUS; } + + @Override public void generateGroup( ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, ArrayGridList chunkWrappers) @@ -88,6 +102,10 @@ public final class StepFeatures Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter()); } + catch (ConcurrentModificationException e) // ReportedException + { + // TODO + } catch (Exception e) { LOGGER.warn("Unexpected issue when generating features for chunk at pos ["+chunkWrapper.getChunkPos()+"], error: ["+e.getMessage()+"].", e); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java index e75a7bdde..49a1b5bcf 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java @@ -26,6 +26,8 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; +import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.chunk.ChunkAccess; @@ -41,7 +43,7 @@ import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus; #endif -public final class StepNoise +public final class StepNoise extends AbstractWorldGenStep { private static final ChunkStatus STATUS = ChunkStatus.NOISE; @@ -49,15 +51,26 @@ public final class StepNoise + //=============// + // constructor // + //=============// + public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; } + //==================// + // abstract methods // + //==================// + + @Override + public ChunkStatus getChunkStatus() { return STATUS; } + + @Override public void generateGroup( - ThreadedParameters tParams, WorldGenRegion worldGenRegion, - List chunkWrappers) + ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, + ArrayGridList chunkWrappers) { - ArrayList chunksToDo = new ArrayList<>(); for (ChunkWrapper chunkWrapper : chunkWrappers) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java index 3bca6f20f..cba8dc7cc 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java @@ -26,6 +26,8 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; +import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; @@ -37,7 +39,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus; #endif -public final class StepStructureReference +public final class StepStructureReference extends AbstractWorldGenStep { private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES; @@ -45,15 +47,26 @@ public final class StepStructureReference + //=============// + // constructor // + //=============// + public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; } + //==================// + // abstract methods // + //==================// + + @Override + public ChunkStatus getChunkStatus() { return STATUS; } + + @Override public void generateGroup( - ThreadedParameters tParams, WorldGenRegion worldGenRegion, - List chunkWrappers) + ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, + ArrayGridList chunkWrappers) { - ArrayList chunksToDo = new ArrayList(); for (ChunkWrapper chunkWrapper : chunkWrappers) @@ -67,6 +80,7 @@ public final class StepStructureReference else if (chunk instanceof ProtoChunk) { chunkWrapper.trySetStatus(STATUS); + chunksToDo.add(chunk); } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java index 702e71f55..c424b7d06 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java @@ -27,7 +27,9 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.Level; @@ -42,7 +44,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus; #endif -public final class StepStructureStart +public final class StepStructureStart extends AbstractWorldGenStep { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS; @@ -52,42 +54,27 @@ public final class StepStructureStart + //=============// + // constructor // + //=============// + public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; } - public static class StructStartCorruptedException extends RuntimeException - { - private static final long serialVersionUID = -8987434342051563358L; - - public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) - { - super("StructStartCorruptedException"); - super.initCause(e); - fillInStackTrace(); - } - - } + //==================// + // abstract methods // + //==================// + @Override + public ChunkStatus getChunkStatus() { return STATUS; } + + @Override public void generateGroup( - ThreadedParameters tParams, WorldGenRegion worldGenRegion, - List chunkWrappers) throws InterruptedException + ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, + ArrayGridList chunkWrappers) { - ArrayList chunksToDo = new ArrayList<>(); - - for (ChunkWrapper chunkWrapper : chunkWrappers) - { - ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunkWrapper.getStatus().isOrAfter(STATUS)) - { - // this chunk has already generated this step - continue; - } - else if (chunk instanceof ProtoChunk) - { - chunkWrapper.trySetStatus(STATUS); - } - } + ArrayList chunksToDo = this.getChunksToGenerate(chunkWrappers); #if MC_VER < MC_1_19_2 if (this.environment.params.worldGenSettings.generateFeatures()) @@ -101,12 +88,6 @@ public final class StepStructureStart #endif for (ChunkAccess chunk : chunksToDo) { - // System.out.println("StepStructureStart: "+chunk.getPos()); - - // there are a few cases where the structure generator call may lock up (either due to teleporting or leaving the world). - // hopefully allowing interrupts here will prevent that from happening. - BatchGenerationEnvironment.throwIfThreadInterrupted(); - // hopefully this shouldn't cause any performance issues (this step is generally quite quick so hopefully it should be fine) // and should prevent some concurrency issues STRUCTURE_PLACEMENT_LOCK.lock(); @@ -151,8 +132,6 @@ public final class StepStructureStart { // the structure logic failed again, log it and move on LOGGER.error("Unable to create structure starts for " + chunk.getPos() + ". This is an error with MC's world generation. Ignoring and continuing generation. Error: " + secondEx.getMessage()); // don't log the full stack trace since it is long and will generally end up in MC's code - - //throw new StepStructureStart.StructStartCorruptedException(secondEx); } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java index b6662d020..4f6ef551a 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java @@ -26,6 +26,8 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; +import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; import net.minecraft.server.level.WorldGenRegion; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; @@ -37,7 +39,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus; #endif -public final class StepSurface +public final class StepSurface extends AbstractWorldGenStep { private static final ChunkStatus STATUS = ChunkStatus.SURFACE; @@ -45,13 +47,25 @@ public final class StepSurface + //=============// + // constructor // + //=============// + public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; } + //==================// + // abstract methods // + //==================// + + @Override + public ChunkStatus getChunkStatus() { return STATUS; } + + @Override public void generateGroup( - ThreadedParameters tParams, WorldGenRegion worldGenRegion, - List chunkWrappers) + ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion, + ArrayGridList chunkWrappers) { ArrayList chunksToDo = new ArrayList<>();