diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Cavegen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Cavegen.kt index dd021e46f..e49e60166 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Cavegen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Cavegen.kt @@ -105,6 +105,8 @@ class Cavegen(world: GameWorld, isFinal: Boolean, val highlandLowlandSelectCache val cavePerturb0 = ModuleTranslateDomain().also { it.setSource(caveShapeAttenuate) it.setAxisXSource(cavePerturbScale) + if (isAlpha2) + it.setAxisZSource(cavePerturbScale) } val cavePerturb = ModuleCombiner().also { // 0: rock, 1: air diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt index 612b98298..7f5843cd7 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Oregen.kt @@ -14,6 +14,9 @@ import kotlin.math.sqrt * Created by minjaesong on 2023-10-25. */ class Oregen(world: GameWorld, isFinal: Boolean, private val caveAttenuateBiasScaledCache: ModuleCache, seed: Long, private val ores: List) : Gen(world, isFinal, seed) { + + private val isAlpha2 = ((params as TerragenParams).version >= 0x0000_000004_000004) + override fun getDone(loadscreen: LoadScreenBase?) { loadscreen?.let { it.stageValue += 1 @@ -127,6 +130,8 @@ class Oregen(world: GameWorld, isFinal: Boolean, private val caveAttenuateBiasSc val orePerturb = ModuleTranslateDomain().also { it.setSource(oreShapeAttenuate) it.setAxisXSource(orePerturbScale) + if (isAlpha2) + it.setAxisZSource(orePerturbScale) } val oreStrecth = ModuleScaleDomain().also { diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt index 6f304b841..a671f9a6a 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt @@ -7,7 +7,6 @@ import net.torvald.terrarum.LoadScreenBase import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.gameworld.GameWorld -import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen.getClampedHeight import net.torvald.terrarum.realestate.LandUtil.CHUNK_H import net.torvald.terrarum.realestate.LandUtil.CHUNK_W import kotlin.math.cos @@ -53,7 +52,7 @@ class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: Modu else 1// TODO - val strata = (params as TerragenParams).getStrataForMode(strataMode) + val strata = (params as TerragenParams).getStrataForMode(seed, strataMode) val groundDepthBlock = strata.map { it.tiles } val terragenTiers = strata.map { it.yheight * terragenYscaling } @@ -222,6 +221,8 @@ class Terragen(world: GameWorld, isFinal: Boolean, val groundScalingCached: Modu } abstract class TerragenParams { + val LANDBLOCK_VAR_COUNTS = 16 + abstract val version: Long abstract val strata: List abstract val featureSize: Double @@ -239,13 +240,14 @@ abstract class TerragenParams { abstract val caveBlockageSelectThre: Double // adjust cave closing-up strength. Lower = more closing abstract val rockBandCutoffFreq: Double abstract val lavaShapeFreg: Double + abstract val landBlockScale: Double - private val strataCache = Array?>(16) { null } + private val strataCache = HashMap?>() - private fun generateStrataCache(mode: Int) { - if (strataCache[mode] != null) return + private fun generateStrataCache(generatorSeed: Long, mode: Int): Long { + val index = generatorSeed shake mode.toLong() - val rng = HQRNG(0x572A7AL shake mode.toLong()) + val rng = HQRNG(index) val tilebuf = Array(2) { "" } fun shiftTilebuf(item: String) { @@ -274,13 +276,20 @@ abstract class TerragenParams { selectedTile ) }.let { - strataCache[mode] = it + strataCache[index] = it + } + + return index + } + + fun pregenerateStrataCache(generatorSeed: Long) { + for (i in 0 until LANDBLOCK_VAR_COUNTS) { + generateStrataCache(generatorSeed, i) } } - fun getStrataForMode(mode: Int): List { - generateStrataCache(mode) - return strataCache[mode]!! + fun getStrataForMode(generatorSeed: Long, mode: Int): List { + return strataCache[generatorSeed shake mode.toLong()]!! } } @@ -326,6 +335,8 @@ data class TerragenParamsAlpha1( override val lavaShapeFreg: Double = 0.03, + override val landBlockScale: Double = 1.0, + ) : TerragenParams() data class TerragenParamsAlpha2( @@ -334,7 +345,7 @@ data class TerragenParamsAlpha2( override val strata: List = listOf( Stratum(Hv(.0, .0), Block.AIR), Stratum(Hv(.5, .0), Block.DIRT), - Stratum(Hv(1.0, 0.03), Block.STONE, Block.STONE_LIMESTONE), + Stratum(Hv(1.0, 0.01), Block.STONE, Block.STONE_LIMESTONE), // 0.01 represents less-eroded faults Stratum(Hv(1.1, 0.03), Block.STONE, Block.SANDSTONE, Block.STONE_LIMESTONE), Stratum(Hv(1.2, 0.03), Block.STONE, Block.SANDSTONE, Block.STONE_LIMESTONE), Stratum(Hv(1.3, 0.03), Block.SANDSTONE, Block.STONE_LIMESTONE, Block.STONE_ORTHOCLASE, Block.STONE_PLAGIOCLASE), @@ -383,4 +394,6 @@ data class TerragenParamsAlpha2( override val lavaShapeFreg: Double = 0.03, + override val landBlockScale: Double = 0.5, + ) : TerragenParams() \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt index 9bacf390b..371d53dbf 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Worldgen.kt @@ -62,6 +62,8 @@ object Worldgen { caveAttenuateBiasScaledForOresCache = getCaveAttenuateBiasScaled(highlandLowlandSelectCache, params.terragenParams) groundScalingCached = getGroundScalingCached(highlandLowlandSelectCache, params.terragenParams) biomeMap = HashMap() + + prepareWorldgen(params.seed, params.terragenParams) } internal lateinit var groundScalingCached: ModuleCache @@ -79,6 +81,11 @@ object Worldgen { private val oreRegistry = ArrayList() + // called by attachMap, which in turn called by enterCreateNewWorld and enterLoadFromSave + fun prepareWorldgen(seed: Long, terragenParams: TerragenParams) { + terragenParams.pregenerateStrataCache(seed) + } + fun getJobs(tags: List = emptyList()): List { val oreTilingModes = HashMap().also { it.putAll(oreRegistry.map { it.tile to it.tiling }) diff --git a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt index bb9b60d3e..3d151397a 100644 --- a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt +++ b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt @@ -44,9 +44,9 @@ const val NOISEBOX_WIDTH = 90 * 18 const val NOISEBOX_HEIGHT = 90 * 26 const val TWO_PI = Math.PI * 2 -//const val WORLDGEN_YOFF = 0 +const val WORLDGEN_YOFF = 0 //const val WORLDGEN_YOFF = 1500 -const val WORLDGEN_YOFF = 5400 - NOISEBOX_HEIGHT +//const val WORLDGEN_YOFF = 5400 - NOISEBOX_HEIGHT /** * Created by minjaesong on 2019-07-23. @@ -92,7 +92,7 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { private var generationTime = 0f private var today = "" - private val NM_TERR = TerragenTest(TerragenParamsAlpha2()) + private val NM_TERR = TerragenTest(seed, TerragenParamsAlpha2()) private val NM_BIOME = BiomeMaker to BiomegenParams() private val NOISEMAKER = NM_TERR @@ -203,6 +203,8 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { private fun renderNoise(noiseMaker: NoiseMaker, callback: () -> Unit = {}) { generationStartTime = System.nanoTime() + NM_TERR.params.pregenerateStrataCache(seed) + // erase first testTex.setColor(colourNull) testTex.fill() @@ -391,7 +393,7 @@ val aquiferTerminalClosureGrad = TerrarumModuleCacheY().also { } // http://accidentalnoise.sourceforge.net/minecraftworlds.html -internal class TerragenTest(val params: TerragenParams) : NoiseMaker { +internal class TerragenTest(val seed: Long, val params: TerragenParams) : NoiseMaker { private infix fun Color.mul(other: Color) = this.mul(other) @@ -460,9 +462,9 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { private fun ItemID.isRock() = this.substringAfter(':').toInt() in 16 until 32 override fun draw(x: Int, y: Int, noiseValue: List, outTex: Pixmap) { - val strataMode = 1//TODO + val strataMode = noiseValue[noiseValue.lastIndex].times(params.LANDBLOCK_VAR_COUNTS).toInt().coerceIn(0, params.LANDBLOCK_VAR_COUNTS - 1) - val strata = params.getStrataForMode(strataMode) + val strata = params.getStrataForMode(seed, strataMode) val groundDepthBlock = strata.map { it.tiles } val terragenTiers = strata.map { it.yheight * terragenYscaling } @@ -476,18 +478,18 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { val terrBlock = if (cave == 0) Block.AIR else if (isMarble) Block.STONE_MARBLE else groundDepthBlock[terr] val terrBlockNoAir = if (isMarble) Block.STONE_MARBLE else groundDepthBlock[terr] - val lavaVal = noiseValue[noiseValue.lastIndex - 3] + val lavaVal = noiseValue[noiseValue.lastIndex - 4] val lava = (lavaVal >= 0.5) - val waterVal = noiseValue[noiseValue.lastIndex - 2] + val waterVal = noiseValue[noiseValue.lastIndex - 3] val waterShell = (waterVal >= 0.32) val water = (waterVal >= 0.5) - val oilVal = noiseValue[noiseValue.lastIndex - 1] + val oilVal = noiseValue[noiseValue.lastIndex - 2] val oilShell = (oilVal >= 0.36) val oil = (oilVal >= 0.7) - val lavaPocketVal = noiseValue[noiseValue.lastIndex] + val lavaPocketVal = noiseValue[noiseValue.lastIndex - 1] val lavaPocketShell = (lavaPocketVal >= 0.30) val lavaPocket = (lavaPocketVal >= 0.5) @@ -519,7 +521,7 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { else blockToCol[terrBlock]!!.toRGBA() ) -// outTex.drawPixel(x, y, noiseValue[2].toColour()) +// outTex.drawPixel(x, y, noiseValue[noiseValue.lastIndex].toColour()) } private fun Double.toColour(): Int { @@ -759,6 +761,7 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { val cavePerturb0 = ModuleTranslateDomain().also { it.setSource(caveShapeAttenuate) it.setAxisXSource(cavePerturbScale) + it.setAxisZSource(cavePerturbScale) } val cavePerturb = ModuleCombiner().also { // 0: rock, 1: air @@ -876,6 +879,7 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { Joise(generateAquifer(seed, groundScalingCached)), Joise(generateCrudeOil(seed, groundScalingCached)), Joise(generateLavaPocket(seed, groundScalingCached)), + Joise(generateLandBlock(seed)) ) } @@ -996,6 +1000,7 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { val orePerturb = ModuleTranslateDomain().also { it.setSource(oreShapeAttenuate) it.setAxisXSource(orePerturbScale) + it.setAxisZSource(orePerturbScale) } val oreStrecth = ModuleScaleDomain().also { @@ -1035,13 +1040,12 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { it.setScaleY(1.0 / 6.0) } - val lavaPerturbFractal = ModuleFractal().also { it.setType(ModuleFractal.FractalType.FBM) it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT) it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) it.setNumOctaves(6) - it.setFrequency(params.lavaShapeFreg * 3.0 / 4.0) + it.setFrequency(params.lavaShapeFreg * 0.75) it.seed = seed shake "FloorIsLava" } @@ -1054,6 +1058,7 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { val lavaPerturb = ModuleTranslateDomain().also { it.setSource(lavaPipe) it.setAxisXSource(lavaPerturbScale) + it.setAxisZSource(lavaPerturbScale) } val lavaSelect = ModuleSelect().also { @@ -1190,6 +1195,51 @@ internal class TerragenTest(val params: TerragenParams) : NoiseMaker { return oilLayer } + private fun generateLandBlock(seed: Long): Module { + val landBlock = ModuleScaleDomain().also { + it.setSource(ModuleFractal().also { + it.setType(ModuleFractal.FractalType.DECARPENTIERSWISS) + it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT) + it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) + it.setNumOctaves(2) + it.setFrequency(params.landBlockScale / params.featureSize) + it.seed = seed shake "LandBlock" + }) + it.setScaleX(1.0 / 4.0) + it.setScaleZ(1.0 / 4.0) + it.setScaleY(1.0 / 18.0) + } + + val landBlockPerturbFractal = ModuleScaleOffset().also { + it.setSource(ModuleFractal().also { + it.setType(ModuleFractal.FractalType.FBM) + it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT) + it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) + it.setNumOctaves(6) + it.setFrequency((params.landBlockScale * 3.0) / params.featureSize) + it.seed = seed shake "MassiveMassif" + }) + it.setScale(24.0) + } + + val landBlockPerturb = ModuleTranslateDomain().also { + it.setSource(landBlock) + it.setAxisXSource(landBlockPerturbFractal) + it.setAxisZSource(landBlockPerturbFractal) + } + + val landBlockClamp = ModuleClamp().also { + it.setSource(ModuleScaleOffset().also { + it.setSource(landBlockPerturb) + it.setScale(1.0) + it.setOffset(-1.0) + }) + it.setRange(0.0, 1.0) + } + + return landBlockClamp + } + private object DummyModule : Module() { override fun get(x: Double, y: Double) = 0.0