Add invoke_lua function to world model
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "animqueue.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "traceback.hpp"
|
||||
#include "print.hpp"
|
||||
#include <iostream>
|
||||
|
||||
void World::store_global_pointer(lua_State *L, World *v) {
|
||||
@@ -320,11 +321,21 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
||||
assert(stack_is_clear());
|
||||
}
|
||||
|
||||
void World::update_source(util::LuaSourcePtr source) {
|
||||
if (source != nullptr) {
|
||||
source_db_.update(*source);
|
||||
source_db_.rebuild(true);
|
||||
}
|
||||
}
|
||||
|
||||
void World::invoke(const Invocation &inv) {
|
||||
switch (inv.kind()) {
|
||||
case Invocation::KIND_PLAN:
|
||||
invoke_plan(inv.actor(), inv.place(), inv.action(), inv.data());
|
||||
break;
|
||||
case Invocation::KIND_LUA:
|
||||
invoke_lua(inv.actor(), inv.place(), inv.action(), inv.data());
|
||||
break;
|
||||
default:
|
||||
// Do nothing. Standard behavior for any invalid command is to
|
||||
// simply do nothing at all. Perhaps eventually we may add a flag
|
||||
@@ -335,14 +346,56 @@ void World::invoke(const Invocation &inv) {
|
||||
}
|
||||
}
|
||||
|
||||
void World::update_source(util::LuaSourcePtr source) {
|
||||
if (source != nullptr) {
|
||||
source_db_.update(*source);
|
||||
source_db_.rebuild(true);
|
||||
void World::invoke_lua(int64_t actor_id, int64_t place_id, const std::string &action, const InvocationData &data) {
|
||||
assert(stack_is_clear());
|
||||
|
||||
// Get the actor and place, which must be the same.
|
||||
if (actor_id != place_id) return;
|
||||
Tangible *tactor = tangible_get(actor_id);
|
||||
if (tactor == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
lua_State *L = state();
|
||||
LuaVar closure;
|
||||
LuaStack LS(L, closure);
|
||||
|
||||
// create the compiled closure.
|
||||
int status = luaL_loadbuffer(L, action.c_str(), action.size(), "=invoke");
|
||||
lua_replace(L, closure.index());
|
||||
if (status != LUA_OK) {
|
||||
// The closure is actually an error message. Do nothing.
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
|
||||
// Call the closure.
|
||||
int top = lua_gettop(L);
|
||||
lua_pushvalue(L, closure.index());
|
||||
set_lthread_state(actor_id, place_id, false);
|
||||
status = traceback_pcall(L, 0, LUA_MULTRET);
|
||||
set_lthread_state(0, 0, false);
|
||||
|
||||
// If there's an error message, print it.
|
||||
// Otherwise, pretty-print the results.
|
||||
if (status == LUA_OK) {
|
||||
for (int i = top + 1; i <= lua_gettop(L); i++) {
|
||||
LuaSpecial root(i);
|
||||
pprint(LS, root, true, &std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
} else {
|
||||
const char *msg = lua_tostring(L, top);
|
||||
if (msg == NULL) {
|
||||
msg = "(error object is not a string)";
|
||||
}
|
||||
std::cerr << msg << std::endl;
|
||||
}
|
||||
LS.result();
|
||||
assert(stack_is_clear());
|
||||
}
|
||||
|
||||
void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, const InvocationData &idata) {
|
||||
void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, const InvocationData &data) {
|
||||
assert(stack_is_clear());
|
||||
|
||||
// Validate that the action is legal.
|
||||
@@ -401,7 +454,7 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &a
|
||||
|
||||
// Convert the InvocationData into a lua table.
|
||||
LS.newtable(invdata);
|
||||
for (const auto &p : idata) {
|
||||
for (const auto &p : data) {
|
||||
LS.rawset(invdata, p.first, p.second);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user