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

View File

@@ -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:
////////////////////////////////////////////////////////////////////////////

View File

@@ -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