= getMaxLightLevel());
- }
-
-
-
- }
-
- public static class LightGetterAdaptor implements LightChunkGetter {
- private final BlockGetter heightGetter;
- public LightedWorldGenRegion genRegion = null;
- final boolean shouldReturnNull;
- public LightGetterAdaptor(BlockGetter heightAccessor) {
- this.heightGetter = heightAccessor;
- shouldReturnNull = ModAccessorApi.get(IStarlightAccessor.class)!=null;
- }
- public void setRegion(LightedWorldGenRegion region) {
- genRegion = region;
- }
-
- @Override
- public BlockGetter getChunkForLighting(int chunkX, int chunkZ) {
- if (genRegion == null) throw new IllegalStateException("World Gen region has not been set!");
- // May be null
- return genRegion.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, false);
- }
- @Override
- public BlockGetter getLevel() {
- return shouldReturnNull ? null : (genRegion!=null ? genRegion : heightGetter);
- }
- }
-
- public static class WorldGenLevelLightEngine extends LevelLightEngine {
- public static final int MAX_SOURCE_LEVEL = 15;
- public static final int LIGHT_SECTION_PADDING = 1;
- @Nullable
- public final BlockLightEngine blockEngine;
- @Nullable
- public final SkyLightEngine skyEngine;
-
- public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
- super(genRegion, false, false);
- this.blockEngine = new BlockLightEngine(genRegion);
- this.skyEngine = new SkyLightEngine(genRegion);
- }
-
- @Override
- public void checkBlock(BlockPos blockPos) {
- if (this.blockEngine != null) {
- this.blockEngine.checkBlock(blockPos);
- }
- if (this.skyEngine != null) {
- this.skyEngine.checkBlock(blockPos);
- }
- }
-
- @Override
- public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
- if (this.blockEngine != null) {
- this.blockEngine.onBlockEmissionIncrease(blockPos, i);
- }
- }
-
- @Override
- public boolean hasLightWork() {
- if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
- return true;
- }
- return this.blockEngine != null && this.blockEngine.hasLightWork();
- }
-
- @Override
- public int runUpdates(int i, boolean bl, boolean bl2) {
- if (this.blockEngine != null && this.skyEngine != null) {
- int j = i / 2;
- int k = this.blockEngine.runUpdates(j, bl, bl2);
- int l = i - j + k;
- int m = this.skyEngine.runUpdates(l, bl, bl2);
- if (k == 0 && m > 0) {
- return this.blockEngine.runUpdates(m, bl, bl2);
- }
- return m;
- }
- if (this.blockEngine != null) {
- return this.blockEngine.runUpdates(i, bl, bl2);
- }
- if (this.skyEngine != null) {
- return this.skyEngine.runUpdates(i, bl, bl2);
- }
- return i;
- }
-
- @Override
- public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
- if (this.blockEngine != null) {
- this.blockEngine.updateSectionStatus(sectionPos, bl);
- }
- if (this.skyEngine != null) {
- this.skyEngine.updateSectionStatus(sectionPos, bl);
- }
- }
-
- @Override
- public void enableLightSources(ChunkPos chunkPos, boolean bl) {
- if (this.blockEngine != null) {
- this.blockEngine.enableLightSources(chunkPos, bl);
- }
- if (this.skyEngine != null) {
- this.skyEngine.enableLightSources(chunkPos, bl);
- }
- }
-
- @Override
- public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
- if (lightLayer == LightLayer.BLOCK) {
- if (this.blockEngine == null) {
- return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
- }
- return this.blockEngine;
- }
- if (this.skyEngine == null) {
- return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
- }
- return this.skyEngine;
- }
-
- @Override
- public int getRawBrightness(BlockPos blockPos, int i) {
- int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
- int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
- return Math.max(k, j);
- }
-
- public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
- ChunkPos chunkPos = chunkAccess.getPos();
- chunkAccess.setLightCorrect(false);
-
- LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
- for (int i = 0; i < 16; i++) {
- LevelChunkSection levelChunkSection = levelChunkSections[i];
- if (!LevelChunkSection.isEmpty(levelChunkSection)) {
- updateSectionStatus(SectionPos.of(chunkPos, i), false);
- }
- }
- enableLightSources(chunkPos, true);
- if (needLightBlockUpdate) {
- chunkAccess.getLights().forEach(blockPos ->
- onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
- }
-
- chunkAccess.setLightCorrect(true);
- }
-
- @Override
- public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
- throw new UnsupportedOperationException("This should never be used!");
- }
- @Override
- public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer, boolean bl) {
- if (lightLayer == LightLayer.BLOCK) {
- if (this.blockEngine != null) {
- this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
- }
- } else if (this.skyEngine != null) {
- this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
- }
- }
- @Override
- public void retainData(ChunkPos chunkPos, boolean bl) {
- if (this.blockEngine != null) {
- this.blockEngine.retainData(chunkPos, bl);
- }
- if (this.skyEngine != null) {
- this.skyEngine.retainData(chunkPos, bl);
- }
- }
- }
-
-
-
-
-
-}
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGeneratorWrapper.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGeneratorWrapper.java
index b5b471d78..f27cb9d40 100644
--- a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGeneratorWrapper.java
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGeneratorWrapper.java
@@ -24,135 +24,121 @@ import net.minecraft.world.level.chunk.*;
* @author James Seibel
* @version 11-13-2021
*/
-public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
-{
- public final ServerLevel serverWorld;
- public final LodDimension lodDim;
- public final LodBuilder lodBuilder;
+public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper {
+ public final ServerLevel serverWorld;
+ public final LodDimension lodDim;
+ public final LodBuilder lodBuilder;
- public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
- {
- super(newLodBuilder, newLodDimension, worldWrapper);
+ public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
+ super(newLodBuilder, newLodDimension, worldWrapper);
- lodBuilder = newLodBuilder;
- lodDim = newLodDimension;
- serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
- }
+ lodBuilder = newLodBuilder;
+ lodDim = newLodDimension;
+ serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
+ }
+ /** takes about 2-5 ms */
+ @Override
+ public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode) {
+ generate(pos.getX(), pos.getZ(), generationMode);
+ }
- /** takes about 2-5 ms */
- @Override
- public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
- {
- generate(pos.getX(), pos.getZ(), generationMode);
- }
+ /** takes about 10 - 20 ms */
+ @Override
+ public void generateSurface(AbstractChunkPosWrapper pos) {
+ generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
+ }
+ /**
+ * takes about 15 - 20 ms
+ *
+ */
+ @Override
+ public void generateFeatures(AbstractChunkPosWrapper pos) {
+ generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
+ }
- /** takes about 10 - 20 ms */
- @Override
- public void generateSurface(AbstractChunkPosWrapper pos)
- {
- generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
- }
+ /**
+ * Generates using MC's ServerWorld.
+ *
+ * on pre generated chunks 0 - 1 ms
+ * on un generated chunks 0 - 50 ms
+ * with the median seeming to hover around 15 - 30 ms
+ * and outliers in the 100 - 200 ms range
+ *
+ * Note this should not be multithreaded and does cause server/simulation lag
+ * (Higher lag for generating than loading)
+ */
+ @Override
+ public void generateFull(AbstractChunkPosWrapper pos) {
+ generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
+ }
-
- /**
- * takes about 15 - 20 ms
- *
- */
- @Override
- public void generateFeatures(AbstractChunkPosWrapper pos)
- {
- generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
- }
-
-
- /**
- * Generates using MC's ServerWorld.
- *
- * on pre generated chunks 0 - 1 ms
- * on un generated chunks 0 - 50 ms
- * with the median seeming to hover around 15 - 30 ms
- * and outliers in the 100 - 200 ms range
- *
- * Note this should not be multithreaded and does cause server/simulation lag
- * (Higher lag for generating than loading)
- */
- @Override
- public void generateFull(AbstractChunkPosWrapper pos)
- {
- generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
- }
-
- private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode) {
+ private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode) {
// long t = System.nanoTime();
- ChunkStatus targetStatus;
- switch (generationMode) {
- case NONE:
- return;
- case BIOME_ONLY:
- targetStatus = ChunkStatus.BIOMES;
- break;
- case BIOME_ONLY_SIMULATE_HEIGHT:
- targetStatus = ChunkStatus.NOISE;
- break;
- case SURFACE:
- targetStatus = ChunkStatus.SURFACE;
- break;
- case FEATURES:
- targetStatus = ChunkStatus.FEATURES;
- break;
- case FULL:
- targetStatus = ChunkStatus.FULL;
- break;
- default:
- return;
- }
+ ChunkStatus targetStatus;
+ switch (generationMode) {
+ case NONE:
+ return;
+ case BIOME_ONLY:
+ targetStatus = ChunkStatus.BIOMES;
+ break;
+ case BIOME_ONLY_SIMULATE_HEIGHT:
+ targetStatus = ChunkStatus.NOISE;
+ break;
+ case SURFACE:
+ targetStatus = ChunkStatus.SURFACE;
+ break;
+ case FEATURES:
+ targetStatus = ChunkStatus.FEATURES;
+ break;
+ case FULL:
+ targetStatus = ChunkStatus.FULL;
+ break;
+ default:
+ return;
+ }
- // The bool=true means that we wants to generate chunk, and that the returned ChunkAccess must not be null
+ // The bool=true means that we wants to generate chunk, and that the returned
+ // ChunkAccess must not be null
- ChunkAccess ca = serverWorld.getChunkSource().getChunk(chunkX, chunkZ, targetStatus, true);
- if (ca == null) throw new RuntimeException("This should NEVER be null due to bool being true");
- lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(ca, serverWorld), new LodBuilderConfig(generationMode), false);
+ ChunkAccess ca = serverWorld.getChunkSource().getChunk(chunkX, chunkZ, targetStatus, true);
+ if (ca == null)
+ throw new RuntimeException("This should NEVER be null due to bool being true");
+ lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(ca, serverWorld),
+ new LodBuilderConfig(generationMode), false);
- // long duration = System.nanoTime()-t;
+ // long duration = System.nanoTime()-t;
- // Debug print the duration
- // System.out.println("LodChunkGenFull["+chunkX+","+chunkZ+"]: "+(double)(duration)/1000.);
- }
+ // Debug print the duration
+ // System.out.println("LodChunkGenFull["+chunkX+","+chunkZ+"]:
+ // "+(double)(duration)/1000.);
+ }
-
-
-
-
-
-
- /* TODO: Ask leetom to update chart
- * performance/generation tests related to
+ /*
+ * TODO: Ask leetom to update chart performance/generation tests related to
* serverWorld.getChunk(x, z, ChunkStatus. *** )
-
- true/false is whether they generated blocks or not
- the time is how long it took to generate
-
- ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
- ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
- ChunkStatus.BIOMES 1 - 10 ms false (no height)
- ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
- ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
- ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
- ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
- ChunkStatus.FEATURES 7 - 25 ms true
- ChunkStatus.HEIGHTMAPS 20 - 40 ms true
- ChunkStatus.LIGHT 20 - 40 ms true
- ChunkStatus.FULL 30 - 50 ms true
- ChunkStatus.SPAWN 50 - 80 ms true
-
-
- At this point I would suggest using FEATURES, as it generates snow and trees
- (and any other object that are needed to make biomes distinct)
-
- Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
+ *
+ * true/false is whether they generated blocks or not the time is how long it
+ * took to generate
+ *
+ * ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
+ * ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates
+ * some chunks) ChunkStatus.BIOMES 1 - 10 ms false (no height) ChunkStatus.NOISE
+ * 4 - 15 ms true (all blocks are stone) ChunkStatus.LIQUID_CARVERS 6 - 12 ms
+ * true (no snow/trees, just grass) ChunkStatus.SURFACE 5 - 15 ms true (no
+ * snow/trees, just grass) ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees,
+ * just grass) ChunkStatus.FEATURES 7 - 25 ms true ChunkStatus.HEIGHTMAPS 20 -
+ * 40 ms true ChunkStatus.LIGHT 20 - 40 ms true ChunkStatus.FULL 30 - 50 ms true
+ * ChunkStatus.SPAWN 50 - 80 ms true
+ *
+ *
+ * At this point I would suggest using FEATURES, as it generates snow and trees
+ * (and any other object that are needed to make biomes distinct)
+ *
+ * Otherwise, if snow/trees aren't necessary SURFACE is the next fastest
+ * (although not by much)
*/
}
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/ChunkLoader.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java
similarity index 89%
rename from common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/ChunkLoader.java
rename to common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java
index b19278c5e..ffc69f557 100644
--- a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/ChunkLoader.java
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java
@@ -1,5 +1,5 @@
-package com.seibel.lod.common.wrappers.worldGeneration;
+package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.seibel.lod.core.api.ClientApi;
@@ -28,8 +28,6 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
-
-
import org.apache.logging.log4j.Logger;
public class ChunkLoader {
@@ -75,7 +73,7 @@ public class ChunkLoader {
}
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
}
-
+
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData) {
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
for (int n = 0; n < tagPostProcessings.size(); ++n) {
@@ -87,17 +85,17 @@ public class ChunkLoader {
}
public static ChunkStatus.ChunkType readChunkType(CompoundTag tagLevel) {
- ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
- if (chunkStatus != null) {
- return chunkStatus.getChunkType();
- }
- return ChunkStatus.ChunkType.PROTOCHUNK;
+ ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
+ if (chunkStatus != null) {
+ return chunkStatus.getChunkType();
+ }
+ return ChunkStatus.ChunkType.PROTOCHUNK;
}
- public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine,
- ChunkPos chunkPos, CompoundTag chunkData) {
+ public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine, ChunkPos chunkPos,
+ CompoundTag chunkData) {
CompoundTag tagLevel = chunkData.getCompound("Level");
-
+
ChunkStatus.ChunkType chunkType = readChunkType(tagLevel);
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
return null;
@@ -109,41 +107,43 @@ public class ChunkLoader {
return null;
}
-
- //====================== Read params for making the LevelChunk ============================
+ // ====================== Read params for making the LevelChunk
+ // ============================
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkPos,
level.getLevel().getChunkSource().getGenerator().getBiomeSource(),
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
-
+
UpgradeData upgradeData = tagLevel.contains("UpgradeData", 10)
? new UpgradeData(tagLevel.getCompound("UpgradeData"))
: UpgradeData.EMPTY;
-
+
TickList blockTicks = tagLevel.contains("TileTicks", 9)
? ChunkTickList.create(tagLevel.getList("TileTicks", 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
: new ProtoTickList(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
tagLevel.getList("ToBeTicked", 9));
-
+
TickList liquidTicks = tagLevel.contains("LiquidTicks", 9)
? ChunkTickList.create(tagLevel.getList("LiquidTicks", 10), Registry.FLUID::getKey, Registry.FLUID::get)
: new ProtoTickList(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
tagLevel.getList("LiquidsToBeTicked", 9));
-
+
long inhabitedTime = tagLevel.getLong("InhabitedTime");
-
+
LevelChunkSection[] levelChunkSections = readSections(level, lightEngine, chunkPos, tagLevel);
- //======================== Make the chunk ===========================================
+ // ======================== Make the chunk
+ // ===========================================
LevelChunk chunk = new LevelChunk(level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
liquidTicks, inhabitedTime, levelChunkSections, null);
- //========================== Post setup some chunk data ==============================
+ // ========================== Post setup some chunk data
+ // ==============================
chunk.setLightCorrect(tagLevel.getBoolean("isLightOn"));
readHeightmaps(chunk, tagLevel);
readPostPocessings(chunk, tagLevel);
- //ClientApi.LOGGER.info("Loaded chunk @ "+chunk.getPos());
+ // ClientApi.LOGGER.info("Loaded chunk @ "+chunk.getPos());
return chunk;
}
}
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java
new file mode 100644
index 000000000..6451ffbc8
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java
@@ -0,0 +1,36 @@
+package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
+
+import com.seibel.lod.core.api.ModAccessorApi;
+import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
+
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.LightChunkGetter;
+
+public class LightGetterAdaptor implements LightChunkGetter {
+ private final BlockGetter heightGetter;
+ public LightedWorldGenRegion genRegion = null;
+ final boolean shouldReturnNull;
+
+ public LightGetterAdaptor(BlockGetter heightAccessor) {
+ this.heightGetter = heightAccessor;
+ shouldReturnNull = ModAccessorApi.get(IStarlightAccessor.class) != null;
+ }
+
+ public void setRegion(LightedWorldGenRegion region) {
+ genRegion = region;
+ }
+
+ @Override
+ public BlockGetter getChunkForLighting(int chunkX, int chunkZ) {
+ if (genRegion == null)
+ throw new IllegalStateException("World Gen region has not been set!");
+ // May be null
+ return genRegion.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, false);
+ }
+
+ @Override
+ public BlockGetter getLevel() {
+ return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/LightedWorldGenRegion.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/LightedWorldGenRegion.java
new file mode 100644
index 000000000..089f71e64
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/LightedWorldGenRegion.java
@@ -0,0 +1,207 @@
+package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.jetbrains.annotations.Nullable;
+
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
+import com.seibel.lod.core.api.ClientApi;
+import com.seibel.lod.core.enums.config.LightGenerationMode;
+
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.SectionPos;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.util.Mth;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.LightLayer;
+import net.minecraft.world.level.StructureFeatureManager;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ImposterProtoChunk;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.levelgen.Heightmap;
+import net.minecraft.world.level.levelgen.feature.StructureFeature;
+import net.minecraft.world.level.levelgen.structure.StructureStart;
+import net.minecraft.world.level.lighting.LevelLightEngine;
+
+public class LightedWorldGenRegion extends WorldGenRegion {
+ public final WorldGenLevelLightEngine light;
+ public final LightGenerationMode lightMode;
+ public final EmptyChunkGenerator generator;
+ public final int writeRadius;
+ public final int size;
+ private final ChunkPos firstPos;
+ private final List cache;
+ private final StructureFeatureManager structFeat;
+ Long2ObjectOpenHashMap chunkMap = new Long2ObjectOpenHashMap();
+
+ public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
+ StructureFeatureManager structFeat, List list, ChunkStatus chunkStatus, int i,
+ LightGenerationMode lightMode, EmptyChunkGenerator generator) {
+ super(serverLevel, list);
+ this.lightMode = lightMode;
+ this.firstPos = list.get(0).getPos();
+ this.generator = generator;
+ this.structFeat = structFeat;
+ light = lightEngine;
+ writeRadius = i;
+ cache = list;
+ size = Mth.floor(Math.sqrt(list.size()));
+ }
+
+ @Override
+ public Stream extends StructureStart>> startsForFeature(SectionPos sectionPos,
+ StructureFeature> structureFeature) {
+ return structFeat.startsForFeature(sectionPos, structureFeature);
+ }
+
+ // Skip updating the related tile entities
+ @Override
+ public boolean setBlock(BlockPos blockPos, BlockState blockState, int i, int j) {
+ ChunkAccess chunkAccess = this.getChunk(blockPos);
+ if (chunkAccess instanceof LevelChunk)
+ return true;
+ chunkAccess.setBlockState(blockPos, blockState, false);
+ // This is for post ticking for water on gen and stuff like that. Not enabled
+ // for now.
+ // if (blockState.hasPostProcess(this, blockPos))
+ // this.getChunk(blockPos).markPosForPostprocessing(blockPos);
+ return true;
+ }
+
+ // Skip Dropping the item on destroy
+ @Override
+ public boolean destroyBlock(BlockPos blockPos, boolean bl, @Nullable Entity entity, int i) {
+ BlockState blockState = this.getBlockState(blockPos);
+ if (blockState.isAir()) {
+ return false;
+ }
+ return this.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3, i);
+ }
+
+ // Skip BlockEntity stuff. It aren't really needed
+ @Override
+ public BlockEntity getBlockEntity(BlockPos blockPos) {
+ return null;
+ }
+
+ // Skip BlockEntity stuff. It aren't really needed
+ @Override
+ public boolean addFreshEntity(Entity entity) {
+ return true;
+ }
+
+ // Allays have empty chunks even if it's outside the worldGenRegion
+ // @Override
+ // public boolean hasChunk(int i, int j) {
+ // return true;
+ // }
+
+ // Override to ensure no other mod mixins cause skipping the overrided
+ // getChunk(...)
+ @Override
+ public ChunkAccess getChunk(int i, int j) {
+ return this.getChunk(i, j, ChunkStatus.EMPTY);
+ }
+
+ // Override to ensure no other mod mixins cause skipping the overrided
+ // getChunk(...)
+ @Override
+ public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus) {
+ return this.getChunk(i, j, chunkStatus, true);
+ }
+
+ // Use this instead of super.getChunk() to bypass C2ME concurrency checks
+ private ChunkAccess superGetChunk(int x, int z, ChunkStatus cs) {
+ int k = x - firstPos.x;
+ int l = z - firstPos.z;
+ return cache.get(k + l * size);
+ }
+
+ // Use this instead of super.hasChunk() to bypass C2ME concurrency checks
+ private boolean superHasChunk(int x, int z) {
+ int k = x - firstPos.x;
+ int l = z - firstPos.z;
+ return l >= 0 && l < size && k >= 0 && k < size;
+ }
+
+ // Allow creating empty chunks even if it's outside the worldGenRegion
+ @Override
+ @Nullable
+ public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl) {
+ ChunkAccess chunk = getChunkAccess(i, j, chunkStatus, bl);
+ if (chunk instanceof LevelChunk) {
+ chunk = new ImposterProtoChunk((LevelChunk) chunk);
+ }
+ return chunk;
+ }
+
+ private static ChunkStatus debugTriggeredForStatus = null;
+
+ private ChunkAccess getChunkAccess(int i, int j, ChunkStatus chunkStatus, boolean bl) {
+ ChunkAccess chunk = superHasChunk(i, j) ? superGetChunk(i, j, ChunkStatus.EMPTY) : null;
+ if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus)) {
+ return chunk;
+ }
+ if (!bl)
+ return null;
+ if (chunk == null) {
+ chunk = chunkMap.get(ChunkPos.asLong(i, j));
+ if (chunk == null) {
+ chunk = generator.generate(i, j);
+ if (chunk == null)
+ throw new NullPointerException("The provided generator should not return null!");
+ chunkMap.put(ChunkPos.asLong(i, j), chunk);
+ }
+ }
+ if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
+ ClientApi.LOGGER.info("WorldGen requiring " + chunkStatus
+ + " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
+ debugTriggeredForStatus = chunkStatus;
+ }
+ return chunk;
+ }
+
+ // Override force use of my own light engine
+ @Override
+ public LevelLightEngine getLightEngine() {
+ return light;
+ }
+
+ // Override force use of my own light engine
+ @Override
+ public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
+ if (lightMode != LightGenerationMode.FAST) {
+ return light.getLayerListener(lightLayer).getLightValue(blockPos);
+ }
+ if (lightLayer == LightLayer.BLOCK)
+ return 0;
+ BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
+ return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
+ }
+
+ // Override force use of my own light engine
+ @Override
+ public int getRawBrightness(BlockPos blockPos, int i) {
+ if (lightMode != LightGenerationMode.FAST) {
+ return light.getRawBrightness(blockPos, i);
+ }
+ BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
+ return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
+ }
+
+ // Override force use of my own light engine
+ @Override
+ public boolean canSeeSky(BlockPos blockPos) {
+ return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
+ }
+
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/WorldGenLevelLightEngine.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/WorldGenLevelLightEngine.java
new file mode 100644
index 000000000..488f5788a
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/WorldGenLevelLightEngine.java
@@ -0,0 +1,164 @@
+package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
+
+import org.jetbrains.annotations.Nullable;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.SectionPos;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.LightLayer;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.DataLayer;
+import net.minecraft.world.level.chunk.LevelChunkSection;
+import net.minecraft.world.level.lighting.BlockLightEngine;
+import net.minecraft.world.level.lighting.LayerLightEventListener;
+import net.minecraft.world.level.lighting.LevelLightEngine;
+import net.minecraft.world.level.lighting.SkyLightEngine;
+
+public class WorldGenLevelLightEngine extends LevelLightEngine {
+ public static final int MAX_SOURCE_LEVEL = 15;
+ public static final int LIGHT_SECTION_PADDING = 1;
+ @Nullable
+ public final BlockLightEngine blockEngine;
+ @Nullable
+ public final SkyLightEngine skyEngine;
+
+ public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
+ super(genRegion, false, false);
+ this.blockEngine = new BlockLightEngine(genRegion);
+ this.skyEngine = new SkyLightEngine(genRegion);
+ }
+
+ @Override
+ public void checkBlock(BlockPos blockPos) {
+ if (this.blockEngine != null) {
+ this.blockEngine.checkBlock(blockPos);
+ }
+ if (this.skyEngine != null) {
+ this.skyEngine.checkBlock(blockPos);
+ }
+ }
+
+ @Override
+ public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
+ if (this.blockEngine != null) {
+ this.blockEngine.onBlockEmissionIncrease(blockPos, i);
+ }
+ }
+
+ @Override
+ public boolean hasLightWork() {
+ if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
+ return true;
+ }
+ return this.blockEngine != null && this.blockEngine.hasLightWork();
+ }
+
+ @Override
+ public int runUpdates(int i, boolean bl, boolean bl2) {
+ if (this.blockEngine != null && this.skyEngine != null) {
+ int j = i / 2;
+ int k = this.blockEngine.runUpdates(j, bl, bl2);
+ int l = i - j + k;
+ int m = this.skyEngine.runUpdates(l, bl, bl2);
+ if (k == 0 && m > 0) {
+ return this.blockEngine.runUpdates(m, bl, bl2);
+ }
+ return m;
+ }
+ if (this.blockEngine != null) {
+ return this.blockEngine.runUpdates(i, bl, bl2);
+ }
+ if (this.skyEngine != null) {
+ return this.skyEngine.runUpdates(i, bl, bl2);
+ }
+ return i;
+ }
+
+ @Override
+ public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
+ if (this.blockEngine != null) {
+ this.blockEngine.updateSectionStatus(sectionPos, bl);
+ }
+ if (this.skyEngine != null) {
+ this.skyEngine.updateSectionStatus(sectionPos, bl);
+ }
+ }
+
+ @Override
+ public void enableLightSources(ChunkPos chunkPos, boolean bl) {
+ if (this.blockEngine != null) {
+ this.blockEngine.enableLightSources(chunkPos, bl);
+ }
+ if (this.skyEngine != null) {
+ this.skyEngine.enableLightSources(chunkPos, bl);
+ }
+ }
+
+ @Override
+ public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
+ if (lightLayer == LightLayer.BLOCK) {
+ if (this.blockEngine == null) {
+ return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
+ }
+ return this.blockEngine;
+ }
+ if (this.skyEngine == null) {
+ return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
+ }
+ return this.skyEngine;
+ }
+
+ @Override
+ public int getRawBrightness(BlockPos blockPos, int i) {
+ int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
+ int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
+ return Math.max(k, j);
+ }
+
+ public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
+ ChunkPos chunkPos = chunkAccess.getPos();
+ chunkAccess.setLightCorrect(false);
+
+ LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
+ for (int i = 0; i < 16; i++) {
+ LevelChunkSection levelChunkSection = levelChunkSections[i];
+ if (!LevelChunkSection.isEmpty(levelChunkSection)) {
+ updateSectionStatus(SectionPos.of(chunkPos, i), false);
+ }
+ }
+ enableLightSources(chunkPos, true);
+ if (needLightBlockUpdate) {
+ chunkAccess.getLights()
+ .forEach(blockPos -> onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
+ }
+
+ chunkAccess.setLightCorrect(true);
+ }
+
+ @Override
+ public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
+ throw new UnsupportedOperationException("This should never be used!");
+ }
+
+ @Override
+ public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer,
+ boolean bl) {
+ if (lightLayer == LightLayer.BLOCK) {
+ if (this.blockEngine != null) {
+ this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
+ }
+ } else if (this.skyEngine != null) {
+ this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
+ }
+ }
+
+ @Override
+ public void retainData(ChunkPos chunkPos, boolean bl) {
+ if (this.blockEngine != null) {
+ this.blockEngine.retainData(chunkPos, bl);
+ }
+ if (this.skyEngine != null) {
+ this.skyEngine.retainData(chunkPos, bl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java
new file mode 100644
index 000000000..25355b57f
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java
@@ -0,0 +1,52 @@
+package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
+
+import java.util.stream.Stream;
+
+import net.minecraft.core.SectionPos;
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.LevelAccessor;
+import net.minecraft.world.level.StructureFeatureManager;
+import net.minecraft.world.level.WorldGenLevel;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.levelgen.WorldGenSettings;
+import net.minecraft.world.level.levelgen.feature.StructureFeature;
+import net.minecraft.world.level.levelgen.structure.StructureStart;
+
+public class WorldGenStructFeatManager extends StructureFeatureManager {
+ WorldGenLevel genLevel;
+ WorldGenSettings worldGenSettings;
+
+ public WorldGenStructFeatManager(LevelAccessor levelAccessor, WorldGenSettings worldGenSettings,
+ WorldGenLevel genLevel) {
+ super(levelAccessor, worldGenSettings);
+ this.genLevel = genLevel;
+ this.worldGenSettings = worldGenSettings;
+ }
+
+ @Override
+ public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
+ if (worldGenRegion == genLevel)
+ return this;
+ return new WorldGenStructFeatManager(worldGenRegion, worldGenSettings, worldGenRegion);
+ }
+
+ @Override
+ public Stream extends StructureStart>> startsForFeature(SectionPos sectionPos2,
+ StructureFeature> structureFeature) {
+ if (genLevel == null)
+ return Stream.empty();
+ ChunkAccess chunk = genLevel.getChunk(sectionPos2.x(), sectionPos2.z(), ChunkStatus.STRUCTURE_REFERENCES,
+ false);
+ if (chunk == null)
+ return Stream.empty();
+ return chunk.getReferencesForFeature(structureFeature).stream().map(pos -> {
+ SectionPos sectPos = SectionPos.of(ChunkPos.getX(pos), 0, ChunkPos.getZ(pos));
+ ChunkAccess startChunk = genLevel.getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS, false);
+ if (startChunk == null)
+ return null;
+ return this.getStartForFeature(sectPos, structureFeature, startChunk);
+ }).filter(structureStart -> structureStart != null && structureStart.isValid());
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepBiomes.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepBiomes.java
new file mode 100644
index 000000000..df6cfdf47
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepBiomes.java
@@ -0,0 +1,45 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ProtoChunk;
+
+public final class StepBiomes {
+ /**
+ *
+ */
+ private final BatchGenerationEnvironment envionment;
+
+ /**
+ * @param worldGenerationEnvironment
+ */
+ public StepBiomes(BatchGenerationEnvironment worldGenerationEnvironment) {
+ envionment = worldGenerationEnvironment;
+ }
+
+ public final ChunkStatus STATUS = ChunkStatus.BIOMES;
+
+ public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) {
+
+ ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ chunksToDo.add(chunk);
+ }
+
+ for (ChunkAccess chunk : chunksToDo) {
+ // System.out.println("StepBiomes: "+chunk.getPos());
+ envionment.params.generator.createBiomes(envionment.params.biomes, chunk);
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepFeatures.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepFeatures.java
new file mode 100644
index 000000000..24f571d7d
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepFeatures.java
@@ -0,0 +1,78 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import java.util.ArrayList;
+
+import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+import com.seibel.lod.core.util.GridList;
+
+import net.minecraft.CrashReport;
+import net.minecraft.ReportedException;
+import net.minecraft.core.BlockPos;
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.StructureFeatureManager;
+import net.minecraft.world.level.biome.Biome;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkGenerator;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ProtoChunk;
+import net.minecraft.world.level.levelgen.WorldgenRandom;
+
+public final class StepFeatures {
+ /**
+ *
+ */
+ private final BatchGenerationEnvironment envionment;
+
+ /**
+ * @param worldGenerationEnvironment
+ */
+ public StepFeatures(BatchGenerationEnvironment worldGenerationEnvironment) {
+ envionment = worldGenerationEnvironment;
+ }
+
+ public final ChunkStatus STATUS = ChunkStatus.FEATURES;
+
+ public void applyBiomeDecoration(ChunkGenerator generator, WorldGenRegion worldGenRegion,
+ StructureFeatureManager structureFeatureManager, ChunkAccess chunk) {
+ int i = chunk.getPos().x;
+ int j = chunk.getPos().z;
+ int k = i * 16;
+ int l = j * 16;
+ BlockPos blockPos = new BlockPos(k, 0, l);
+ Biome biome = generator.biomeSource.getNoiseBiome((i << 2) + 2, 2, (j << 2) + 2);
+ WorldgenRandom worldgenRandom = new WorldgenRandom();
+ long m = worldgenRandom.setDecorationSeed(worldGenRegion.getSeed(), k, l);
+ try {
+ synchronized (generator) {
+ biome.generate(structureFeatureManager, generator, worldGenRegion, m, worldgenRandom, blockPos);
+ }
+ } catch (Exception exception) {
+ CrashReport crashReport = CrashReport.forThrowable(exception, "Biome decoration");
+ crashReport.addCategory("Generation")
+
+ .setDetail("CenterX", Integer.valueOf(i)).setDetail("CenterZ", Integer.valueOf(j))
+ .setDetail("Seed", Long.valueOf(m)).setDetail("Biome", biome);
+ throw new ReportedException(crashReport);
+ }
+ }
+
+ public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, GridList chunks) {
+ ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ chunksToDo.add(chunk);
+ }
+
+ for (ChunkAccess chunk : chunksToDo) {
+ try {
+ applyBiomeDecoration(envionment.params.generator, worldGenRegion, tParams.structFeat, chunk);
+ } catch (ReportedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepLight.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepLight.java
new file mode 100644
index 000000000..39fbc057d
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepLight.java
@@ -0,0 +1,58 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
+import com.seibel.lod.core.util.GridList;
+
+import net.minecraft.server.level.ThreadedLevelLightEngine;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.chunk.ProtoChunk;
+import net.minecraft.world.level.lighting.LevelLightEngine;
+
+public final class StepLight {
+ /**
+ *
+ */
+ private final BatchGenerationEnvironment envionment;
+
+ /**
+ * @param worldGenerationEnvironment
+ */
+ public StepLight(BatchGenerationEnvironment worldGenerationEnvironment) {
+ envionment = worldGenerationEnvironment;
+ }
+
+ public final ChunkStatus STATUS = ChunkStatus.LIGHT;
+
+ public void generateGroup(LevelLightEngine lightEngine, GridList chunks) {
+ // ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ }
+
+ for (ChunkAccess chunk : chunks) {
+ boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
+ try {
+ if (lightEngine == null) {
+ // Do nothing
+ } else if (lightEngine instanceof WorldGenLevelLightEngine) {
+ ((WorldGenLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
+ } else if (lightEngine instanceof ThreadedLevelLightEngine) {
+ ((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
+ } else {
+ assert (false);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ chunk.setLightCorrect(true);
+ }
+ lightEngine.runUpdates(Integer.MAX_VALUE, true, true);
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepNoise.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepNoise.java
new file mode 100644
index 000000000..ff4282649
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepNoise.java
@@ -0,0 +1,45 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ProtoChunk;
+
+public final class StepNoise {
+ /**
+ *
+ */
+ private final BatchGenerationEnvironment envionment;
+
+ /**
+ * @param worldGenerationEnvironment
+ */
+ public StepNoise(BatchGenerationEnvironment worldGenerationEnvironment) {
+ envionment = worldGenerationEnvironment;
+ }
+
+ public final ChunkStatus STATUS = ChunkStatus.NOISE;
+
+ public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) {
+
+ ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ chunksToDo.add(chunk);
+ }
+
+ for (ChunkAccess chunk : chunksToDo) {
+ // System.out.println("StepNoise: "+chunk.getPos());
+ envionment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepStructureReference.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepStructureReference.java
new file mode 100644
index 000000000..6c7696e3a
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepStructureReference.java
@@ -0,0 +1,78 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+
+import net.minecraft.CrashReport;
+import net.minecraft.CrashReportCategory;
+import net.minecraft.ReportedException;
+import net.minecraft.core.Registry;
+import net.minecraft.core.SectionPos;
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.StructureFeatureManager;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ProtoChunk;
+import net.minecraft.world.level.levelgen.structure.StructureStart;
+
+public final class StepStructureReference {
+ public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
+
+ private void createReferences(WorldGenRegion worldGenLevel, StructureFeatureManager structureFeatureManager,
+ ChunkAccess chunkAccess) {
+ ChunkPos chunkPos = chunkAccess.getPos();
+ int j = chunkPos.x;
+ int k = chunkPos.z;
+ int l = chunkPos.getMinBlockX();
+ int m = chunkPos.getMinBlockZ();
+
+ SectionPos sectionPos = SectionPos.of(chunkAccess.getPos(), 0);
+
+ for (int n = j - 8; n <= j + 8; n++) {
+ for (int o = k - 8; o <= k + 8; o++) {
+ if (!worldGenLevel.hasChunk(n, o))
+ continue;
+ long p = ChunkPos.asLong(n, o);
+ for (StructureStart> structureStart : worldGenLevel.getChunk(n, o).getAllStarts().values()) {
+ try {
+ if (structureStart.isValid()
+ && structureStart.getBoundingBox().intersects(l, m, l + 15, m + 15)) {
+ structureFeatureManager.addReferenceForFeature(sectionPos, structureStart.getFeature(), p,
+ chunkAccess);
+ }
+ } catch (Exception exception) {
+ CrashReport crashReport = CrashReport.forThrowable(exception, "Generating structure reference");
+ CrashReportCategory crashReportCategory = crashReport.addCategory("Structure");
+ crashReportCategory.setDetail("Id",
+ () -> Registry.STRUCTURE_FEATURE.getKey(structureStart.getFeature()).toString());
+ crashReportCategory.setDetail("Name", () -> structureStart.getFeature().getFeatureName());
+ crashReportCategory.setDetail("Class",
+ () -> structureStart.getFeature().getClass().getCanonicalName());
+ throw new ReportedException(crashReport);
+ }
+ }
+ }
+ }
+ }
+
+ public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) {
+
+ ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ chunksToDo.add(chunk);
+ }
+
+ for (ChunkAccess chunk : chunksToDo) {
+ // System.out.println("StepStructureReference: "+chunk.getPos());
+ createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepStructureStart.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepStructureStart.java
new file mode 100644
index 000000000..ab6e7c071
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepStructureStart.java
@@ -0,0 +1,59 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ProtoChunk;
+
+public final class StepStructureStart {
+ /**
+ *
+ */
+ private final BatchGenerationEnvironment envionment;
+
+ /**
+ * @param worldGenerationEnvironment
+ */
+ public StepStructureStart(BatchGenerationEnvironment worldGenerationEnvironment) {
+ envionment = worldGenerationEnvironment;
+ }
+
+ public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
+
+ public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) {
+
+ ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ chunksToDo.add(chunk);
+ }
+
+ if (envionment.params.worldGenSettings.generateFeatures()) {
+ for (ChunkAccess chunk : chunksToDo) {
+ // System.out.println("StepStructureStart: "+chunk.getPos());
+ envionment.params.generator.createStructures(envionment.params.registry, tParams.structFeat, chunk,
+ envionment.params.structures, envionment.params.worldSeed);
+ // try {
+ envionment.params.generator.createStructures(envionment.params.registry, tParams.structFeat, chunk,
+ envionment.params.structures, envionment.params.worldSeed);
+ // tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
+ /*
+ * } catch (ArrayIndexOutOfBoundsException e) { // There's a rare issue with
+ * StructStart where it throws ArrayIndexOutOfBounds // This means the
+ * structFeat is corrupted (For some reason) and I need to reset it. // TODO:
+ * Figure out in the future why this happens even though I am using new
+ * structFeat throw new StructStartCorruptedException(e); }
+ */
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepSurface.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepSurface.java
new file mode 100644
index 000000000..2932ad4a0
--- /dev/null
+++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/step/StepSurface.java
@@ -0,0 +1,44 @@
+package com.seibel.lod.common.wrappers.worldGeneration.step;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
+import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
+
+import net.minecraft.server.level.WorldGenRegion;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.ProtoChunk;
+
+public final class StepSurface {
+ /**
+ *
+ */
+ private final BatchGenerationEnvironment envionment;
+
+ /**
+ * @param worldGenerationEnvironment
+ */
+ public StepSurface(BatchGenerationEnvironment worldGenerationEnvironment) {
+ envionment = worldGenerationEnvironment;
+ }
+
+ public final ChunkStatus STATUS = ChunkStatus.SURFACE;
+
+ public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) {
+ ArrayList chunksToDo = new ArrayList();
+
+ for (ChunkAccess chunk : chunks) {
+ if (chunk.getStatus().isOrAfter(STATUS))
+ continue;
+ ((ProtoChunk) chunk).setStatus(STATUS);
+ chunksToDo.add(chunk);
+ }
+
+ for (ChunkAccess chunk : chunksToDo) {
+ // System.out.println("StepSurface: "+chunk.getPos());
+ envionment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core b/core
index ca81ed1ef..068622895 160000
--- a/core
+++ b/core
@@ -1 +1 @@
-Subproject commit ca81ed1efef9b117ff848124b06bca8c27d182b4
+Subproject commit 068622895fab70dd7b7eef17c51c0ea753b0889b