From fd385d33a014e4f5f8263215090deec7c75ff61c Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 15 Nov 2023 20:37:52 +0900 Subject: [PATCH] marble veins on worldgen --- assets/mods/basegame/blocks/blocks.csv | 6 +- .../modulebasegame/ui/UILoadDemoSavefiles.kt | 2 + .../terrarum/modulebasegame/ui/UILoadList.kt | 6 +- .../terrarum/modulebasegame/ui/UINewWorld.kt | 3 + .../modulebasegame/worldgenerator/Oregen.kt | 2 +- .../modulebasegame/worldgenerator/Terragen.kt | 84 ++++++++++++++++++- .../modulebasegame/worldgenerator/Worldgen.kt | 3 +- .../terrarum/tests/WorldgenNoiseSandbox.kt | 7 +- 8 files changed, 100 insertions(+), 13 deletions(-) diff --git a/assets/mods/basegame/blocks/blocks.csv b/assets/mods/basegame/blocks/blocks.csv index e35117ed3..60dabdeb0 100644 --- a/assets/mods/basegame/blocks/blocks.csv +++ b/assets/mods/basegame/blocks/blocks.csv @@ -3,11 +3,11 @@ "1";"0";"0";"BLOCK_UPDATE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"AIIR";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL,NORANDTILE" # rocks -"16";"17";"17";"BLOCK_STONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL" -"17";"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL" +"16";"17";"17";"BLOCK_STONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL,OREBEARING" +"17";"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL,OREBEARING" "18";"18";"18";"BLOCK_STONE_TILE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.18";"STONE,NORANDTILE" "19";"19";"19";"BLOCK_STONE_BRICKS";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"STONE,NORANDTILE" -"20";"20";"20";"BLOCK_STONE_DEEP";"0.1252";"0.1252";"0.1252";"0.1252";"80";"24600";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL" +"20";"20";"20";"BLOCK_STONE_DEEP";"0.1252";"0.1252";"0.1252";"0.1252";"80";"24600";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURA,OREBEARING" "21";"21";"21";"BLOCK_STONE_MARBLE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.1";"ROCK,NATURAL" # dirts diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt b/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt index 63f55aa20..458e9b8f7 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UILoadDemoSavefiles.kt @@ -75,6 +75,8 @@ object UILoadGovernor { field = value }*/ + var interruptSavegameListGenerator = false + fun reset() { printdbg(this, "Resetting player and world selection") // playerDisk = null diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt b/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt index a116f6ae9..d698dd8ff 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt @@ -82,6 +82,7 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() { override fun show() { if (!showCalled) { + UILoadGovernor.interruptSavegameListGenerator = false showCalled = true // println("UILoadList ${this.hashCode()} show called by:") // printStackTrace(this) @@ -102,7 +103,10 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() { // read savegames var savegamesCount = 0 printdbg(this, "============== ${this.hashCode()} ============== ") - App.sortedPlayers.forEach { uuid -> + for (uuid in App.sortedPlayers) { + if (UILoadGovernor.interruptSavegameListGenerator) break + + printdbg(this, "Reading player $uuid") val x = full.uiX diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UINewWorld.kt b/src/net/torvald/terrarum/modulebasegame/ui/UINewWorld.kt index 5bf877c6e..ff1f1a1db 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UINewWorld.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UINewWorld.kt @@ -196,6 +196,8 @@ class UINewWorld(val remoCon: UIRemoCon) : UICanvas() { ingame.gameLoadInfoPayload = worldParam ingame.gameLoadMode = TerrarumIngame.GameLoadMode.CREATE_NEW + UILoadGovernor.interruptSavegameListGenerator = true + Terrarum.setCurrentIngameInstance(ingame) val loadScreen = FancyWorldgenLoadScreen(ingame, wx, wy) App.setLoadScreen(loadScreen) @@ -227,6 +229,7 @@ class UINewWorld(val remoCon: UIRemoCon) : UICanvas() { ByteArray64Reader(playerDisk.getFile(SAVEGAMEINFO)!!.bytes, Common.CHARSET) ) as IngamePlayer + UILoadGovernor.interruptSavegameListGenerator = true LoadSavegame( App.savegamePlayers[player.uuid]!!.files[0], diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt index 19db5d556..eaaf45169 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt @@ -62,7 +62,7 @@ class Oregen(world: GameWorld, private val caveAttenuateBiasScaledCache: ModuleC val tileToPut = noiseValues.zip(oreTiles).firstNotNullOfOrNull { (n, tile) -> if (n > 0.5) tile else null } val backingTile = world.getTileFromTerrain(x, y) - if (tileToPut != null && BlockCodex[backingTile].hasTag("ROCK")) { + if (tileToPut != null && BlockCodex[backingTile].hasAllTagOf("ROCK", "OREBEARING")) { // actually put the ore block world.setTileOre(x, y, tileToPut, 0) // autotiling will be handled by the other worldgen process } diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt index d8bf20605..d8009f3ac 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.worldgenerator import com.sudoplay.joise.Joise import com.sudoplay.joise.module.* +import net.torvald.random.HQRNG import net.torvald.random.XXHash32 import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.LoadScreenBase @@ -59,7 +60,8 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se return tiers.lastIndex } - private val terragenTiers = listOf(.0, .5, 1.0, 2.5).map { it * (world.height / 2400.0).pow(0.75) } // pow 1.0 for 1-to-1 scaling; 0.75 is used to make deep-rock layers actually deep for huge world size + private val terragenYscaling = (world.height / 2400.0).pow(0.75) + private val terragenTiers = listOf(.0, .5, 1.0, 2.5).map { it * terragenYscaling } // pow 1.0 for 1-to-1 scaling; 0.75 is used to make deep-rock layers actually deep for huge world size //private fun draw(x: Int, y: Int, width: Int, height: Int, noiseValue: List, world: GameWorld) { private fun draw(x: Int, noises: List, st: Double, soff: Double) { @@ -81,8 +83,10 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se if (stoneSlateTransition == 0 && terr == 3) stoneSlateTransition = y - val wallBlock = groundDepthBlock[terr] - val terrBlock = wallBlock + val isMarble = noiseValue[1] > 0.5 + + val wallBlock = if (isMarble) Block.STONE_MARBLE else groundDepthBlock[terr] + val terrBlock = if (isMarble) Block.STONE_MARBLE else wallBlock world.setTileTerrain(x, y, terrBlock, true) world.setTileWall(x, y, wallBlock, true) @@ -135,6 +139,7 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se } } + private val thicknesses = listOf(0.016, 0.021, 0.029, 0.036, 0.036, 0.029, 0.021, 0.016) private fun getGenerator(seed: Long, params: TerragenParams): List { // this noise tree WILL generate noise value greater than 1.0 @@ -153,10 +158,81 @@ class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, se it.setSource(groundClamp) } + val marblerng = HQRNG(seed) // this must be here: every slice must get identical series of random numbers + return listOf( - Joise(groundScaling) + Joise(groundScaling), + + Joise(generateRockLayer(groundScaling, seed, params, (0..7).map { + thicknesses[it] + marblerng.nextTriangularBal() * 0.006 to (2.6 * terragenYscaling) + it * 0.18 + marblerng.nextTriangularBal() * 0.09 + })), ) } + + private fun generateRockLayer(ground: Module, seed: Long, params: TerragenParams, thicknessAndRange: List>): Module { + + val occlusion = ModuleFractal().also { + it.setType(ModuleFractal.FractalType.RIDGEMULTI) + it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.SIMPLEX) + it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) + it.setNumOctaves(2) + it.setFrequency(params.rockBandCutoffFreq / params.featureSize) // adjust the "density" of the veins + it.seed = seed shake 0x41A2B1E5 + } + + val occlusionScale = ModuleScaleDomain().also { + it.setScaleX(0.5) + it.setScaleZ(0.5) + it.setSource(occlusion) + } + + val occlusionBinary = ModuleSelect().also { + it.setLowSource(0.0) + it.setHighSource(1.0) + it.setControlSource(occlusionScale) + it.setThreshold(1.1) + it.setFalloff(0.0) + } + + val occlusionCache = ModuleCache().also { + it.setSource(occlusionBinary) + } + + val bands = thicknessAndRange.map { (thickness, rangeStart) -> + val thresholdLow = ModuleSelect().also { + it.setLowSource(0.0) + it.setHighSource(1.0) + it.setControlSource(ground) + it.setThreshold(rangeStart) + it.setFalloff(0.0) + } + + val thresholdHigh = ModuleSelect().also { + it.setLowSource(1.0) + it.setHighSource(0.0) + it.setControlSource(ground) + it.setThreshold(rangeStart + thickness) + it.setFalloff(0.0) + } + + ModuleCombiner().also { + it.setSource(0, thresholdLow) + it.setSource(1, thresholdHigh) + it.setSource(2, occlusionCache) + it.setType(ModuleCombiner.CombinerType.MULT) + } + } + + + val combinedBands = ModuleCombiner().also { + bands.forEachIndexed { index, module -> + it.setSource(index, module) + } + it.setType(ModuleCombiner.CombinerType.ADD) + } + + return combinedBands + } } data class TerragenParams( diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt index 16c741df7..e7299f820 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt @@ -63,6 +63,7 @@ object Worldgen { Work(Lang["MENU_IO_WORLDGEN_RETICULATING_SPLINES"], Terragen(world, highlandLowlandSelectCache, params.seed, params.terragenParams), listOf("TERRAIN")), Work(Lang["MENU_IO_WORLDGEN_GROWING_MINERALS"], Oregen(world, caveAttenuateBiasScaledCache, params.seed, oreRegistry), listOf("ORES")), Work(Lang["MENU_IO_WORLDGEN_POSITIONING_ROCKS"], OregenAutotiling(world, params.seed, oreTilingModes), listOf("ORES")), + Work(Lang["MENU_IO_WORLDGEN_POSITIONING_ROCKS"], OregenAutotiling(world, params.seed, oreTilingModes), listOf("ORES")), // TODO generate rock veins // TODO generate gemstones Work(Lang["MENU_IO_WORLDGEN_CARVING_EARTH"], Cavegen(world, highlandLowlandSelectCache, params.seed, params.terragenParams), listOf("TERRAIN", "CAVE")), @@ -115,7 +116,7 @@ object Worldgen { data class Work(val loadingScreenName: String, val theWork: Gen, val tags: List) fun getEstimationSec(width: Int, height: Int): Long { - return (30.0 * 1.25 * (48600000.0 / bogoflops) * ((width * height) / 20095000.0) * (32.0 / THREAD_COUNT)).roundToLong() + return (38.0 * 1.25 * (48600000.0 / bogoflops) * ((width * height) / 20095000.0) * (32.0 / THREAD_COUNT)).roundToLong() } private fun getHighlandLowlandSelectCache(params: TerragenParams, seed: Long): ModuleCache { diff --git a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt index 871a3cf1e..40667105e 100644 --- a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt +++ b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt @@ -345,7 +345,8 @@ internal object TerragenTest : NoiseMaker { COPPER_ORE, IRON_ORE, COAL_ORE, ZINC_ORE, TIN_ORE, GOLD_ORE, SILVER_ORE, LEAD_ORE ) - private val terragenTiers = listOf(.0, .5, 1.0, 2.5).map { it * (NOISEBOX_HEIGHT / 2400.0).pow(0.75) } // pow 1.0 for 1-to-1 scaling; 0.75 is used to make deep-rock layers actually deep for huge world size + private val terragenYscaling = (NOISEBOX_HEIGHT / 2400.0).pow(0.75) + private val terragenTiers = listOf(.0, .5, 1.0, 2.5).map { it * terragenYscaling } // pow 1.0 for 1-to-1 scaling; 0.75 is used to make deep-rock layers actually deep for huge world size private fun Double.dither() = Math.random() < this @@ -356,7 +357,7 @@ internal object TerragenTest : NoiseMaker { val isMarble = noiseValue[10] > 0.5 - val wallBlock = if (isMarble) Block.STONE_MARBLE else groundDepthBlock[terr] + val wallBlock = if (isMarble) Block.STONE_MARBLE else groundDepthBlock[terr] val terrBlock = if (cave == 0) Block.AIR else if (isMarble) Block.STONE_MARBLE else wallBlock @@ -690,7 +691,7 @@ internal object TerragenTest : NoiseMaker { Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:8", 0.017, 0.020, 0.511, 1.0)), Joise(generateRockLayer(groundScalingCached, seed, params, (0..7).map { - thicknesses[it] + marblerng.nextTriangularBal() * 0.006 to 2.6 + it * 0.18 + marblerng.nextTriangularBal() * 0.09 + thicknesses[it] + marblerng.nextTriangularBal() * 0.006 to (2.6 * terragenYscaling) + it * 0.18 + marblerng.nextTriangularBal() * 0.09 })), ) }