From 23f6401a933372c7f9bc64872b790a4826ac06e1 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 26 Feb 2025 15:58:12 -0500 Subject: [PATCH] Improve invoke_lua_call and probe_lua_call, don't pass actor/place, better support for classname/funcname --- Content/Tangibles/tangiblecharacter.uasset | 4 +- luprex/cpp/core/world-core.cpp | 96 +++++++++++----------- luprex/cpp/core/world.hpp | 2 +- luprex/lua/login.lua | 6 +- 4 files changed, 56 insertions(+), 52 deletions(-) diff --git a/Content/Tangibles/tangiblecharacter.uasset b/Content/Tangibles/tangiblecharacter.uasset index 74a55083..776ef78e 100644 --- a/Content/Tangibles/tangiblecharacter.uasset +++ b/Content/Tangibles/tangiblecharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bfe3336e004d5bb19e9cffb6d3c4cf9caa90dbc597a51ee137ed301cc92f5cce -size 335772 +oid sha256:e1504e7d8d446acad328fd7c178e86bf8c874eb71d53b975837988ef7992f2ee +size 334577 diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 65b25c23..2f7e1bf1 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -345,7 +345,7 @@ int64_t World::create_login_actor() { if (is_authoritative()) { LS.rawget(func, classtab, "init"); - spawn(LS, id, id, func, true, 0, false); + spawn(LS, id, id, func, 0, false); } } if (is_authoritative()) { @@ -440,12 +440,9 @@ void World::probe_lua_call(int64_t place_id, int64_t actor_id, std::string_view } catch (const StreamException &ex) { return; } - if ((!sv::is_lua_id(classname)) || (!sv::is_lua_id(funcname))) { - return; - } - LuaVar lclass, lfunc, actor, place, tangibles, retvec, retval; - LuaExtStack LS(L, lclass, lfunc, actor, place, tangibles, retvec, retval); + LuaVar lclass, lfunc, actor, place, mt, tangibles, retvec, retval; + LuaExtStack LS(L, lclass, lfunc, actor, place, mt, tangibles, retvec, retval); // Get the actor and place, lua version. Make sure both exist. LS.rawget(tangibles, LuaRegistry, "tangibles"); @@ -455,21 +452,26 @@ void World::probe_lua_call(int64_t place_id, int64_t actor_id, std::string_view return; } - // Get the class table and closure - eng::string err = LS.getclass(lclass, classname); - if ((!err.empty()) || (!LS.istable(lclass))) { - return; + // Get the class. If the classname is *, then use the class of the place. + if (classname == "*") { + LS.getmetatable(mt, place); + if (!LS.istable(mt)) return; + LS.rawget(lclass, mt, "__index"); + } else { + LS.getclass(lclass, classname); } + + // Get the true classname. This also checks validity of the class. + classname = LS.classname(lclass); + if (classname.empty()) return; + + // Get the function from the class. LS.rawget(lfunc, lclass, funcname); - if (!LS.isfunction(lfunc)) { - return; - } + if (!LS.isfunction(lfunc)) return; // Call the closure. lua_pushvalue(L, lfunc.index()); - lua_pushvalue(L, actor.index()); - lua_pushvalue(L, place.index()); - int nargs = 2; + int nargs = 0; try { while (!datasb.empty()) { push_simple_dynamic(L, &datasb); @@ -738,7 +740,7 @@ void World::invoke(const Invocation &inv) { } bool World::spawn(LuaCoreStack &LS0, int64_t actor_id, int64_t place_id, LuaSlot func, - bool passactorplace, int nargs, bool print) { + int nargs, bool print) { lua_State *L = LS0.state(); LuaVar actor, place, mt, index, tangibles, thread, threads, thinfo; LuaExtStack LS(L, actor, place, mt, index, tangibles, thread, threads, thinfo); @@ -783,14 +785,10 @@ bool World::spawn(LuaCoreStack &LS0, int64_t actor_id, int64_t place_id, LuaSlot return false; } - // Create a new thread. Push function, and maybe actor and place. + // Create a new thread. Push function. lua_State *CO = LS.newthread(thread); lua_pushvalue(L, func.index()); - if (passactorplace) { - lua_pushvalue(L, actor.index()); - lua_pushvalue(L, place.index()); - } - lua_xmove(L, CO, passactorplace ? 3:1); + lua_xmove(L, CO, 1); // Push any extra arguments. Extra arguments were pushed onto // the lua stack before calling spawn, so they are located at oldtop. @@ -858,21 +856,19 @@ void World::invoke_lua_expr(int64_t actor_id, int64_t place_id, std::string_view // Spawn the thread and run it. int nargs = 0; - spawn(LS, actor_id, place_id, func, false, nargs, true); + spawn(LS, actor_id, place_id, func, nargs, true); } run_scheduled_threads(); assert(stack_is_clear()); } -volatile int vx; - void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view datapack) { assert(stack_is_clear()); // Use a streambuffer to parse the datapack. StreamBuffer datasb(datapack); - // Extract the class and function name from the datapack. + // Extract the class name and function name from the datapack. eng::string classname; eng::string funcname; try { @@ -881,29 +877,33 @@ void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view } catch (const StreamException &ex) { return; } - if ((!sv::is_lua_id(classname)) || (!sv::is_lua_id(funcname))) { - return; - } - // TODO: Add support for the wildcard classname. - // TODO: Add check for permit_invoke(classname, funcname) - - if (funcname == "printhi") { - vx = 0; - } + { lua_State *L = state(); - LuaVar lclass, lfunc; - LuaExtStack LS(L, lclass, lfunc); - - // Get the class table and closure - eng::string err = LS.getclass(lclass, classname); - if ((!err.empty()) || (!LS.istable(lclass))) { - return; + LuaVar tangibles, place, mt, lclass, lfunc; + LuaExtStack LS(L, tangibles, place, mt, lclass, lfunc); + + // Get the class. If the classname is *, then use the class of the place. + if (classname == "*") { + LS.rawget(tangibles, LuaRegistry, "tangibles"); + LS.rawget(place, tangibles, place_id); + if (LS.isnil(place)) return; + LS.getmetatable(mt, place); + if (!LS.istable(mt)) return; + LS.rawget(lclass, mt, "__index"); + } else { + LS.getclass(lclass, classname); } + + // Get the true classname. This also checks validity of the class. + classname = LS.classname(lclass); + if (classname.empty()) return; + + // TODO: CHECK FOR PERMIT_INVOKE. + + // Get the function from the class. LS.rawget(lfunc, lclass, funcname); - if (!LS.isfunction(lfunc)) { - return; - } + if (!LS.isfunction(lfunc)) return; // Spawn a thread, pushing extra arguments from the datapack. int nargs = 0; @@ -915,8 +915,10 @@ void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view } catch (const StreamException &exc) { return; } - spawn(LS, actor_id, place_id, lfunc, true, nargs, false); + spawn(LS, actor_id, place_id, lfunc, nargs, false); } + + // Run the new thread and return. run_scheduled_threads(); assert(stack_is_clear()); } diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index d9ab3931..fdc44b72 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -420,7 +420,7 @@ private: // Low level spawn thread function. // - bool spawn(LuaCoreStack &LS0, int64_t actor_id, int64_t place_id, LuaSlot func, bool passactorplace, int nargs, bool print); + bool spawn(LuaCoreStack &LS0, int64_t actor_id, int64_t place_id, LuaSlot func, int nargs, bool print); public: //////////////////////////////////////////////////////////////////////////// diff --git a/luprex/lua/login.lua b/luprex/lua/login.lua index ff961260..99cb59a6 100644 --- a/luprex/lua/login.lua +++ b/luprex/lua/login.lua @@ -10,15 +10,17 @@ function tree.init(self, config) wait(1) end -function login.init(actor, place) +function login.init() + local actor = tangible.actor() dprint("login.init:", actor) local x = math.random(1, 100) local y = math.random(1, 100) tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}}) end -function engio.move(actor, place, action, xyz, facing) +function engio.move(action, xyz, facing) -- todo: sanity check the parameters. + local actor = tangible.actor() dprint("engio.move ", action, " ", xyz[1], " ", xyz[2], " ", xyz[3]) tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing}) end