KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/lua/bindings/UtilityBindings.kt

136 lines
4.8 KiB
Kotlin

package ru.dbotthepony.kstarbound.lua.bindings
import org.apache.logging.log4j.LogManager
import org.classdump.luna.ByteString
import org.classdump.luna.Table
import ru.dbotthepony.kstarbound.math.vector.Vector2d
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
import ru.dbotthepony.kstarbound.lua.LuaEnvironment
import ru.dbotthepony.kstarbound.lua.from
import ru.dbotthepony.kstarbound.lua.get
import ru.dbotthepony.kstarbound.lua.luaFunction
import ru.dbotthepony.kstarbound.lua.luaFunctionArray
import ru.dbotthepony.kstarbound.lua.luaFunctionN
import ru.dbotthepony.kstarbound.lua.nextOptionalFloat
import ru.dbotthepony.kstarbound.lua.set
import ru.dbotthepony.kstarbound.lua.toJson
import ru.dbotthepony.kstarbound.lua.toVector2d
import ru.dbotthepony.kstarbound.lua.userdata.LuaPerlinNoise
import ru.dbotthepony.kstarbound.lua.userdata.LuaRandomGenerator
import ru.dbotthepony.kstarbound.math.Interpolator
import ru.dbotthepony.kstarbound.util.SBPattern
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise
import ru.dbotthepony.kstarbound.util.random.nextNormalDouble
import ru.dbotthepony.kstarbound.util.random.random
import ru.dbotthepony.kstarbound.util.random.staticRandom32
import ru.dbotthepony.kstarbound.util.random.staticRandomDouble
import ru.dbotthepony.kstarbound.util.random.staticRandomLong
import ru.dbotthepony.kstarbound.util.toStarboundString
import java.util.*
import java.util.random.RandomGenerator
private val LOGGER = LogManager.getLogger()
private val logInfo = luaFunctionN("logInfo") { args ->
LOGGER.info(args.nextString().toString().format(*args.copyRemaining()))
}
private val logWarn = luaFunctionN("logWarn") { args ->
LOGGER.warn(args.nextString().toString().format(*args.copyRemaining()))
}
private val logError = luaFunctionN("logError") { args ->
LOGGER.error(args.nextString().toString().format(*args.copyRemaining()))
}
private val interpolateSinEase = luaFunctionArray { args ->
if (args.size < 3)
throw IllegalArgumentException("Invalid amount of arguments to interpolateSinEase: ${args.size}")
val offset = args[0] as? Number ?: throw IllegalArgumentException("Invalid 'offset' argument: ${args[0]}")
if (args[1] is Number && args[2] is Number) {
returnBuffer.setTo(Interpolator.Sin.interpolate(offset.toDouble(), (args[1] as Number).toDouble(), (args[2] as Number).toDouble()))
} else {
// assume vectors
val a = toVector2d(args[1]!!)
val b = toVector2d(args[2]!!)
val result = Vector2d(
Interpolator.Sin.interpolate(offset.toDouble(), a.x, b.x),
Interpolator.Sin.interpolate(offset.toDouble(), a.y, b.y),
)
returnBuffer.setTo(from(result))
}
}
private val replaceTags = luaFunction { string: ByteString, tags: Table ->
returnBuffer.setTo(SBPattern.of(string.toString()).resolveOrSkip({ tags[it]?.toString() }))
}
private val makePerlinSource = luaFunction { settings: Table ->
returnBuffer.setTo(LuaPerlinNoise(AbstractPerlinNoise.of(Starbound.gson.fromJson(settings.toJson(), PerlinNoiseParameters::class.java))))
}
private val staticRandomI32 = luaFunctionArray {
returnBuffer.setTo(staticRandom32(*it))
}
private val staticRandomDouble = luaFunctionArray {
returnBuffer.setTo(staticRandomDouble(*it))
}
private val staticRandomDoubleRange = luaFunctionN("staticRandomDoubleRange") {
val min = it.nextFloat()
val max = it.nextFloat()
returnBuffer.setTo(staticRandomDouble(*it.copyRemaining()) * (max - min) + min)
}
private val staticRandomI32Range = luaFunctionN("staticRandomI32Range") {
val min = it.nextInteger()
val max = it.nextInteger()
returnBuffer.setTo(staticRandomLong(min, max, *it.copyRemaining()))
}
fun provideUtilityBindings(
lua: LuaEnvironment,
random: RandomGenerator = random()
) {
val table = lua.newTable()
lua.globals["sb"] = table
table["makeUuid"] = luaFunction {
returnBuffer.setTo(UUID(random.nextLong(), random.nextLong()).toStarboundString())
}
table["logInfo"] = logInfo
table["logWarn"] = logWarn
table["logError"] = logError
table["nrand"] = luaFunctionN("nrand") { args ->
val stdev = args.nextOptionalFloat() ?: 1.0
val mean = args.nextOptionalFloat() ?: 0.0
random.nextNormalDouble(stdev, mean)
}
table["print"] = lua.globals["tostring"]
table["printJson"] = lua.globals["tostring"]
table["interpolateSinEase"] = interpolateSinEase
table["replaceTags"] = replaceTags
table["makeRandomSource"] = luaFunction { seed: Long? ->
returnBuffer.setTo(LuaRandomGenerator(random(seed ?: random.nextLong())))
}
table["makePerlinSource"] = makePerlinSource
table["staticRandomI32"] = staticRandomI32
table["staticRandomI64"] = staticRandomI32
table["staticRandomDouble"] = staticRandomDouble
table["staticRandomDoubleRange"] = staticRandomDoubleRange
table["staticRandomI32Range"] = staticRandomI32Range
table["staticRandomI64Range"] = staticRandomI32Range
}