#include "ui/FrameScript_Object.hpp" #include "util/Lua.hpp" #include #include int32_t FrameScript_Object::s_objectTypes = 0; int32_t FrameScript_Object::CreateScriptMetaTable(lua_State* L, void (*a2)(lua_State* L)) { lua_createtable(L, 0, 0); lua_pushstring(L, "__index"); lua_createtable(L, 0, 0); a2(L); lua_settable(L, -3); return luaL_ref(L, LUA_REGISTRYINDEX); } void FrameScript_Object::FillScriptMethodTable(lua_State *L, FrameScript_Method methods[], int32_t count) { for (int32_t i = 0; i < count; i++) { lua_pushstring(L, methods[i].name); lua_pushcclosure(L, methods[i].method, 0); lua_settable(L, -3); } } FrameScript_Object::~FrameScript_Object() { if (this->m_onEvent.luaRef) { luaL_unref(FrameScript_GetContext(), LUA_REGISTRYINDEX, this->m_onEvent.luaRef); } } const char* FrameScript_Object::GetDisplayName() { const char* name = this->GetName(); return name ? name : ""; } FrameScript_Object::ScriptIx* FrameScript_Object::GetScriptByName(const char* name, FrameScript_Object::ScriptData& data) { if (!SStrCmpI(name, "OnEvent", STORM_MAX_STR)) { data.wrapper = "return function(self,event,...) %s end"; return &this->m_onEvent; } return nullptr; } int32_t FrameScript_Object::RegisterScriptEvent(const char* name) { auto event = FrameScript::s_scriptEventsHash.Ptr(name); if (!event) { return 0; } if (event->pendingSignalCount) { auto node = event->unregisterListeners.Head(); while (node) { if (node->listener == this) { break; } node = node->Next(); } if (node) { event->unregisterListeners.DeleteNode(node); } } auto node = event->listeners.Head(); while (node) { if (node->listener == this) { break; } node = node->Next(); } if (!node) { FrameScript_RegisterScriptEvent(this, event); } return 1; } void FrameScript_Object::RegisterScriptObject(const char* name) { auto L = FrameScript_GetContext(); if (!this->lua_registered) { // TODO // v4 = lua_taintexpected++ == -1; // v5 = lua_tainted; // if (!v4 && !lua_taintedclosure) { // lua_tainted = 0; // } lua_createtable(L, 0, 0); lua_pushnumber(L, 0.0); lua_pushlightuserdata(L, this); lua_rawset(L, -3); int32_t metatable = this->GetScriptMetaTable(); lua_rawgeti(L, LUA_REGISTRYINDEX, metatable); lua_setmetatable(L, -2); this->lua_objectRef = luaL_ref(L, LUA_REGISTRYINDEX); // TODO // if (lua_taintexpected && !lua_taintedclosure) { // lua_tainted = v5; // } // if (--lua_taintexpected <= 0) { // lua_taintexpected = 0; // } } this->lua_registered++; if (name) { int32_t v8 = 0; lua_pushstring(L, name); lua_rawget(L, LUA_GLOBALSINDEX); if (lua_type(L, -1)) { v8 = 1; } lua_settop(L, -2); if (!v8) { lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef); lua_pushstring(L, name); lua_insert(L, -2); lua_rawset(L, LUA_GLOBALSINDEX); } } } void FrameScript_Object::RunScript(ScriptIx const& script, int32_t argCount, const char* a4) { FrameScript_Execute(script.luaRef, this, argCount, a4 ? a4 : script.unk, nullptr); } void FrameScript_Object::UnregisterScriptObject(const char* name) { auto L = FrameScript_GetContext(); if (this->lua_registered > 0) { this->lua_registered--; if (this->lua_registered == 0) { lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef); lua_pushnumber(L, 0.0); lua_pushnil(L); lua_rawset(L, -3); lua_settop(L, -2); luaL_unref(L, LUA_REGISTRYINDEX, this->lua_objectRef); this->lua_objectRef = -2; } } if (name) { lua_pushnil(L); lua_pushstring(L, name); lua_insert(L, -2); lua_rawset(L, LUA_GLOBALSINDEX); } } FrameScript_Object* FrameScript_GetObjectThis(lua_State* L, int32_t type) { if (lua_type(L, 1) != LUA_TTABLE) { luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)"); } lua_rawgeti(L, 1, 0); auto object = static_cast(lua_touserdata(L, -1)); lua_settop(L, -2); if (!object) { luaL_error(L, "Attempt to find 'this' in non-framescript object"); } if (!object->IsA(type)) { luaL_error(L, "Wrong object type for member function"); } return object; }