From 223570a0b763564f515ae2c0052e2cf9d40203d2 Mon Sep 17 00:00:00 2001 From: tom lee Date: Sat, 22 Jan 2022 18:10:53 +0800 Subject: [PATCH] Update core. Fixed WorldGen using Util.background threads --- .../worldGeneration/WorldGenerationStep.java | 95 ++++++++++++++++--- common/src/main/resources/lod.accesswidener | 2 + core | 2 +- 3 files changed, 83 insertions(+), 16 deletions(-) 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 5303d0cf6..8ee0c7694 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 @@ -19,7 +19,6 @@ package com.seibel.lod.common.wrappers.worldGeneration; -import com.seibel.lod.core.api.ApiShared; import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.api.ModAccessorApi; import com.seibel.lod.core.builders.lodBuilding.LodBuilder; @@ -30,9 +29,9 @@ import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import java.io.IOException; import java.time.Duration; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -45,18 +44,18 @@ import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.Nullable; +import com.google.common.collect.Sets; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.mojang.datafixers.DataFixer; -import com.mojang.datafixers.util.Either; import com.seibel.lod.common.wrappers.chunk.ChunkWrapper; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.WorldGenRegion; +import net.minecraft.util.Mth; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.StructureFeatureManager; import net.minecraft.world.level.biome.Biome; @@ -80,6 +79,8 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.core.SectionPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.NoiseSettings; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.blending.Blender; import net.minecraft.world.level.levelgen.structure.StructureCheck; @@ -108,6 +109,7 @@ public final class WorldGenerationStep { //TODO: Make this LightMode a config public static final LightMode DEFAULT_LIGHTMODE = LightMode.Fancy; + //FIXME: Move this outside the WorldGenerationStep thingy public static class Rolling { private final int size; @@ -147,6 +149,22 @@ public final class WorldGenerationStep { long featureNano = 0; long lightNano = 0; long endNano = 0; + + @Override + public String toString() { + return + "beginNano: "+beginNano+",\n"+ + "emptyNano: "+emptyNano+",\n"+ + "structStartNano: "+structStartNano+",\n"+ + "structRefNano: "+structRefNano+",\n"+ + "biomeNano: "+biomeNano+",\n"+ + "noiseNano: "+noiseNano+",\n"+ + "surfaceNano: "+surfaceNano+",\n"+ + "carverNano: "+carverNano+",\n"+ + "featureNano: "+featureNano+",\n"+ + "lightNano: "+lightNano+",\n"+ + "endNano: "+endNano+"\n"; + } } public static class PerfCalculator { @@ -202,6 +220,7 @@ public final class WorldGenerationStep { Fancy, Fast, Step, StarLight } + //FIXME: Remove this and use the Utils one public static final class GridList extends ArrayList implements List { public static class Pos { @@ -337,6 +356,7 @@ public final class WorldGenerationStep { } } + //======================= Main Event class====================== public static final class GenerationEvent { private static int generationFutureDebugIDs = 0; final ThreadedParameters tParam; @@ -375,8 +395,9 @@ public final class WorldGenerationStep { return (delta > TimeUnit.NANOSECONDS.convert(duration, unit)); } - public void terminate() { + public boolean terminate() { future.cancel(true); + return future.isCancelled(); } public void join() { @@ -404,8 +425,17 @@ public final class WorldGenerationStep { return id + ":" + range + "@" + pos + "(" + target + ")"; } } + + + + + + + + //=================Generation Step=================== - private static T joinAsync(CompletableFuture f) { + private static T joinSync(CompletableFuture f) { + if (!f.isDone()) throw new RuntimeException("The future is concurrent!"); return f.join(); } @@ -455,9 +485,10 @@ public final class WorldGenerationStep { iter.remove(); } } else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)) { - System.err.println(event.id + ": Timed out and terminated!"); + ClientApi.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!"); + ClientApi.LOGGER.info("Dump PrefEvent: "+event.pEvent); try { - event.terminate(); + if (!event.terminate()) ClientApi.LOGGER.error("Failed to terminate the stuck generation event!"); } finally { iter.remove(); } @@ -757,6 +788,11 @@ public final class WorldGenerationStep { public final class StepBiomes { public final ChunkStatus STATUS = ChunkStatus.BIOMES; + private ChunkAccess createBiomes(ChunkGenerator generator, Registry registry, Blender blender, StructureFeatureManager structureFeatureManager, ChunkAccess chunkAccess) { + chunkAccess.fillBiomesFromNoise(generator.getBiomeSource()::getNoiseBiome, generator.climateSampler()); + return chunkAccess; + } + public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) { @@ -770,16 +806,40 @@ public final class WorldGenerationStep { for (ChunkAccess chunk : chunksToDo) { // System.out.println("StepBiomes: "+chunk.getPos()); - chunk = joinAsync(params.generator.createBiomes(params.biomes, Runnable::run, - Blender.of(worldGenRegion), - tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); + chunk = createBiomes(params.generator, params.biomes, Blender.of(worldGenRegion), + tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk); } } } public final class StepNoise { public final ChunkStatus STATUS = ChunkStatus.NOISE; - + + private ChunkAccess NoiseBased$fillFromNoise(NoiseBasedChunkGenerator generator, Blender blender, StructureFeatureManager structureFeatureManager, ChunkAccess chunkAccess) { + NoiseSettings noiseSettings = generator.settings.get().noiseSettings(); + LevelHeightAccessor levelHeightAccessor = chunkAccess.getHeightAccessorForGeneration(); + int i = Math.max(noiseSettings.minY(), levelHeightAccessor.getMinBuildHeight()); + int j = Math.min(noiseSettings.minY() + noiseSettings.height(), levelHeightAccessor.getMaxBuildHeight()); + int k = Mth.intFloorDiv(i, noiseSettings.getCellHeight()); + int l = Mth.intFloorDiv(j - i, noiseSettings.getCellHeight()); + if (l <= 0) { + return chunkAccess; + } + int m = chunkAccess.getSectionIndex(l * noiseSettings.getCellHeight() - 1 + i); + int n = chunkAccess.getSectionIndex(i); + HashSet set = Sets.newHashSet(); + for (int o = m; o >= n; --o) { + LevelChunkSection levelChunkSection = chunkAccess.getSection(o); + levelChunkSection.acquire(); + set.add(levelChunkSection); + } + chunkAccess = generator.doFill(blender, structureFeatureManager, chunkAccess, k, l); + for (LevelChunkSection levelChunkSection : set) { + levelChunkSection.release(); + }; + return chunkAccess; + } + public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List chunks) { @@ -793,8 +853,13 @@ public final class WorldGenerationStep { for (ChunkAccess chunk : chunksToDo) { // System.out.println("StepNoise: "+chunk.getPos()); - chunk = joinAsync(params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), - tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); + if (params.generator instanceof NoiseBasedChunkGenerator) { + chunk = NoiseBased$fillFromNoise((NoiseBasedChunkGenerator)params.generator,Blender.of(worldGenRegion), + tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk); + } else { + chunk = joinSync(params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), + tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); + } } } } diff --git a/common/src/main/resources/lod.accesswidener b/common/src/main/resources/lod.accesswidener index a41db5740..752bd2c30 100644 --- a/common/src/main/resources/lod.accesswidener +++ b/common/src/main/resources/lod.accesswidener @@ -22,6 +22,8 @@ accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine L # world generation accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings; +accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Ljava/util/function/Supplier; +accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess; # lod generation from save file accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop; diff --git a/core b/core index 958033569..9e7703ac5 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 9580335692f948bfd8b3fb90e19a777dcf8d404c +Subproject commit 9e7703ac53ded7fbdb77f4001a87543da66f98c3