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()) } }