diff --git a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGenerationStep.java b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGenerationStep.java index 0477eb376..5d3247e2e 100644 --- a/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGenerationStep.java +++ b/common/src/main/java/com/seibel/lod/common/wrappers/worldGeneration/WorldGenerationStep.java @@ -26,6 +26,7 @@ import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig; import com.seibel.lod.core.enums.config.DistanceGenerationMode; import com.seibel.lod.core.enums.config.LightGenerationMode; import com.seibel.lod.core.objects.lod.LodDimension; +import com.seibel.lod.core.util.GridList; import com.seibel.lod.core.util.LodThreadFactory; import com.seibel.lod.core.util.SingletonHandler; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; @@ -39,7 +40,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -177,7 +177,8 @@ public final class WorldGenerationStep { } public static class PerfCalculator { - public static final int SIZE = 50; + public static final int SIZE = 10; + private int dataCount = 0; Rolling totalTime = new Rolling(SIZE); Rolling emptyTime = new Rolling(SIZE); Rolling structStartTime = new Rolling(SIZE); @@ -191,6 +192,7 @@ public final class WorldGenerationStep { Rolling lodTime = new Rolling(SIZE); public void recordEvent(PrefEvent e) { + dataCount++; long preTime = e.beginNano; totalTime.add(e.endNano - preTime); if (e.emptyNano!=0) { @@ -236,6 +238,7 @@ public final class WorldGenerationStep { } public String toString() { + if (dataCount extends ArrayList implements List { - - public static class Pos { - public int x; - public int y; - - public Pos(int xx, int yy) { - x = xx; - y = yy; - } - } - - private static final long serialVersionUID = 1585978374811888116L; - public final int gridCentreToEdge; - public final int gridSize; - - public GridList(int gridCentreToEdge) { - super((gridCentreToEdge * 2 + 1) * (gridCentreToEdge * 2 + 1)); - gridSize = gridCentreToEdge * 2 + 1; - this.gridCentreToEdge = gridCentreToEdge; - } - - public T getOffsetOf(int index, int x, int y) { - return get(index + x + y * gridSize); - } - - public int offsetOf(int index, int x, int y) { - return index + x + y * gridSize; - } - - public Pos posOf(int index) { - return new Pos(index % gridSize, index / gridSize); - } - - public int calculateOffset(int x, int y) { - return x + y * gridSize; - } - - public GridList subGrid(int gridCentreToEdge) { - int centreIndex = size() / 2; - GridList subGrid = new GridList(gridCentreToEdge); - for (int oy = -gridCentreToEdge; oy <= gridCentreToEdge; oy++) { - int begin = offsetOf(centreIndex, -gridCentreToEdge, oy); - int end = offsetOf(centreIndex, gridCentreToEdge, oy); - subGrid.addAll(this.subList(begin, end + 1)); - } - // System.out.println("========================================\n"+ - // this.toDetailString() + "\nTOOOOOOOOOOOOO\n"+subGrid.toDetailString()+ - // "==========================================\n"); - return subGrid; - } - - @Override - public String toString() { - return "GridList " + gridSize + "*" + gridSize + "[" + size() + "]"; - } - - public String toDetailString() { - StringBuilder str = new StringBuilder("\n"); - int i = 0; - for (T t : this) { - str.append(t.toString()); - str.append(", "); - i++; - if (i % gridSize == 0) { - str.append("\n"); - } - } - return str.toString(); - } - } - public static final class GlobalParameters { final ChunkGenerator generator; final StructureManager structures; @@ -364,7 +294,7 @@ public final class WorldGenerationStep { public static final class ThreadedParameters { private static final ThreadLocal localParam = new ThreadLocal(); final ServerLevel level; - public WorldGenStructFeatManager structFeat = null; + public WorldGenStructFeatManager structFeat; boolean isValid = true; public final PerfCalculator perf = new PerfCalculator(); @@ -382,6 +312,7 @@ public final class WorldGenerationStep { private ThreadedParameters(GlobalParameters param) { level = param.level; + structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings, null); } public void makeStructFeat(WorldGenLevel genLevel, WorldGenSettings worldGenSettings) { @@ -464,11 +395,6 @@ public final class WorldGenerationStep { //=================Generation Step=================== - private static T joinSync(CompletableFuture f) { - if (!f.isDone()) throw new RuntimeException("The future is concurrent!"); - return f.join(); - } - final LinkedList events = new LinkedList(); final GlobalParameters params; final StepStructureStart stepStructureStart = new StepStructureStart(); @@ -612,7 +538,7 @@ public final class WorldGenerationStep { } e.pEvent.emptyNano = System.nanoTime(); e.refreshTimeout(); - region = new LightedWorldGenRegion(params.level, lightEngine, chunks, ChunkStatus.STRUCTURE_STARTS, rangeEmpty, e.lightMode, generator); + region = new LightedWorldGenRegion(params.level, lightEngine, e.tParam.structFeat, chunks, ChunkStatus.STRUCTURE_STARTS, rangeEmpty, e.lightMode, generator); adaptor.setRegion(region); e.tParam.makeStructFeat(region, params.worldGenSettings); referencedChunks = chunks.subGrid(e.range); @@ -923,7 +849,7 @@ public final class WorldGenerationStep { WorldgenRandom worldgenRandom = new WorldgenRandom(); long m = worldgenRandom.setDecorationSeed(worldGenRegion.getSeed(), k, l); try { - synchronized(this) { + synchronized(generator) { biome.generate(structureFeatureManager, generator, worldGenRegion, m, worldgenRandom, blockPos); } } catch (Exception exception) { @@ -1005,16 +931,23 @@ public final class WorldGenerationStep { @Override public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) { + if (worldGenRegion == genLevel) return this; return new WorldGenStructFeatManager(worldGenRegion, worldGenSettings, worldGenRegion); } @Override public Stream> startsForFeature(SectionPos sectionPos2, StructureFeature structureFeature) { - return genLevel.getChunk(sectionPos2.x(), sectionPos2.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureFeature) - .stream().map(long_ -> SectionPos.of(new ChunkPos((long)long_), 0)).map( - sectionPos -> this.getStartForFeature((SectionPos)sectionPos, structureFeature, - genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_STARTS))).filter( - structureStart -> structureStart != null && structureStart.isValid()); + 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()); } } @@ -1026,19 +959,26 @@ public final class WorldGenerationStep { 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, List list, ChunkStatus chunkStatus, int i, + 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> 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) { diff --git a/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinChunkGenerator.java b/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinChunkGenerator.java new file mode 100644 index 000000000..90a1e2819 --- /dev/null +++ b/fabric/src/main/java/com/seibel/lod/fabric/mixins/MixinChunkGenerator.java @@ -0,0 +1,46 @@ +package com.seibel.lod.fabric.mixins; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +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.biome.BiomeSource; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.WorldgenRandom; + +@Mixin(ChunkGenerator.class) +public class MixinChunkGenerator { + @Shadow + @Final + protected BiomeSource biomeSource; + + @Overwrite + public void applyBiomeDecoration(WorldGenRegion worldGenRegion, StructureFeatureManager structureFeatureManager) { + int i = worldGenRegion.getCenterX(); + int j = worldGenRegion.getCenterZ(); + int k = i * 16; + int l = j * 16; + BlockPos blockPos = new BlockPos(k, 0, l); + Biome biome = this.biomeSource.getNoiseBiome((i << 2) + 2, 2, (j << 2) + 2); + WorldgenRandom worldgenRandom = new WorldgenRandom(); + long m = worldgenRandom.setDecorationSeed(worldGenRegion.getSeed(), k, l); + try { + synchronized(this) { + biome.generate(structureFeatureManager, (ChunkGenerator)(Object)this, worldGenRegion, m, worldgenRandom, blockPos); + } + } + catch (Exception exception) { + CrashReport crashReport = CrashReport.forThrowable(exception, "Biome decoration"); + crashReport.addCategory("Generation").setDetail("CenterX", i).setDetail("CenterZ", j).setDetail("Seed", m).setDetail("Biome", biome); + throw new ReportedException(crashReport); + } + } + +} diff --git a/fabric/src/main/resources/fabric.lod.mixins.json b/fabric/src/main/resources/fabric.lod.mixins.json index b630f401f..7307a0360 100644 --- a/fabric/src/main/resources/fabric.lod.mixins.json +++ b/fabric/src/main/resources/fabric.lod.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "events.MixinServerLevel", - "unsafe.MixinPalettedContainer" + "unsafe.MixinPalettedContainer", + "MixinChunkGenerator" ], "client": [ "MixinMinecraft", diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/MixinChunkGenerator.java b/forge/src/main/java/com/seibel/lod/forge/mixins/MixinChunkGenerator.java new file mode 100644 index 000000000..367e27752 --- /dev/null +++ b/forge/src/main/java/com/seibel/lod/forge/mixins/MixinChunkGenerator.java @@ -0,0 +1,46 @@ +package com.seibel.lod.forge.mixins; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +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.biome.BiomeSource; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.WorldgenRandom; + +@Mixin(ChunkGenerator.class) +public class MixinChunkGenerator { + @Shadow + @Final + protected BiomeSource biomeSource; + + @Overwrite + public void applyBiomeDecoration(WorldGenRegion worldGenRegion, StructureFeatureManager structureFeatureManager) { + int i = worldGenRegion.getCenterX(); + int j = worldGenRegion.getCenterZ(); + int k = i * 16; + int l = j * 16; + BlockPos blockPos = new BlockPos(k, 0, l); + Biome biome = this.biomeSource.getNoiseBiome((i << 2) + 2, 2, (j << 2) + 2); + WorldgenRandom worldgenRandom = new WorldgenRandom(); + long m = worldgenRandom.setDecorationSeed(worldGenRegion.getSeed(), k, l); + try { + synchronized(this) { + biome.generate(structureFeatureManager, (ChunkGenerator)(Object)this, worldGenRegion, m, worldgenRandom, blockPos); + } + } + catch (Exception exception) { + CrashReport crashReport = CrashReport.forThrowable(exception, "Biome decoration"); + crashReport.addCategory("Generation").setDetail("CenterX", i).setDetail("CenterZ", j).setDetail("Seed", m).setDetail("Biome", biome); + throw new ReportedException(crashReport); + } + } + +} diff --git a/forge/src/main/resources/lod.mixins.json b/forge/src/main/resources/lod.mixins.json index a68b47314..416cb59c9 100644 --- a/forge/src/main/resources/lod.mixins.json +++ b/forge/src/main/resources/lod.mixins.json @@ -4,6 +4,7 @@ "package": "com.seibel.lod.forge.mixins", "compatibilityLevel": "JAVA_8", "mixins": [ + "MixinChunkGenerator" ], "client": [ "MixinOptionsScreen",