From fd533a2ec5a9f642b3449442533b18606bf75ead Mon Sep 17 00:00:00 2001 From: Seggan Date: Mon, 29 Jan 2024 15:19:45 -0500 Subject: [PATCH] `SimplePerlin` --- .../addoncommunity/galactifun/Galactifun2.kt | 70 +++++++ .../galactifun/scripting/dsl/PlanetBuilder.kt | 4 + .../scripting/dsl/gen/AbstractPerlin.kt | 6 +- .../galactifun/scripting/dsl/gen/NoiseMap.kt | 9 +- .../scripting/dsl/gen/PerlinBuilder.kt | 8 +- .../scripting/dsl/gen/SimpleBlocksBuilder.kt | 55 ++++++ .../scripting/dsl/gen/SimplePerlinBuilder.kt | 174 ++++++++++++++++++ 7 files changed, 317 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimpleBlocksBuilder.kt create mode 100644 src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimplePerlinBuilder.kt diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt index 68b3e25..cc2fb3c 100644 --- a/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt @@ -2,23 +2,33 @@ package io.github.addoncommunity.galactifun import co.aikar.commands.PaperCommandManager import io.github.addoncommunity.galactifun.api.objects.planet.PlanetaryWorld +import io.github.addoncommunity.galactifun.api.objects.properties.Distance.Companion.au +import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.Gas +import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.composition import io.github.addoncommunity.galactifun.base.BaseUniverse import io.github.addoncommunity.galactifun.core.Gf2Command import io.github.addoncommunity.galactifun.core.managers.WorldManager import io.github.addoncommunity.galactifun.scripting.PlanetScript +import io.github.addoncommunity.galactifun.scripting.dsl.* +import io.github.addoncommunity.galactifun.scripting.dsl.gen.* import io.github.addoncommunity.galactifun.scripting.evalScript +import io.github.addoncommunity.galactifun.util.years import io.github.seggan.kfun.AbstractAddon import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion import io.github.thebusybiscuit.slimefun4.implementation.Slimefun import io.github.thebusybiscuit.slimefun4.libraries.paperlib.PaperLib import org.bstats.bukkit.Metrics import org.bukkit.Bukkit +import org.bukkit.Material +import org.bukkit.block.Biome import org.bukkit.plugin.java.JavaPlugin import java.util.logging.Level import kotlin.script.experimental.api.ResultValue import kotlin.script.experimental.api.ScriptDiagnostic import kotlin.script.experimental.api.valueOrThrow import kotlin.script.experimental.host.toScriptSource +import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.hours class Galactifun2 : AbstractAddon() { @@ -118,6 +128,8 @@ class Galactifun2 : AbstractAddon() { "###################################################" ) } + + doTestingStuff() } override fun onDisable() { @@ -127,6 +139,64 @@ class Galactifun2 : AbstractAddon() { override fun getJavaPlugin(): JavaPlugin = this override fun getBugTrackerURL(): String = "https://github.com/Slimefun-Addon-Community/Galactifun2/issues" + + private fun doTestingStuff() { + val script = object : PlanetScript() {} + + script.planet { + name = "Mars" + item = Material.RED_CONCRETE + orbiting = BaseUniverse.solarSystem + orbit { + distance = 1.52.au + yearLength = 1.88.years + } + dayCycle = (1.days + 0.65.hours).long + + atmosphere { + pressure = 0.006 + + composition { + 95 percent Gas.CARBON_DIOXIDE + 2.8 percent Gas.NITROGEN + 2 percent Gas.ARGON + 0.2 percent Gas.OXYGEN + } + } + + world { + generator(SimplePerlin) { + configNoise { + scale = 0.01 + frequency = 0.5 + amplitude = 0.1 + smoothen = true + } + + averageHeight = 50 + maxDeviation = 20 + + blocks { + Material.RED_SAND top 2 + + fillInRestWith(random { + Material.RED_SANDSTONE withWeight 0.8f + Material.IRON_ORE withWeight 0.2f + }) + } + + singleBiome(Biome.DESERT) + } + } + } + + for (planet in script.toRegister) { + if (planet is PlanetaryWorld) { + planet.register() + } + log("Registered planet: ${planet.name}") + } + } } private var instance: Galactifun2? = null diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/PlanetBuilder.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/PlanetBuilder.kt index 3ecd6e3..3a8c1ad 100644 --- a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/PlanetBuilder.kt +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/PlanetBuilder.kt @@ -81,4 +81,8 @@ fun PlanetBuilder.eternal(ticks: Int): DayCycle = DayCycle.eternal(ticks) fun PlanetBuilder.atmosphere(block: AtmosphereBuilder.() -> Unit) { atmosphere = Atmosphere.buildAtmosphere(block) +} + +fun PlanetBuilder.world(block: WorldBuilder.() -> Unit) { + worldConfig = WorldBuilder().apply(block) } \ No newline at end of file diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/AbstractPerlin.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/AbstractPerlin.kt index b1800ba..3ddb9d4 100644 --- a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/AbstractPerlin.kt +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/AbstractPerlin.kt @@ -1,5 +1,6 @@ package io.github.addoncommunity.galactifun.scripting.dsl.gen +import io.github.addoncommunity.galactifun.scripting.PlanetDsl import io.github.addoncommunity.galactifun.scripting.RequiredProperty abstract class AbstractPerlin : GeneratorBuilder() { @@ -7,15 +8,16 @@ abstract class AbstractPerlin : GeneratorBuilder() { var averageHeight: Int by RequiredProperty() var maxDeviation: Int by RequiredProperty() - var minHeight: Int by RequiredProperty() + var minY = Int.MIN_VALUE var surfaceHeight = 10 + @PlanetDsl class PerlinConfig { var octaves: Int = 8 var scale: Double by RequiredProperty() var amplitude: Double by RequiredProperty() var frequency: Double by RequiredProperty() - var flattenFactor: Double = 1.0 + var smoothen: Boolean = false } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/NoiseMap.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/NoiseMap.kt index b9e7485..5682e70 100644 --- a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/NoiseMap.kt +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/NoiseMap.kt @@ -3,7 +3,6 @@ package io.github.addoncommunity.galactifun.scripting.dsl.gen import io.github.addoncommunity.galactifun.util.gen.DoubleChunkGrid import org.bukkit.util.noise.OctaveGenerator import org.bukkit.util.noise.SimplexOctaveGenerator -import kotlin.math.pow class NoiseMap(noises: Map) { @@ -27,7 +26,7 @@ class NoiseMap(noises: Map) { private val scale = config.scale private val amplitude = config.amplitude private val frequency = config.frequency - private val flattenFactor = config.flattenFactor + private val smoothen = config.smoothen @Volatile private lateinit var noise: OctaveGenerator @@ -41,7 +40,11 @@ class NoiseMap(noises: Map) { operator fun invoke(x: Int, z: Int): Double { return grid.getOrSet(x, z) { - noise.noise(x.toDouble(), z.toDouble(), frequency, amplitude, true).pow(flattenFactor) + var noise = noise.noise(x.toDouble(), z.toDouble(), frequency, amplitude, true) + if (smoothen) { + noise *= noise + } + noise } } } diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/PerlinBuilder.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/PerlinBuilder.kt index a0dc2e2..0a834eb 100644 --- a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/PerlinBuilder.kt +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/PerlinBuilder.kt @@ -23,7 +23,7 @@ class PerlinBuilder : AbstractPerlin(), NoiseCombiner { override fun build(): WorldGenerator { val averageHeight = averageHeight val maxDeviation = maxDeviation - val minHeight = minHeight + if (generateBedrock) 1 else 0 + val minHeight = minY + if (generateBedrock) 1 else 0 val noises = NoiseMap(noises) @@ -31,8 +31,6 @@ class PerlinBuilder : AbstractPerlin(), NoiseCombiner { override val biomeProvider = biomeBuilder?.build(noises) ?: this@PerlinBuilder.biomeProvider - fun getMinHeight(worldInfo: WorldInfo): Int = minHeight.coerceAtLeast(worldInfo.minHeight) - override fun generateNoise( worldInfo: WorldInfo, random: Random, @@ -107,6 +105,8 @@ class PerlinBuilder : AbstractPerlin(), NoiseCombiner { val height = noiseCombiner(NoiseCombiner.NoiseInfo(worldInfo, noises, random, x, z)) return (height * maxDeviation + averageHeight).roundToInt() } + + private fun getMinHeight(worldInfo: WorldInfo): Int = minHeight.coerceAtLeast(worldInfo.minHeight) } } @@ -156,7 +156,7 @@ fun PerlinBuilder.generateBlock(block: PerlinBuilder.GenInfo.() -> Material) { noiseGenerator = block } -fun PerlinBuilder.noiseConfig(name: String, config: AbstractPerlin.PerlinConfig.() -> Unit) { +fun PerlinBuilder.configNoise(name: String, config: AbstractPerlin.PerlinConfig.() -> Unit) { noises[name] = AbstractPerlin.PerlinConfig().apply(config) } diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimpleBlocksBuilder.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimpleBlocksBuilder.kt new file mode 100644 index 0000000..5d693cd --- /dev/null +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimpleBlocksBuilder.kt @@ -0,0 +1,55 @@ +package io.github.addoncommunity.galactifun.scripting.dsl.gen + +import io.github.addoncommunity.galactifun.scripting.PlanetDsl +import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.RandomizedSet +import org.bukkit.Material + + +typealias BlockProvider = SimplePerlinBuilder.GenInfo.() -> Material + +@PlanetDsl +class SimpleBlocksBuilder { + + var top = mutableListOf() + var bottom = mutableListOf() + var middle: BlockProvider = { Material.AIR } + + private fun addN(n: Int, list: MutableList, block: BlockProvider) { + repeat(n) { + list.add(block) + } + } + + infix fun BlockProvider.top(n: Int) = addN(n, top, this) + + infix fun Material.top(n: Int) = addN(n, top) { this@top } + + infix fun BlockProvider.bottom(n: Int) = addN(n, bottom, this) + + infix fun Material.bottom(n: Int) = addN(n, bottom) { this@bottom } + + @PlanetDsl + class RandomBuilder { + internal val selector = RandomizedSet() + + infix fun Material.withWeight(weight: Float) { + selector.add(this, weight) + } + } +} + +fun SimpleBlocksBuilder.fillInRestWith(block: BlockProvider) { + middle = block +} + +fun SimpleBlocksBuilder.fillInRestWith(material: Material) { + middle = { material } +} + +fun SimpleBlocksBuilder.random(block: SimpleBlocksBuilder.RandomBuilder.() -> Unit): BlockProvider { + val builder = SimpleBlocksBuilder.RandomBuilder() + builder.block() + return { + builder.selector.getRandom(random) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimplePerlinBuilder.kt b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimplePerlinBuilder.kt new file mode 100644 index 0000000..890f068 --- /dev/null +++ b/src/main/kotlin/io/github/addoncommunity/galactifun/scripting/dsl/gen/SimplePerlinBuilder.kt @@ -0,0 +1,174 @@ +package io.github.addoncommunity.galactifun.scripting.dsl.gen + +import io.github.addoncommunity.galactifun.api.objects.planet.gen.WorldGenerator +import io.github.addoncommunity.galactifun.scripting.PlanetDsl +import io.github.addoncommunity.galactifun.scripting.RequiredProperty +import org.bukkit.Material +import org.bukkit.generator.WorldInfo +import org.bukkit.util.noise.OctaveGenerator +import org.bukkit.util.noise.SimplexOctaveGenerator +import java.util.* +import kotlin.math.roundToInt + +@PlanetDsl +class SimplePerlinBuilder : AbstractPerlin() { + + var noiseConfig: PerlinConfig by RequiredProperty() + + var blocks: SimpleBlocksBuilder by RequiredProperty() + + override fun build(): WorldGenerator { + val octaves = noiseConfig.octaves + val scale = noiseConfig.scale + val frequency = noiseConfig.frequency + val amplitude = noiseConfig.amplitude + val smoothen = noiseConfig.smoothen + val averageHeight = averageHeight + val maxDeviation = maxDeviation + + val top = blocks.top + val bottom = blocks.bottom + val middle = blocks.middle + + val minHeight = minY + if (generateBedrock) 1 else 0 + val surfaceHeight = top.size + + return object : WorldGenerator() { + + override val biomeProvider = this@SimplePerlinBuilder.biomeProvider + + @Volatile + private lateinit var baseNoise: OctaveGenerator + + override fun generateNoise( + worldInfo: WorldInfo, + random: Random, + chunkX: Int, + chunkZ: Int, + chunkData: ChunkData + ) { + val cx = chunkX * 16 + val cz = chunkZ * 16 + val info = GenInfo(worldInfo, random, chunkX, chunkZ) + val min = getMinHeight(worldInfo) + bottom.size + for (x in 0..15) { + for (z in 0..15) { + val realX = cx + x + val realZ = cz + z + val height = getHeight(worldInfo, realX, realZ) + info.x = realX + info.z = realZ + info.height = height + for (y in min until height - surfaceHeight) { + info.y = y + chunkData.setBlock(x, y, z, middle(info)) + } + } + } + } + + override fun generateSurface( + worldInfo: WorldInfo, + random: Random, + chunkX: Int, + chunkZ: Int, + chunkData: ChunkData + ) { + val cx = chunkX * 16 + val cz = chunkZ * 16 + val info = GenInfo(worldInfo, random, chunkX, chunkZ) + for (x in 0..15) { + for (z in 0..15) { + val realX = cx + x + val realZ = cz + z + val height = getHeight(worldInfo, realX, realZ) + info.x = realX + info.z = realZ + info.height = height + info.y = height + for (topBlock in top) { + info.y-- + chunkData.setBlock(x, info.y, z, topBlock(info)) + } + } + } + } + + override fun generateBedrock( + worldInfo: WorldInfo, + random: Random, + chunkX: Int, + chunkZ: Int, + chunkData: ChunkData + ) { + var y = getMinHeight(worldInfo) + if (generateBedrock) { + for (x in 0..15) { + for (z in 0..15) { + chunkData.setBlock(x, y, z, Material.BEDROCK) + } + } + y++ + } + if (bottom.isEmpty()) return + val cx = chunkX * 16 + val cz = chunkZ * 16 + val info = GenInfo(worldInfo, random, chunkX, chunkZ) + for (x in 0..15) { + for (z in 0..15) { + val realX = cx + x + val realZ = cz + z + val height = getHeight(worldInfo, realX, realZ) + info.x = realX + info.z = realZ + info.height = height + info.y = y + for (bottomBlock in bottom) { + chunkData.setBlock(x, info.y, z, bottomBlock(info)) + info.y++ + } + } + } + } + + private fun getHeight(worldInfo: WorldInfo, x: Int, z: Int): Int { + if (!::baseNoise.isInitialized) { + baseNoise = SimplexOctaveGenerator(worldInfo.seed, octaves) + baseNoise.setScale(scale) + } + + var height = baseNoise.noise(x.toDouble(), z.toDouble(), frequency, amplitude, true) + if (smoothen) { + height *= height + } + return (height * maxDeviation + averageHeight).roundToInt() + } + + private fun getMinHeight(worldInfo: WorldInfo): Int = minHeight.coerceAtLeast(worldInfo.minHeight) + } + } + + data class GenInfo( + val world: WorldInfo, + val random: Random, + val chunkX: Int, + val chunkZ: Int, + ) { + var x: Int = 0 + var y: Int = 0 + var z: Int = 0 + var height: Int = 0 + } +} + +inline fun SimplePerlinBuilder.configNoise(block: AbstractPerlin.PerlinConfig.() -> Unit) { + noiseConfig = AbstractPerlin.PerlinConfig().apply(block) +} + +inline fun SimplePerlinBuilder.blocks(block: SimpleBlocksBuilder.() -> Unit) { + blocks = SimpleBlocksBuilder().apply(block) +} + +object SimplePerlin : GeneratorBuilderProvider { + override fun provide(): SimplePerlinBuilder = SimplePerlinBuilder() +} \ No newline at end of file