mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 19:14:05 +09:00
worldgen: actually generating ores
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
"0";"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INCONSEQUENTIAL,AIR"
|
"0";"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INCONSEQUENTIAL,AIR"
|
||||||
"1";"0";"0";"BLOCK_UPDATE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL"
|
"1";"0";"0";"BLOCK_UPDATE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL"
|
||||||
"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"
|
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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,NATURAL"
|
||||||
|
|||||||
|
@@ -17,6 +17,7 @@ id;classname
|
|||||||
16;net.torvald.terrarum.modulebasegame.gameitems.ItemWorkbench
|
16;net.torvald.terrarum.modulebasegame.gameitems.ItemWorkbench
|
||||||
|
|
||||||
128;net.torvald.terrarum.modulebasegame.gameitems.OreCopper
|
128;net.torvald.terrarum.modulebasegame.gameitems.OreCopper
|
||||||
|
129;net.torvald.terrarum.modulebasegame.gameitems.OreIron
|
||||||
|
|
||||||
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
||||||
257;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorEbony
|
257;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorEbony
|
||||||
|
|||||||
|
BIN
assets/mods/basegame/ores/1.tga
LFS
BIN
assets/mods/basegame/ores/1.tga
LFS
Binary file not shown.
BIN
assets/mods/basegame/ores/2.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/2.tga
LFS
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
"id";"item";"tags"
|
"id";"item";"tags"
|
||||||
"1";"item@basegame:128";"COPPER,MALACHITE"
|
"1";"item@basegame:128";"COPPER,MALACHITE"
|
||||||
# "2";"item@basegame:129";"IRON,HEMATITE"
|
"2";"item@basegame:129";"IRON,HEMATITE"
|
||||||
# "3";"item@basegame:130";"GOLD,NATURAL_GOLD"
|
# "3";"item@basegame:130";"GOLD,NATURAL_GOLD"
|
||||||
# "4";"item@basegame:131";"COAL,CARBON"
|
# "4";"item@basegame:131";"COAL,CARBON"
|
||||||
# "5";"item@basegame:132";"ZINC,SPHALERITE"
|
# "5";"item@basegame:132";"ZINC,SPHALERITE"
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 3 and column 3.
|
4
assets/mods/basegame/ores/worldgen.csv
Normal file
4
assets/mods/basegame/ores/worldgen.csv
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
"id";"freq";"power";"scale";"comment"
|
||||||
|
"1";"0.026";"0.01";"0.505";"copper (malachite)"
|
||||||
|
"2";"0.040";"0.01";"0.505";"iron (haematite)"
|
||||||
|
#"3";"0.040";"0.08";"0.501";"coal"
|
||||||
|
Can't render this file because it contains an unexpected character in line 4 and column 2.
|
@@ -15,6 +15,8 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||||
import net.torvald.terrarum.itemproperties.MaterialCodex
|
import net.torvald.terrarum.itemproperties.MaterialCodex
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.modulebasegame.worldgenerator.OregenParams
|
||||||
|
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import net.torvald.terrarum.utils.CSVFetcher
|
import net.torvald.terrarum.utils.CSVFetcher
|
||||||
import net.torvald.terrarum.utils.JsonFetcher
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
@@ -508,7 +510,23 @@ object ModMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic operator fun invoke(module: String) {
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
|
// register ore codex
|
||||||
Terrarum.oreCodex.fromModule(module, "ores/ores.csv")
|
Terrarum.oreCodex.fromModule(module, "ores/ores.csv")
|
||||||
|
|
||||||
|
// register to worldgen
|
||||||
|
try {
|
||||||
|
CSVFetcher.readFromModule(module, "ores/worldgen.csv").forEach { rec ->
|
||||||
|
val tile = "ores@$module:${rec.get("id")}"
|
||||||
|
val freq = rec.get("freq").toDouble()
|
||||||
|
val power = rec.get("power").toDouble()
|
||||||
|
val scale = rec.get("scale").toDouble()
|
||||||
|
|
||||||
|
Worldgen.registerOre(OregenParams(tile, freq, power, scale))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -582,6 +582,9 @@ open class GameWorld(
|
|||||||
throw IllegalArgumentException("illegal mode input: $mode")
|
throw IllegalArgumentException("illegal mode input: $mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will return (Block.AIR, 0) if there is no ore
|
||||||
|
*/
|
||||||
fun getTileFromOre(rawX: Int, rawY: Int): OrePlacement {
|
fun getTileFromOre(rawX: Int, rawY: Int): OrePlacement {
|
||||||
val (x, y) = coerceXY(rawX, rawY)
|
val (x, y) = coerceXY(rawX, rawY)
|
||||||
val (tileNum, placement) = layerOres.unsafeGetTile1(x, y)
|
val (tileNum, placement) = layerOres.unsafeGetTile1(x, y)
|
||||||
|
|||||||
@@ -569,7 +569,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
val autotiled = getNearbyOres8(x, y).foldIndexed(0) { index, acc, placement ->
|
val autotiled = getNearbyOres8(x, y).foldIndexed(0) { index, acc, placement ->
|
||||||
acc or (placement.item == palSelection).toInt(index)
|
acc or (placement.item == palSelection).toInt(index)
|
||||||
}
|
}
|
||||||
val placement = BlocksDrawer.connectLut47[autotiled]
|
val placement = BlocksDrawer.connectLut16[autotiled]
|
||||||
|
|
||||||
world.setTileOre(x, y, palSelection, placement)
|
world.setTileOre(x, y, palSelection, placement)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ open class DroppedItem : ActorWithBody {
|
|||||||
visualItemID = BlockCodex.getOrNull(itemID)?.world ?: itemID
|
visualItemID = BlockCodex.getOrNull(itemID)?.world ?: itemID
|
||||||
}
|
}
|
||||||
if (textureRegion == null) {
|
if (textureRegion == null) {
|
||||||
textureRegion = ItemCodex.getItemImage(visualItemID)!!
|
textureRegion = ItemCodex.getItemImage(visualItemID) ?: throw NullPointerException("No Item image for ${visualItemID}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy-pasted from ActorWithBody.drawSpriteInGoodPosition()
|
// copy-pasted from ActorWithBody.drawSpriteInGoodPosition()
|
||||||
|
|||||||
@@ -35,3 +35,8 @@ class OreCopper(originalID: ItemID) : OreItemBase(originalID) {
|
|||||||
override val itemImage: TextureRegion
|
override val itemImage: TextureRegion
|
||||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(2,6)
|
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(2,6)
|
||||||
}
|
}
|
||||||
|
class OreIron(originalID: ItemID) : OreItemBase(originalID) {
|
||||||
|
override var originalName = "ITEM_ORE_HAEMATITE"
|
||||||
|
override val itemImage: TextureRegion
|
||||||
|
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(3,6)
|
||||||
|
}
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
package net.torvald.terrarum.modulebasegame.worldgenerator
|
||||||
|
|
||||||
import com.sudoplay.joise.Joise
|
import com.sudoplay.joise.Joise
|
||||||
|
import com.sudoplay.joise.module.*
|
||||||
|
import net.torvald.terrarum.BlockCodex
|
||||||
|
import net.torvald.terrarum.Point2i
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.concurrent.sliceEvenly
|
import net.torvald.terrarum.concurrent.sliceEvenly
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.Terragen.Companion.YHEIGHT_DIVISOR
|
import net.torvald.terrarum.modulebasegame.worldgenerator.Terragen.Companion.YHEIGHT_DIVISOR
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.Terragen.Companion.YHEIGHT_MAGIC
|
import net.torvald.terrarum.modulebasegame.worldgenerator.Terragen.Companion.YHEIGHT_MAGIC
|
||||||
|
import net.torvald.terrarum.toInt
|
||||||
|
import net.torvald.terrarum.utils.OrePlacement
|
||||||
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@@ -14,7 +20,7 @@ import kotlin.math.sin
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-25.
|
* Created by minjaesong on 2023-10-25.
|
||||||
*/
|
*/
|
||||||
class Oregen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, params) {
|
class Oregen(world: GameWorld, private val caveAttenuateBiasScaled: ModuleScaleDomain, seed: Long, private val ores: List<OregenParams>) : Gen(world, seed) {
|
||||||
|
|
||||||
private val threadExecutor = TerrarumIngame.worldgenThreadExecutor
|
private val threadExecutor = TerrarumIngame.worldgenThreadExecutor
|
||||||
private val genSlices = max(threadExecutor.threadCount, world.width / 8)
|
private val genSlices = max(threadExecutor.threadCount, world.width / 8)
|
||||||
@@ -23,7 +29,7 @@ class Oregen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, param
|
|||||||
threadExecutor.renew()
|
threadExecutor.renew()
|
||||||
(0 until world.width).sliceEvenly(genSlices).mapIndexed { i, xs ->
|
(0 until world.width).sliceEvenly(genSlices).mapIndexed { i, xs ->
|
||||||
threadExecutor.submit {
|
threadExecutor.submit {
|
||||||
val localJoise = getGenerator(seed, params as OregenParams)
|
val localJoise = getGenerator(seed)
|
||||||
for (x in xs) {
|
for (x in xs) {
|
||||||
val sampleTheta = (x.toDouble() / world.width) * TWO_PI
|
val sampleTheta = (x.toDouble() / world.width) * TWO_PI
|
||||||
val sampleOffset = world.width / 8.0
|
val sampleOffset = world.width / 8.0
|
||||||
@@ -38,10 +44,15 @@ class Oregen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, param
|
|||||||
/**
|
/**
|
||||||
* @return List of noise instances, each instance refers to one of the spawnable ores
|
* @return List of noise instances, each instance refers to one of the spawnable ores
|
||||||
*/
|
*/
|
||||||
private fun getGenerator(seed: Long, params: OregenParams): List<Joise> {
|
private fun getGenerator(seed: Long): List<Joise> {
|
||||||
TODO()
|
return ores.map {
|
||||||
|
Joise(generateOreVeinModule(caveAttenuateBiasScaled, seed shake it.tile, it.freq, it.power, it.scale))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indices of `noises` has one-to-one mapping to the `ores`
|
||||||
|
*/
|
||||||
private fun draw(x: Int, noises: List<Joise>, st: Double, soff: Double) {
|
private fun draw(x: Int, noises: List<Joise>, st: Double, soff: Double) {
|
||||||
for (y in 0 until world.height) {
|
for (y in 0 until world.height) {
|
||||||
val sx = sin(st) * soff + soff // plus sampleOffset to make only
|
val sx = sin(st) * soff + soff // plus sampleOffset to make only
|
||||||
@@ -50,15 +61,90 @@ class Oregen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, param
|
|||||||
// DEBUG NOTE: it is the OFFSET FROM THE IDEAL VALUE (observed land height - (HEIGHT * DIVISOR)) that must be constant
|
// DEBUG NOTE: it is the OFFSET FROM THE IDEAL VALUE (observed land height - (HEIGHT * DIVISOR)) that must be constant
|
||||||
|
|
||||||
// get the actual noise values
|
// get the actual noise values
|
||||||
|
// the size of the two lists are guaranteed to be identical as they all derive from the same `ores`
|
||||||
val noiseValues = noises.map { it.get(sx, sy, sz) }
|
val noiseValues = noises.map { it.get(sx, sy, sz) }
|
||||||
|
val oreTiles = ores.map { it.tile }
|
||||||
|
|
||||||
TODO()
|
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")) {
|
||||||
|
// actually put the ore block
|
||||||
|
world.setTileOre(x, y, tileToPut, 0) // autotiling will be handled by the other worldgen process
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun applyPowMult(joiseModule: Module, pow: Double, mult: Double): Module {
|
||||||
|
return ModuleScaleOffset().also {
|
||||||
|
it.setSource(ModulePow().also {
|
||||||
|
it.setSource(joiseModule)
|
||||||
|
it.setPower(pow)
|
||||||
|
})
|
||||||
|
it.setScale(mult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateOreVeinModule(caveAttenuateBiasScaled: ModuleScaleDomain, seed: Long, freq: Double, pow: Double, scale: Double): Module {
|
||||||
|
val oreShape = ModuleFractal().also {
|
||||||
|
it.setType(ModuleFractal.FractalType.RIDGEMULTI)
|
||||||
|
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
|
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
|
it.setNumOctaves(2)
|
||||||
|
it.setFrequency(freq) // adjust the "density" of the caves
|
||||||
|
it.seed = seed
|
||||||
|
}
|
||||||
|
|
||||||
|
val oreShape2 = ModuleScaleOffset().also {
|
||||||
|
it.setSource(oreShape)
|
||||||
|
it.setScale(1.0)
|
||||||
|
it.setOffset(-0.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
val caveAttenuateBias3 = applyPowMult(caveAttenuateBiasScaled, pow, scale)
|
||||||
|
|
||||||
|
val oreShapeAttenuate = ModuleCombiner().also {
|
||||||
|
it.setType(ModuleCombiner.CombinerType.MULT)
|
||||||
|
it.setSource(0, oreShape2)
|
||||||
|
it.setSource(1, caveAttenuateBias3)
|
||||||
|
}
|
||||||
|
|
||||||
|
val orePerturbFractal = ModuleFractal().also {
|
||||||
|
it.setType(ModuleFractal.FractalType.FBM)
|
||||||
|
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
|
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
|
it.setNumOctaves(6)
|
||||||
|
it.setFrequency(freq * 3.0 / 4.0)
|
||||||
|
it.seed = seed shake 0x5721CE_76E_EA276L // strike the earth
|
||||||
|
}
|
||||||
|
|
||||||
|
val orePerturbScale = ModuleScaleOffset().also {
|
||||||
|
it.setSource(orePerturbFractal)
|
||||||
|
it.setScale(20.0)
|
||||||
|
it.setOffset(0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val orePerturb = ModuleTranslateDomain().also {
|
||||||
|
it.setSource(oreShapeAttenuate)
|
||||||
|
it.setAxisXSource(orePerturbScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
val oreSelect = ModuleSelect().also {
|
||||||
|
it.setLowSource(0.0)
|
||||||
|
it.setHighSource(1.0)
|
||||||
|
it.setControlSource(orePerturb)
|
||||||
|
it.setThreshold(0.5)
|
||||||
|
it.setFalloff(0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return oreSelect
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class OregenParams(
|
data class OregenParams(
|
||||||
val oreShapeFreq: Double = 0.04, //adjust the "density" of the caves
|
val tile: String,
|
||||||
val oreAttenuateBias: Double = 0.90, // adjust the "concentration" of the cave gen. Lower = larger voids
|
val freq: Double, //adjust the "density" of the caves
|
||||||
val oreSelectThre: Double = 0.918, // also adjust this if you've touched the bias value. Number can be greater than 1.0
|
val power: Double, // adjust the "concentration" of the cave gen. Lower = larger voids
|
||||||
|
val scale: Double, // also adjust this if you've touched the bias value. Number can be greater than 1.0
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.worldgenerator
|
||||||
|
|
||||||
|
import net.torvald.terrarum.Point2i
|
||||||
|
import net.torvald.terrarum.concurrent.sliceEvenly
|
||||||
|
import net.torvald.terrarum.gameitems.isOre
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
|
import net.torvald.terrarum.toInt
|
||||||
|
import net.torvald.terrarum.utils.OrePlacement
|
||||||
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-10-26.
|
||||||
|
*/
|
||||||
|
class OregenAutotiling(world: GameWorld, seed: Long) : Gen(world, seed) {
|
||||||
|
|
||||||
|
private val threadExecutor = TerrarumIngame.worldgenThreadExecutor
|
||||||
|
private val genSlices = max(threadExecutor.threadCount, world.width / 8)
|
||||||
|
|
||||||
|
override fun getDone() {
|
||||||
|
threadExecutor.renew()
|
||||||
|
(0 until world.width).sliceEvenly(genSlices).mapIndexed { i, xs ->
|
||||||
|
threadExecutor.submit {
|
||||||
|
for (x in xs) {
|
||||||
|
draw(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
threadExecutor.join()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun draw(x: Int) {
|
||||||
|
for (y in 0 until world.height) {
|
||||||
|
val (ore, _) = world.getTileFromOre(x, y)
|
||||||
|
|
||||||
|
if (ore.isOre()) {
|
||||||
|
// get placement (tile connection) info
|
||||||
|
val autotiled = getNearbyOres8(x, y).foldIndexed(0) { index, acc, placement ->
|
||||||
|
acc or (placement.item == ore).toInt(index)
|
||||||
|
}
|
||||||
|
val placement = BlocksDrawer.connectLut16[autotiled]
|
||||||
|
|
||||||
|
// actually put the ore block
|
||||||
|
world.setTileOre(x, y, ore, placement) // autotiling will be handled by the other worldgen process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getNearbyTilesPos8(x: Int, y: Int): Array<Point2i> {
|
||||||
|
return arrayOf(
|
||||||
|
Point2i(x + 1, y),
|
||||||
|
Point2i(x + 1, y + 1),
|
||||||
|
Point2i(x, y + 1),
|
||||||
|
Point2i(x - 1, y + 1),
|
||||||
|
Point2i(x - 1, y),
|
||||||
|
Point2i(x - 1, y - 1),
|
||||||
|
Point2i(x, y - 1),
|
||||||
|
Point2i(x + 1, y - 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
|
||||||
|
return getNearbyTilesPos8(x, y).map { world.getTileFromOre(it.x, it.y) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ import kotlin.math.sin
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2019-07-23.
|
* Created by minjaesong on 2019-07-23.
|
||||||
*/
|
*/
|
||||||
class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, params) {
|
class Terragen(world: GameWorld, val highlandLowlandSelectCache: ModuleCache, seed: Long, params: Any) : Gen(world, seed, params) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val YHEIGHT_MAGIC = 2800.0 / 3.0
|
const val YHEIGHT_MAGIC = 2800.0 / 3.0
|
||||||
@@ -137,160 +137,10 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
|||||||
|
|
||||||
|
|
||||||
private fun getGenerator(seed: Long, params: TerragenParams): List<Joise> {
|
private fun getGenerator(seed: Long, params: TerragenParams): List<Joise> {
|
||||||
val lowlandMagic: Long = 0x41A21A114DBE56 // Maria Lindberg
|
|
||||||
val highlandMagic: Long = 0x0114E091 // Olive Oyl
|
|
||||||
val mountainMagic: Long = 0x115AA4DE2504 // Lisa Anderson
|
|
||||||
val selectionMagic: Long = 0x41E10D9B100 // Melody Blue
|
|
||||||
|
|
||||||
val caveMagic: Long = 0x00215741CDF // Urist McDF
|
val caveMagic: Long = 0x00215741CDF // Urist McDF
|
||||||
val cavePerturbMagic: Long = 0xA2410C // Armok
|
val cavePerturbMagic: Long = 0xA2410C // Armok
|
||||||
val caveBlockageMagic: Long = 0xD15A57E5 // Disaster
|
val caveBlockageMagic: Long = 0xD15A57E5 // Disaster
|
||||||
|
|
||||||
|
|
||||||
val groundGradient = ModuleGradient().also {
|
|
||||||
it.setGradient(0.0, 0.0, 0.0, 1.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* lowlands */
|
|
||||||
|
|
||||||
val lowlandShapeFractal = ModuleFractal().also {
|
|
||||||
it.setType(ModuleFractal.FractalType.BILLOW)
|
|
||||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
|
||||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
|
||||||
it.setNumOctaves(2)
|
|
||||||
it.setFrequency(0.25)
|
|
||||||
it.seed = seed shake lowlandMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
val lowlandScale = ModuleScaleOffset().also {
|
|
||||||
it.setSource(lowlandShapeFractal)
|
|
||||||
it.setScale(0.22)
|
|
||||||
it.setOffset(params.lowlandScaleOffset) // linearly alters the height
|
|
||||||
}
|
|
||||||
|
|
||||||
val lowlandYScale = ModuleScaleDomain().also {
|
|
||||||
it.setSource(lowlandScale)
|
|
||||||
it.setScaleY(0.02) // greater = more distortion, overhangs
|
|
||||||
}
|
|
||||||
|
|
||||||
val lowlandTerrain = ModuleTranslateDomain().also {
|
|
||||||
it.setSource(groundGradient)
|
|
||||||
it.setAxisYSource(lowlandYScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* highlands */
|
|
||||||
|
|
||||||
val highlandShapeFractal = ModuleFractal().also {
|
|
||||||
it.setType(ModuleFractal.FractalType.FBM)
|
|
||||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
|
||||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
|
||||||
it.setNumOctaves(4)
|
|
||||||
it.setFrequency(2.0)
|
|
||||||
it.seed = seed shake highlandMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
val highlandScale = ModuleScaleOffset().also {
|
|
||||||
it.setSource(highlandShapeFractal)
|
|
||||||
it.setScale(0.5)
|
|
||||||
it.setOffset(params.highlandScaleOffset) // linearly alters the height
|
|
||||||
}
|
|
||||||
|
|
||||||
val highlandYScale = ModuleScaleDomain().also {
|
|
||||||
it.setSource(highlandScale)
|
|
||||||
it.setScaleY(0.14) // greater = more distortion, overhangs
|
|
||||||
}
|
|
||||||
|
|
||||||
val highlandTerrain = ModuleTranslateDomain().also {
|
|
||||||
it.setSource(groundGradient)
|
|
||||||
it.setAxisYSource(highlandYScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mountains */
|
|
||||||
|
|
||||||
val mountainShapeFractal = ModuleFractal().also {
|
|
||||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
|
||||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
|
||||||
it.setNumOctaves(8)
|
|
||||||
it.setFrequency(1.0)
|
|
||||||
it.seed = seed shake mountainMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
val mountainScale = ModuleScaleOffset().also {
|
|
||||||
it.setSource(mountainShapeFractal)
|
|
||||||
it.setScale(1.0)
|
|
||||||
it.setOffset(params.mountainScaleOffset) // linearly alters the height
|
|
||||||
}
|
|
||||||
|
|
||||||
val mountainYScale = ModuleScaleDomain().also {
|
|
||||||
it.setSource(mountainScale)
|
|
||||||
it.setScaleY(params.mountainDisturbance) // greater = more distortion, overhangs
|
|
||||||
}
|
|
||||||
|
|
||||||
val mountainTerrain = ModuleTranslateDomain().also {
|
|
||||||
it.setSource(groundGradient)
|
|
||||||
it.setAxisYSource(mountainYScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* selection */
|
|
||||||
|
|
||||||
val terrainTypeFractal = ModuleFractal().also {
|
|
||||||
it.setType(ModuleFractal.FractalType.FBM)
|
|
||||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
|
||||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
|
||||||
it.setNumOctaves(3)
|
|
||||||
it.setFrequency(0.125)
|
|
||||||
it.seed = seed shake selectionMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
val terrainScaleOffset = ModuleScaleOffset().also {
|
|
||||||
it.setSource(terrainTypeFractal)
|
|
||||||
it.setOffset(0.5)
|
|
||||||
it.setScale(0.666666) // greater = more dynamic terrain
|
|
||||||
}
|
|
||||||
|
|
||||||
val terrainTypeYScale = ModuleScaleDomain().also {
|
|
||||||
it.setSource(terrainScaleOffset)
|
|
||||||
it.setScaleY(0.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val terrainTypeCache = ModuleCache().also {
|
|
||||||
it.setSource(terrainTypeYScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
val highlandMountainSelect = ModuleSelect().also {
|
|
||||||
it.setLowSource(highlandTerrain)
|
|
||||||
it.setHighSource(mountainTerrain)
|
|
||||||
it.setControlSource(terrainTypeCache)
|
|
||||||
it.setThreshold(0.55)
|
|
||||||
it.setFalloff(0.2)
|
|
||||||
}
|
|
||||||
|
|
||||||
val highlandLowlandSelect = ModuleSelect().also {
|
|
||||||
it.setLowSource(lowlandTerrain)
|
|
||||||
it.setHighSource(highlandMountainSelect)
|
|
||||||
it.setControlSource(terrainTypeCache)
|
|
||||||
it.setThreshold(0.25)
|
|
||||||
it.setFalloff(0.15)
|
|
||||||
}
|
|
||||||
|
|
||||||
val highlandLowlandSelectCache = ModuleCache().also {
|
|
||||||
it.setSource(highlandLowlandSelect)
|
|
||||||
}
|
|
||||||
|
|
||||||
val groundSelect = ModuleSelect().also {
|
|
||||||
it.setLowSource(0.0)
|
|
||||||
it.setHighSource(1.0)
|
|
||||||
it.setThreshold(0.5)
|
|
||||||
it.setControlSource(highlandLowlandSelectCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
val groundSelect2 = ModuleSelect().also {
|
|
||||||
it.setLowSource(0.0)
|
|
||||||
it.setHighSource(1.0)
|
|
||||||
it.setThreshold(0.8)
|
|
||||||
it.setControlSource(highlandLowlandSelectCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* caves */
|
/* caves */
|
||||||
|
|
||||||
val caveShape = ModuleFractal().also {
|
val caveShape = ModuleFractal().also {
|
||||||
@@ -401,6 +251,7 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
|||||||
it.setSource(caveClamp)
|
it.setSource(caveClamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//return Joise(caveInMix)
|
//return Joise(caveInMix)
|
||||||
return listOf(
|
return listOf(
|
||||||
Joise(groundScaling),
|
Joise(groundScaling),
|
||||||
@@ -422,13 +273,13 @@ data class TerragenParams(
|
|||||||
val caveBlockageFractalFreq: Double = 8.88,
|
val caveBlockageFractalFreq: Double = 8.88,
|
||||||
val caveBlockageSelectThre: Double = 1.40, // adjust cave cloing-up strength. Larger = more closing
|
val caveBlockageSelectThre: Double = 1.40, // adjust cave cloing-up strength. Larger = more closing
|
||||||
|
|
||||||
val oreCopperFreq: Double = 0.024, // adjust the "density" of the ore veins
|
// val oreCopperFreq: Double = 0.024, // adjust the "density" of the ore veins
|
||||||
val oreCopperPower: Double = 0.01, // super-low value almost negates the depth element
|
// val oreCopperPower: Double = 0.01, // super-low value almost negates the depth element
|
||||||
val oreCopperScale: Double = 0.505,
|
// val oreCopperScale: Double = 0.505,
|
||||||
|
|
||||||
val oreIronFreq: Double = 0.04, // adjust the "density" of the ore veins
|
// val oreIronFreq: Double = 0.04, // adjust the "density" of the ore veins
|
||||||
val oreIronPower: Double = 0.01, // super-low value almost negates the depth element
|
// val oreIronPower: Double = 0.01, // super-low value almost negates the depth element
|
||||||
val oreIronScale: Double = 0.505,
|
// val oreIronScale: Double = 0.505,
|
||||||
|
|
||||||
|
|
||||||
// 0.01 - 0.505
|
// 0.01 - 0.505
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
package net.torvald.terrarum.modulebasegame.worldgenerator
|
||||||
|
|
||||||
|
import com.sudoplay.joise.module.*
|
||||||
|
import net.torvald.random.XXHash64
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.*
|
import net.torvald.terrarum.App.*
|
||||||
import net.torvald.terrarum.BlockCodex
|
import net.torvald.terrarum.BlockCodex
|
||||||
@@ -24,10 +26,27 @@ object Worldgen {
|
|||||||
params = genParams
|
params = genParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal lateinit var highlandLowlandSelectCache: ModuleCache
|
||||||
|
internal lateinit var caveAttenuateBiasScaled: ModuleScaleDomain
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Other modules are free to add their own ores to the world generator.
|
||||||
|
*/
|
||||||
|
fun registerOre(oreInfo: OregenParams) {
|
||||||
|
oreRegistry.add(oreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val oreRegistry = ArrayList<OregenParams>()
|
||||||
|
|
||||||
fun generateMap() {
|
fun generateMap() {
|
||||||
|
highlandLowlandSelectCache = getHighlandLowlandSelectCache(params.terragenParams, params.seed)
|
||||||
|
caveAttenuateBiasScaled = getCaveAttenuateBiasScaled(highlandLowlandSelectCache, params.terragenParams)
|
||||||
|
|
||||||
val jobs = listOf(
|
val jobs = listOf(
|
||||||
Work("Reticulating Splines", Terragen(world, params.seed, params.terragenParams)),
|
Work("Reticulating Splines", Terragen(world, highlandLowlandSelectCache, params.seed, params.terragenParams)),
|
||||||
Work("Adding Vegetations", Biomegen(world, params.seed, params.biomegenParams))
|
Work("Adding Rocks", Oregen(world, caveAttenuateBiasScaled, params.seed, oreRegistry)),
|
||||||
|
Work("Positioning Rocks", OregenAutotiling(world, params.seed)),
|
||||||
|
Work("Adding Vegetations", Biomegen(world, params.seed, params.biomegenParams)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -66,9 +85,163 @@ object Worldgen {
|
|||||||
fun getEstimationSec(width: Int, height: Int): Long {
|
fun getEstimationSec(width: Int, height: Int): Long {
|
||||||
return (23.05 * 1.25 * (48600000.0 / bogoflops) * ((width * height) / 40095000.0) * (32.0 / THREAD_COUNT)).roundToLong()
|
return (23.05 * 1.25 * (48600000.0 / bogoflops) * ((width * height) / 40095000.0) * (32.0 / THREAD_COUNT)).roundToLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getHighlandLowlandSelectCache(params: TerragenParams, seed: Long): ModuleCache {
|
||||||
|
val lowlandMagic: Long = 0x41A21A114DBE56 // Maria Lindberg
|
||||||
|
val highlandMagic: Long = 0x0114E091 // Olive Oyl
|
||||||
|
val mountainMagic: Long = 0x115AA4DE2504 // Lisa Anderson
|
||||||
|
val selectionMagic: Long = 0x41E10D9B100 // Melody Blue
|
||||||
|
|
||||||
|
val groundGradient = ModuleGradient().also {
|
||||||
|
it.setGradient(0.0, 0.0, 0.0, 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lowlands */
|
||||||
|
|
||||||
|
val lowlandShapeFractal = ModuleFractal().also {
|
||||||
|
it.setType(ModuleFractal.FractalType.BILLOW)
|
||||||
|
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
|
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
|
it.setNumOctaves(2)
|
||||||
|
it.setFrequency(0.25)
|
||||||
|
it.seed = seed shake lowlandMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
val lowlandScale = ModuleScaleOffset().also {
|
||||||
|
it.setSource(lowlandShapeFractal)
|
||||||
|
it.setScale(0.22)
|
||||||
|
it.setOffset(params.lowlandScaleOffset) // linearly alters the height
|
||||||
|
}
|
||||||
|
|
||||||
|
val lowlandYScale = ModuleScaleDomain().also {
|
||||||
|
it.setSource(lowlandScale)
|
||||||
|
it.setScaleY(0.02) // greater = more distortion, overhangs
|
||||||
|
}
|
||||||
|
|
||||||
|
val lowlandTerrain = ModuleTranslateDomain().also {
|
||||||
|
it.setSource(groundGradient)
|
||||||
|
it.setAxisYSource(lowlandYScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* highlands */
|
||||||
|
|
||||||
|
val highlandShapeFractal = ModuleFractal().also {
|
||||||
|
it.setType(ModuleFractal.FractalType.FBM)
|
||||||
|
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
|
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
|
it.setNumOctaves(4)
|
||||||
|
it.setFrequency(2.0)
|
||||||
|
it.seed = seed shake highlandMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
val highlandScale = ModuleScaleOffset().also {
|
||||||
|
it.setSource(highlandShapeFractal)
|
||||||
|
it.setScale(0.5)
|
||||||
|
it.setOffset(params.highlandScaleOffset) // linearly alters the height
|
||||||
|
}
|
||||||
|
|
||||||
|
val highlandYScale = ModuleScaleDomain().also {
|
||||||
|
it.setSource(highlandScale)
|
||||||
|
it.setScaleY(0.14) // greater = more distortion, overhangs
|
||||||
|
}
|
||||||
|
|
||||||
|
val highlandTerrain = ModuleTranslateDomain().also {
|
||||||
|
it.setSource(groundGradient)
|
||||||
|
it.setAxisYSource(highlandYScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mountains */
|
||||||
|
|
||||||
|
val mountainShapeFractal = ModuleFractal().also {
|
||||||
|
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
|
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
|
it.setNumOctaves(8)
|
||||||
|
it.setFrequency(1.0)
|
||||||
|
it.seed = seed shake mountainMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
val mountainScale = ModuleScaleOffset().also {
|
||||||
|
it.setSource(mountainShapeFractal)
|
||||||
|
it.setScale(1.0)
|
||||||
|
it.setOffset(params.mountainScaleOffset) // linearly alters the height
|
||||||
|
}
|
||||||
|
|
||||||
|
val mountainYScale = ModuleScaleDomain().also {
|
||||||
|
it.setSource(mountainScale)
|
||||||
|
it.setScaleY(params.mountainDisturbance) // greater = more distortion, overhangs
|
||||||
|
}
|
||||||
|
|
||||||
|
val mountainTerrain = ModuleTranslateDomain().also {
|
||||||
|
it.setSource(groundGradient)
|
||||||
|
it.setAxisYSource(mountainYScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* selection */
|
||||||
|
|
||||||
|
val terrainTypeFractal = ModuleFractal().also {
|
||||||
|
it.setType(ModuleFractal.FractalType.FBM)
|
||||||
|
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
|
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
|
it.setNumOctaves(3)
|
||||||
|
it.setFrequency(0.125)
|
||||||
|
it.seed = seed shake selectionMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
val terrainScaleOffset = ModuleScaleOffset().also {
|
||||||
|
it.setSource(terrainTypeFractal)
|
||||||
|
it.setOffset(0.5)
|
||||||
|
it.setScale(0.666666) // greater = more dynamic terrain
|
||||||
|
}
|
||||||
|
|
||||||
|
val terrainTypeYScale = ModuleScaleDomain().also {
|
||||||
|
it.setSource(terrainScaleOffset)
|
||||||
|
it.setScaleY(0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val terrainTypeCache = ModuleCache().also {
|
||||||
|
it.setSource(terrainTypeYScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
val highlandMountainSelect = ModuleSelect().also {
|
||||||
|
it.setLowSource(highlandTerrain)
|
||||||
|
it.setHighSource(mountainTerrain)
|
||||||
|
it.setControlSource(terrainTypeCache)
|
||||||
|
it.setThreshold(0.55)
|
||||||
|
it.setFalloff(0.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
val highlandLowlandSelect = ModuleSelect().also {
|
||||||
|
it.setLowSource(lowlandTerrain)
|
||||||
|
it.setHighSource(highlandMountainSelect)
|
||||||
|
it.setControlSource(terrainTypeCache)
|
||||||
|
it.setThreshold(0.25)
|
||||||
|
it.setFalloff(0.15)
|
||||||
|
}
|
||||||
|
|
||||||
|
val highlandLowlandSelectCache = ModuleCache().also {
|
||||||
|
it.setSource(highlandLowlandSelect)
|
||||||
|
}
|
||||||
|
|
||||||
|
return highlandLowlandSelectCache
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCaveAttenuateBiasScaled(highlandLowlandSelectCache: ModuleCache, params: TerragenParams): ModuleScaleDomain {
|
||||||
|
val caveAttenuateBias = ModuleBias().also {
|
||||||
|
it.setSource(highlandLowlandSelectCache)
|
||||||
|
it.setBias(params.caveAttenuateBias) // (0.5+) adjust the "concentration" of the cave gen. Lower = larger voids
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModuleScaleDomain().also {
|
||||||
|
it.setScaleX(1.0 / params.featureSize) // adjust this value to change features size
|
||||||
|
it.setScaleY(1.0 / params.featureSize)
|
||||||
|
it.setScaleZ(1.0 / params.featureSize)
|
||||||
|
it.setSource(caveAttenuateBias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Gen(val world: GameWorld, val seed: Long, val params: Any) {
|
abstract class Gen(val world: GameWorld, val seed: Long, val params: Any? = null) {
|
||||||
open fun getDone() { } // trying to use different name so that it won't be confused with Runnable or Callable
|
open fun getDone() { } // trying to use different name so that it won't be confused with Runnable or Callable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,5 +263,9 @@ infix fun Long.shake(other: Long): Long {
|
|||||||
return s0 + s1
|
return s0 + s1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infix fun Long.shake(other: String): Long {
|
||||||
|
return this shake XXHash64.hash(other.toByteArray(), this + 31)
|
||||||
|
}
|
||||||
|
|
||||||
val TWO_PI = Math.PI * 2.0
|
val TWO_PI = Math.PI * 2.0
|
||||||
val HALF_PI = Math.PI / 2.0
|
val HALF_PI = Math.PI / 2.0
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ class WorldgenNoiseSandbox : ApplicationAdapter() {
|
|||||||
|
|
||||||
private val NM_TERR = TerragenTest to TerragenParams()
|
private val NM_TERR = TerragenTest to TerragenParams()
|
||||||
private val NM_BIOME = BiomeMaker to BiomegenParams()
|
private val NM_BIOME = BiomeMaker to BiomegenParams()
|
||||||
private val NM_ORES = Oregen to OregenParams()
|
|
||||||
|
|
||||||
private val NOISEMAKER = NM_TERR
|
private val NOISEMAKER = NM_TERR
|
||||||
|
|
||||||
@@ -687,8 +686,8 @@ internal object TerragenTest : NoiseMaker {
|
|||||||
return listOf(
|
return listOf(
|
||||||
Joise(groundScaling),
|
Joise(groundScaling),
|
||||||
Joise(caveScaling),
|
Joise(caveScaling),
|
||||||
Joise(generateOreVeinModule(caveAttenuateBiasScaled, seed shake 0xC08204, params.oreCopperFreq, params.oreCopperPower, params.oreCopperScale)),
|
Joise(generateOreVeinModule(caveAttenuateBiasScaled, seed shake "ores@basegame:1", 0.024, 0.01, 0.505)),
|
||||||
Joise(generateOreVeinModule(caveAttenuateBiasScaled, seed shake 0xFE2204, params.oreIronFreq, params.oreIronPower, params.oreIronScale)),
|
Joise(generateOreVeinModule(caveAttenuateBiasScaled, seed shake "ores@basegame:2", 0.04, 0.01, 0.505)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -759,84 +758,6 @@ internal object TerragenTest : NoiseMaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal object Oregen : NoiseMaker {
|
|
||||||
override fun draw(x: Int, y: Int, noiseValue: List<Double>, outTex: Pixmap) {
|
|
||||||
var n = noiseValue[0]
|
|
||||||
|
|
||||||
// if (n in 0.0..1.0) n = 1.0 - n
|
|
||||||
|
|
||||||
val cout = if (n >= 0.0)
|
|
||||||
Color(n.toFloat(), n.toFloat(), n.toFloat(), 1f)
|
|
||||||
else
|
|
||||||
Color(-n.toFloat(), 0f, 1f, 1f)
|
|
||||||
|
|
||||||
outTex.drawPixel(x, y, cout.toRGBA())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getGenerator(seed: Long, params: Any): List<Joise> {
|
|
||||||
val params = params as OregenParams
|
|
||||||
|
|
||||||
val oreMagic = 0x023L
|
|
||||||
val orePerturbMagic = 12345L
|
|
||||||
|
|
||||||
val oreShape = ModuleFractal().also {
|
|
||||||
it.setType(ModuleFractal.FractalType.RIDGEMULTI)
|
|
||||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
|
||||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
|
||||||
it.setNumOctaves(2)
|
|
||||||
it.setFrequency(params.oreShapeFreq) // adjust the "density" of the caves
|
|
||||||
it.seed = seed shake oreMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
val oreShape2 = ModuleScaleOffset().also {
|
|
||||||
it.setSource(oreShape)
|
|
||||||
it.setScale(1.0)
|
|
||||||
it.setOffset(-0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
val orePerturbFractal = ModuleFractal().also {
|
|
||||||
it.setType(ModuleFractal.FractalType.FBM)
|
|
||||||
it.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
|
||||||
it.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
|
||||||
it.setNumOctaves(6)
|
|
||||||
it.setFrequency(params.oreShapeFreq * 3.0 / 4.0)
|
|
||||||
it.seed = seed shake orePerturbMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
val orePerturbScale = ModuleScaleOffset().also {
|
|
||||||
it.setSource(orePerturbFractal)
|
|
||||||
it.setScale(20.0)
|
|
||||||
it.setOffset(0.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val orePerturb = ModuleTranslateDomain().also {
|
|
||||||
it.setSource(oreShape2)
|
|
||||||
it.setAxisXSource(orePerturbScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
val oreSelectAttenuate = ModulePow().also {
|
|
||||||
it.setSource(ModuleGradient().also {
|
|
||||||
it.setGradient(0.0, 0.0, NOISEBOX_HEIGHT.toDouble() * 5, 100.0)
|
|
||||||
})
|
|
||||||
it.setPower(1.0 / 4.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val oreSelect = ModuleSelect().also {
|
|
||||||
it.setLowSource(0.0)
|
|
||||||
it.setHighSource(1.0)
|
|
||||||
it.setControlSource(orePerturb)
|
|
||||||
it.setThreshold(oreSelectAttenuate)
|
|
||||||
it.setFalloff(0.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return listOf(
|
|
||||||
Joise(oreSelect)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*infix fun Long.shake(other: Long): Long {
|
/*infix fun Long.shake(other: Long): Long {
|
||||||
var s0 = this
|
var s0 = this
|
||||||
var s1 = other
|
var s1 = other
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
|
|
||||||
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
||||||
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
||||||
val oreNum = it.getTileFromOre(mouseTileX, mouseTileY).item
|
val (oreNum, orePlacement) = it.getTileFromOre(mouseTileX, mouseTileY)
|
||||||
val wires = it.getAllWiresFrom(mouseTileX, mouseTileY)
|
val wires = it.getAllWiresFrom(mouseTileX, mouseTileY)
|
||||||
val fluid = it.getFluid(mouseTileX, mouseTileY)
|
val fluid = it.getFluid(mouseTileX, mouseTileY)
|
||||||
val wireCount = wires.first?.size?.toString() ?: "no"
|
val wireCount = wires.first?.size?.toString() ?: "no"
|
||||||
@@ -256,7 +256,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
App.fontSmallNumbers.draw(batch, "$ccO$TERRAIN$ccG$tileNum", gap + 7f*(tileCursX + 3), line(tileCursY))
|
App.fontSmallNumbers.draw(batch, "$ccO$TERRAIN$ccG$tileNum", gap + 7f*(tileCursX + 3), line(tileCursY))
|
||||||
App.fontSmallNumbers.draw(batch, "$ccO$WALL$ccG$wallNum", gap + 7f*(tileCursX + 3), line(tileCursY + 1))
|
App.fontSmallNumbers.draw(batch, "$ccO$WALL$ccG$wallNum", gap + 7f*(tileCursX + 3), line(tileCursY + 1))
|
||||||
// App.fontSmallNumbers.draw(batch, "$ccO$LIQUID$ccG${fluid.type.padEnd(3)}$ccO$BEAKER$ccG${fluid.amount.toIntAndFrac(2)}", gap + 7f*(tileCursX + 3), line(tileCursY + 2))
|
// App.fontSmallNumbers.draw(batch, "$ccO$LIQUID$ccG${fluid.type.padEnd(3)}$ccO$BEAKER$ccG${fluid.amount.toIntAndFrac(2)}", gap + 7f*(tileCursX + 3), line(tileCursY + 2))
|
||||||
App.fontSmallNumbers.draw(batch, "$ccO$ROCK$ccG$oreNum", gap + 7f*(tileCursX + 3), line(tileCursY + 2))
|
App.fontSmallNumbers.draw(batch, "$ccO$ROCK$ccG$oreNum.$orePlacement", gap + 7f*(tileCursX + 3), line(tileCursY + 2))
|
||||||
App.fontSmallNumbers.draw(batch, "$ccO$WIRE$ccG$wireCount ${ccY}X$ccO$mouseTileX ${ccY}Y$ccO$mouseTileY", gap + 7f*(tileCursX + 3), line(tileCursY + 3))
|
App.fontSmallNumbers.draw(batch, "$ccO$WIRE$ccG$wireCount ${ccY}X$ccO$mouseTileX ${ccY}Y$ccO$mouseTileY", gap + 7f*(tileCursX + 3), line(tileCursY + 3))
|
||||||
App.fontSmallNumbers.draw(batch, "$ccR$rawR $ccG$rawG $ccB$rawB $ccW$rawA", gap + 7f*(tileCursX + 3), line(tileCursY + 4))
|
App.fontSmallNumbers.draw(batch, "$ccR$rawR $ccG$rawG $ccB$rawB $ccW$rawA", gap + 7f*(tileCursX + 3), line(tileCursY + 4))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user