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

222 lines
7.4 KiB
Kotlin

package ru.dbotthepony.kstarbound.lua.bindings
import org.classdump.luna.ByteString
import org.classdump.luna.Table
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.EntityDamageTeam
import ru.dbotthepony.kstarbound.defs.item.ItemDescriptor
import ru.dbotthepony.kstarbound.defs.quest.QuestArcDescriptor
import ru.dbotthepony.kstarbound.fromJsonFast
import ru.dbotthepony.kstarbound.lua.LuaEnvironment
import ru.dbotthepony.kstarbound.lua.from
import ru.dbotthepony.kstarbound.lua.get
import ru.dbotthepony.kstarbound.lua.iterator
import ru.dbotthepony.kstarbound.lua.luaFunction
import ru.dbotthepony.kstarbound.lua.set
import ru.dbotthepony.kstarbound.lua.tableOf
import ru.dbotthepony.kstarbound.lua.toByteString
import ru.dbotthepony.kstarbound.lua.toJsonFromLua
import ru.dbotthepony.kstarbound.lua.toVector2d
import ru.dbotthepony.kstarbound.util.SBPattern
import ru.dbotthepony.kstarbound.util.sbIntern
import ru.dbotthepony.kstarbound.util.valueOfOrNull
import ru.dbotthepony.kstarbound.world.entities.AnchorNetworkState
import ru.dbotthepony.kstarbound.world.entities.HumanoidActorEntity
import ru.dbotthepony.kstarbound.world.entities.NPCEntity
import ru.dbotthepony.kstarbound.world.entities.api.LoungeableEntity
fun provideNPCBindings(self: NPCEntity, lua: LuaEnvironment) {
val callbacks = lua.newTable()
lua.globals["npc"] = callbacks
callbacks["toAbsolutePosition"] = luaFunction { pos: Table ->
returnBuffer.setTo(from(self.toAbsolutePosition(toVector2d(pos))))
}
callbacks["species"] = luaFunction { returnBuffer.setTo(self.variant.species.key.toByteString()) }
callbacks["gender"] = luaFunction { returnBuffer.setTo(self.variant.humanoidIdentity.gender.jsonName.toByteString()) }
callbacks["humanoidIdentity"] = luaFunction { returnBuffer.setTo(from(Starbound.gson.toJsonTree(self.variant.humanoidIdentity))) }
callbacks["npcType"] = luaFunction { returnBuffer.setTo(self.variant.typeName.toByteString()) }
callbacks["seed"] = luaFunction { returnBuffer.setTo(self.variant.seed) }
callbacks["level"] = luaFunction { returnBuffer.setTo(self.variant.level) }
callbacks["dropPools"] = luaFunction { returnBuffer.setTo(tableOf(*self.dropPools.map { it.key.left().toByteString() }.toTypedArray())) }
callbacks["setDropPools"] = luaFunction { dropPools: Table? ->
self.dropPools.clear()
if (dropPools != null) {
for ((_, pool) in dropPools) {
self.dropPools.add(Registries.treasurePools.ref(pool.toString()))
}
}
}
// lol why
callbacks["energy"] = luaFunction { returnBuffer.setTo(self.energy) }
callbacks["maxEnergy"] = luaFunction { returnBuffer.setTo(self.maxEnergy) }
callbacks["say"] = luaFunction { line: ByteString, tags: Table?, config: Any? ->
val actualLine = if (tags != null) {
SBPattern.of(line.decode()).resolveOrSkip({ tags[it]?.toString() })
} else {
line.decode()
}
val isNotEmpty = actualLine.isNotEmpty()
if (isNotEmpty)
self.addChatMessage(actualLine, toJsonFromLua(config))
returnBuffer.setTo(isNotEmpty)
}
callbacks["sayPortrait"] = luaFunction { line: ByteString, portrait: ByteString, tags: Table?, config: Any? ->
val actualLine = if (tags != null) {
SBPattern.of(line.decode()).resolveOrSkip({ tags[it]?.toString() })
} else {
line.decode()
}
val isNotEmpty = actualLine.isNotEmpty()
if (isNotEmpty)
self.addChatMessage(actualLine, toJsonFromLua(config), portrait.decode())
returnBuffer.setTo(isNotEmpty)
}
callbacks["emote"] = luaFunction { emote: ByteString ->
self.addEmote(emote.decode())
}
callbacks["dance"] = luaFunction { dance: ByteString ->
self.setDance(dance.decode())
}
callbacks["setInteractive"] = luaFunction { isInteractive: Boolean ->
self.isInteractive = isInteractive
}
callbacks["setLounging"] = luaFunction { loungeable: Number, oAnchorIndex: Number? ->
val anchorIndex = oAnchorIndex?.toInt() ?: 0
val entity = self.world.entities[loungeable.toInt()] as? LoungeableEntity
if (entity == null || anchorIndex !in 0 until entity.anchors.size || entity.entitiesLoungingIn(anchorIndex).isNotEmpty()) {
returnBuffer.setTo(false)
} else {
self.movement.anchorNetworkState = AnchorNetworkState(loungeable.toInt(), anchorIndex)
returnBuffer.setTo(true)
}
}
callbacks["resetLounging"] = luaFunction {
self.movement.anchorNetworkState = null
}
callbacks["isLounging"] = luaFunction {
returnBuffer.setTo(self.movement.anchorNetworkState != null)
}
callbacks["loungingIn"] = luaFunction {
returnBuffer.setTo(self.movement.anchorNetworkState?.entityID)
}
callbacks["setOfferedQuests"] = luaFunction { values: Table? ->
self.offeredQuests.clear()
if (values != null) {
for ((_, quest) in values) {
self.offeredQuests.add(Starbound.gson.fromJsonFast(toJsonFromLua(quest), QuestArcDescriptor::class.java))
}
}
}
callbacks["setTurnInQuests"] = luaFunction { values: Table? ->
self.turnInQuests.clear()
if (values != null) {
for ((_, value) in values) {
self.turnInQuests.add(value.toString())
}
}
}
callbacks["setItemSlot"] = luaFunction { slot: ByteString, descriptor: Any ->
returnBuffer.setTo(self.setItem(slot.decode(), ItemDescriptor(descriptor)))
}
callbacks["getItemSlot"] = luaFunction { slot: ByteString ->
val decoded = slot.decode()
val slotType = HumanoidActorEntity.ItemSlot.entries.valueOfOrNull(decoded.lowercase())
if (slotType == null) {
if (decoded in self.variant.items) {
returnBuffer.setTo(self.variant.items[decoded]!!.toTable(this))
} else {
returnBuffer.setTo()
}
} else {
returnBuffer.setTo(self.getItem(slotType).toTable(this))
}
}
callbacks["disableWornArmor"] = luaFunction { disable: Boolean ->
self.disableWornArmor = disable
}
callbacks["beginPrimaryFire"] = luaFunction { self.beginPrimaryFire() }
callbacks["beginAltFire"] = luaFunction { self.beginSecondaryFire() }
callbacks["beginSecondaryFire"] = luaFunction { self.beginSecondaryFire() }
callbacks["endPrimaryFire"] = luaFunction { self.endPrimaryFire() }
callbacks["endAltFire"] = luaFunction { self.endSecondaryFire() }
callbacks["endSecondaryFire"] = luaFunction { self.endSecondaryFire() }
callbacks["setShifting"] = luaFunction { value: Boolean ->
self.isShifting = value
}
callbacks["setDamageOnTouch"] = luaFunction { value: Boolean ->
self.damageOnTouch = value
}
callbacks["aimPosition"] = luaFunction {
returnBuffer.setTo(from(self.aimPosition))
}
callbacks["setAimPosition"] = luaFunction { pos: Table ->
self.aimPosition = self.world.geometry.diff(toVector2d(pos), self.position)
}
callbacks["setDeathParticleBurst"] = luaFunction { value: ByteString? ->
self.deathParticleBurst = value?.decode()?.sbIntern()
}
callbacks["setStatusText"] = luaFunction { value: ByteString? ->
self.statusText = value?.decode()?.sbIntern()
}
callbacks["setDisplayNametag"] = luaFunction { value: Boolean ->
self.displayNametag = value
}
callbacks["setPersistent"] = luaFunction { value: Boolean ->
self.isPersistent = value
}
callbacks["setKeepAlive"] = luaFunction { value: Boolean ->
self.keepAlive = value
}
callbacks["setAggressive"] = luaFunction { value: Boolean ->
self.isAggressive = value
}
callbacks["setDamageTeam"] = luaFunction { value: Table ->
self.team.accept(Starbound.gson.fromJsonFast(toJsonFromLua(value), EntityDamageTeam::class.java))
}
callbacks["setUniqueId"] = luaFunction { value: ByteString? ->
self.uniqueID.accept(value?.decode()?.sbIntern())
}
}