Improve invoke_lua_call and probe_lua_call, don't pass actor/place, better support for classname/funcname

This commit is contained in:
2025-02-26 15:58:12 -05:00
parent 72eda3026f
commit 23f6401a93
4 changed files with 56 additions and 52 deletions

Binary file not shown.

View File

@@ -345,7 +345,7 @@ int64_t World::create_login_actor() {
if (is_authoritative()) { if (is_authoritative()) {
LS.rawget(func, classtab, "init"); LS.rawget(func, classtab, "init");
spawn(LS, id, id, func, true, 0, false); spawn(LS, id, id, func, 0, false);
} }
} }
if (is_authoritative()) { 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) { } catch (const StreamException &ex) {
return; return;
} }
if ((!sv::is_lua_id(classname)) || (!sv::is_lua_id(funcname))) {
return;
}
LuaVar lclass, lfunc, actor, place, tangibles, retvec, retval; LuaVar lclass, lfunc, actor, place, mt, tangibles, retvec, retval;
LuaExtStack LS(L, lclass, lfunc, actor, place, 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. // Get the actor and place, lua version. Make sure both exist.
LS.rawget(tangibles, LuaRegistry, "tangibles"); 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; return;
} }
// Get the class table and closure // Get the class. If the classname is *, then use the class of the place.
eng::string err = LS.getclass(lclass, classname); if (classname == "*") {
if ((!err.empty()) || (!LS.istable(lclass))) { LS.getmetatable(mt, place);
return; 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); LS.rawget(lfunc, lclass, funcname);
if (!LS.isfunction(lfunc)) { if (!LS.isfunction(lfunc)) return;
return;
}
// Call the closure. // Call the closure.
lua_pushvalue(L, lfunc.index()); lua_pushvalue(L, lfunc.index());
lua_pushvalue(L, actor.index()); int nargs = 0;
lua_pushvalue(L, place.index());
int nargs = 2;
try { try {
while (!datasb.empty()) { while (!datasb.empty()) {
push_simple_dynamic(L, &datasb); 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 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(); lua_State *L = LS0.state();
LuaVar actor, place, mt, index, tangibles, thread, threads, thinfo; LuaVar actor, place, mt, index, tangibles, thread, threads, thinfo;
LuaExtStack LS(L, 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; 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_State *CO = LS.newthread(thread);
lua_pushvalue(L, func.index()); lua_pushvalue(L, func.index());
if (passactorplace) { lua_xmove(L, CO, 1);
lua_pushvalue(L, actor.index());
lua_pushvalue(L, place.index());
}
lua_xmove(L, CO, passactorplace ? 3:1);
// Push any extra arguments. Extra arguments were pushed onto // Push any extra arguments. Extra arguments were pushed onto
// the lua stack before calling spawn, so they are located at oldtop. // 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. // Spawn the thread and run it.
int nargs = 0; 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(); run_scheduled_threads();
assert(stack_is_clear()); assert(stack_is_clear());
} }
volatile int vx;
void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view datapack) { void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view datapack) {
assert(stack_is_clear()); assert(stack_is_clear());
// Use a streambuffer to parse the datapack. // Use a streambuffer to parse the datapack.
StreamBuffer datasb(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 classname;
eng::string funcname; eng::string funcname;
try { 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) { } catch (const StreamException &ex) {
return; 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(); lua_State *L = state();
LuaVar lclass, lfunc; LuaVar tangibles, place, mt, lclass, lfunc;
LuaExtStack LS(L, lclass, lfunc); LuaExtStack LS(L, tangibles, place, mt, lclass, lfunc);
// Get the class table and closure // Get the class. If the classname is *, then use the class of the place.
eng::string err = LS.getclass(lclass, classname); if (classname == "*") {
if ((!err.empty()) || (!LS.istable(lclass))) { LS.rawget(tangibles, LuaRegistry, "tangibles");
return; 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); LS.rawget(lfunc, lclass, funcname);
if (!LS.isfunction(lfunc)) { if (!LS.isfunction(lfunc)) return;
return;
}
// Spawn a thread, pushing extra arguments from the datapack. // Spawn a thread, pushing extra arguments from the datapack.
int nargs = 0; 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) { } catch (const StreamException &exc) {
return; 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(); run_scheduled_threads();
assert(stack_is_clear()); assert(stack_is_clear());
} }

View File

@@ -420,7 +420,7 @@ private:
// Low level spawn thread function. // 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: public:
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////

View File

@@ -10,15 +10,17 @@ function tree.init(self, config)
wait(1) wait(1)
end end
function login.init(actor, place) function login.init()
local actor = tangible.actor()
dprint("login.init:", actor) dprint("login.init:", actor)
local x = math.random(1, 100) local x = math.random(1, 100)
local y = math.random(1, 100) local y = math.random(1, 100)
tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}}) tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}})
end end
function engio.move(actor, place, action, xyz, facing) function engio.move(action, xyz, facing)
-- todo: sanity check the parameters. -- todo: sanity check the parameters.
local actor = tangible.actor()
dprint("engio.move ", action, " ", xyz[1], " ", xyz[2], " ", xyz[3]) dprint("engio.move ", action, " ", xyz[1], " ", xyz[2], " ", xyz[3])
tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing}) tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing})
end end