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 }