Skip to content

Commit

Permalink
Change to MultiNoise
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Jan 27, 2024
1 parent 6309bd5 commit 8dd383c
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import io.github.addoncommunity.galactifun.scripting.RequiredProperty

@PlanetDsl
abstract class AbstractPerlin : GeneratorBuilder() {

var config: PerlinConfig by RequiredProperty()

var generateBedrock = true

var averageHeight: Int by RequiredProperty()
var maxDeviation: Int by RequiredProperty()
var minHeight: Int by RequiredProperty()
var surfaceHeight = 10

Expand All @@ -21,10 +19,5 @@ abstract class AbstractPerlin : GeneratorBuilder() {
var frequency: Double by RequiredProperty()

var flattenFactor: Double = 1.0
var smoothen: Boolean = false
}
}

inline fun AbstractPerlin.noiseConfig(block: AbstractPerlin.PerlinConfig.() -> Unit) {
config = AbstractPerlin.PerlinConfig().apply(block)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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<String, AbstractPerlin.PerlinConfig>) {

private val noises = noises.mapValues { Noise(it.value) }

@Volatile
private var initted = false

internal fun init(seed: Long) {
if (initted) return
synchronized(this) {
if (initted) return
noises.values.forEach { it.init(seed) }
initted = true
}
}

class Noise internal constructor(config: AbstractPerlin.PerlinConfig) {

private val octaves = config.octaves
private val scale = config.scale
private val amplitude = config.amplitude
private val frequency = config.frequency
private val flattenFactor = config.flattenFactor

@Volatile
private lateinit var noise: OctaveGenerator

private val grid = DoubleChunkGrid()

internal fun init(seed: Long) {
noise = SimplexOctaveGenerator(seed, octaves)
noise.setScale(scale)
}

operator fun invoke(x: Int, z: Int): Double {
return grid.getOrSet(x, z) {
noise.noise(x.toDouble(), z.toDouble(), frequency, amplitude, true).pow(flattenFactor)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@
package io.github.addoncommunity.galactifun.scripting.dsl.gen

import io.github.addoncommunity.galactifun.api.objects.planet.gen.WorldGenerator
import io.github.addoncommunity.galactifun.scripting.RequiredProperty
import org.bukkit.Material
import org.bukkit.generator.WorldInfo
import org.bukkit.util.noise.SimplexOctaveGenerator
import java.util.*
import kotlin.math.pow
import kotlin.math.roundToInt

class PerlinBuilder : AbstractPerlin() {

var noiseGenerator: (WorldInfo, Random, Int, Int, Int, Int) -> Material =
{ _, _, _, _, _, _ -> Material.AIR }

var surfaceGenerator: (WorldInfo, Random, Int, Int, Int, Int) -> Material =
{ _, _, _, _, _, _ -> Material.AIR }
var noiseGenerator: GenInfo.() -> Material by RequiredProperty()
var noiseCombiner: NoiseInfo.() -> Double by RequiredProperty()

val noises = mutableMapOf<String, PerlinConfig>()

override fun build(): WorldGenerator {
// Prevent performance issues by unboxing before building the generator
val octaves = config.octaves
val scale = config.scale
val amplitude = config.amplitude
val frequency = config.frequency
val flattenFactor = config.flattenFactor
val smoothen = config.smoothen

val averageHeight = averageHeight
val maxDeviation = maxDeviation
val minHeight = minHeight + if (generateBedrock) 1 else 0

val noises = NoiseMap(noises)

return object : WorldGenerator() {
override val biomeProvider = this@PerlinBuilder.biomeProvider

@Volatile
private lateinit var baseNoise: SimplexOctaveGenerator
override val biomeProvider = this@PerlinBuilder.biomeProvider

fun getMinHeight(worldInfo: WorldInfo): Int = minHeight.coerceAtLeast(worldInfo.minHeight)

Expand All @@ -46,11 +37,18 @@ class PerlinBuilder : AbstractPerlin() {
val cx = chunkX * 16
val cz = chunkZ * 16
val min = getMinHeight(worldInfo)
val info = GenInfo(worldInfo, random, chunkX, chunkZ)
for (x in 0..15) {
for (z in 0..15) {
val height = getHeight(worldInfo, cx + x, cz + z)
val realX = cx + x
val realZ = cz + z
val height = getHeight(worldInfo, random, realX, realZ)
info.x = realX
info.z = realZ
info.height = height
for (y in min until height - surfaceHeight) {
chunkData.setBlock(x, y, z, noiseGenerator(worldInfo, random, cx + x, y, cz + z, height))
info.y = y
chunkData.setBlock(x, y, z, noiseGenerator(info))
}
}
}
Expand All @@ -65,11 +63,18 @@ class PerlinBuilder : AbstractPerlin() {
) {
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 height = getHeight(worldInfo, cx + x, cz + z)
val realX = cx + x
val realZ = cz + z
val height = getHeight(worldInfo, random, realX, realZ)
info.x = realX
info.z = realZ
info.height = height
for (y in height - surfaceHeight until height) {
chunkData.setBlock(x, y, z, surfaceGenerator(worldInfo, random, cx + x, y, cz + z, height))
info.y = y
chunkData.setBlock(x, y, z, noiseGenerator(info))
}
}
}
Expand All @@ -91,32 +96,41 @@ class PerlinBuilder : AbstractPerlin() {
}
}

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)
height = height.pow(flattenFactor)
height = (height + 1) / 2
return (height * (averageHeight - minHeight)).toInt()
private fun getHeight(worldInfo: WorldInfo, random: Random, x: Int, z: Int): Int {
noises.init(worldInfo.seed)
val height = noiseCombiner(NoiseInfo(worldInfo, noises, random, x, z))
return (height * maxDeviation + averageHeight).roundToInt()
}
}
}

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
}

data class NoiseInfo(val world: WorldInfo, val noise: NoiseMap, val random: Random, val x: Int, val z: Int)
}

fun PerlinBuilder.generateNoiseBlock(
block: (WorldInfo, Random, Int, Int, Int, Int) -> Material
) {
fun PerlinBuilder.generateBlock(block: PerlinBuilder.GenInfo.() -> Material) {
noiseGenerator = block
}

fun PerlinBuilder.generateSurfaceBlock(
block: (WorldInfo, Random, Int, Int, Int, Int) -> Material
) {
surfaceGenerator = block
fun PerlinBuilder.combineNoise(noise: PerlinBuilder.NoiseInfo.() -> Double) {
noiseCombiner = noise
}

fun PerlinBuilder.noiseConfig(name: String, config: AbstractPerlin.PerlinConfig.() -> Unit) {
noises[name] = AbstractPerlin.PerlinConfig().apply(config)
}

object Perlin : GeneratorBuilderProvider<PerlinBuilder> {
object MultiNoise : GeneratorBuilderProvider<PerlinBuilder> {
override fun provide() = PerlinBuilder()
}

0 comments on commit 8dd383c

Please sign in to comment.