Less serialization and deserialization of Lua Source, also, Invocation is now simpler

This commit is contained in:
2023-10-19 19:42:33 -04:00
parent 049b0b893a
commit 7104a523b5
16 changed files with 134 additions and 150 deletions

View File

@@ -165,8 +165,10 @@ void DrivenEngine::set_console_prompt(const eng::string &prompt) {
console_prompt_ = prompt; console_prompt_ = prompt;
} }
util::LuaSourcePtr DrivenEngine::get_lua_source() { eng::string DrivenEngine::get_lua_source_pack() {
return std::move(lua_source_); eng::string result = std::move(lua_source_pack_);
lua_source_pack_.clear();
return result;
} }
void DrivenEngine::rescan_lua_source() { void DrivenEngine::rescan_lua_source() {
@@ -219,7 +221,7 @@ enum DrvAction {
PLAY_NOTIFY_CLOSE, PLAY_NOTIFY_CLOSE,
PLAY_NOTIFY_ACCEPT, PLAY_NOTIFY_ACCEPT,
PLAY_INVOKE_EVENT_UPDATE, PLAY_INVOKE_EVENT_UPDATE,
PLAY_SET_LUA_SOURCE, PLAY_SET_LUA_SOURCE_PACK,
PLAY_RELEASE, PLAY_RELEASE,
}; };
@@ -232,7 +234,7 @@ inline static const char *action_string(DrvAction act) {
case PLAY_NOTIFY_CLOSE: return "PLAY_NOTIFY_CLOSE"; case PLAY_NOTIFY_CLOSE: return "PLAY_NOTIFY_CLOSE";
case PLAY_NOTIFY_ACCEPT: return "PLAY_NOTIFY_ACCEPT"; case PLAY_NOTIFY_ACCEPT: return "PLAY_NOTIFY_ACCEPT";
case PLAY_INVOKE_EVENT_UPDATE: return "PLAY_INVOKE_EVENT_UPDATE"; case PLAY_INVOKE_EVENT_UPDATE: return "PLAY_INVOKE_EVENT_UPDATE";
case PLAY_SET_LUA_SOURCE: return "PLAY_SET_LUA_SOURCE"; case PLAY_SET_LUA_SOURCE_PACK: return "PLAY_SET_LUA_SOURCE_PACK";
case PLAY_RELEASE: return "PLAY_RELEASE"; case PLAY_RELEASE: return "PLAY_RELEASE";
default: return "unknown"; default: return "unknown";
} }
@@ -442,7 +444,7 @@ void DrivenEngine::drv_get_animation_queues(uint32_t count, const int64_t *ids,
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void DrivenEngine::drv_initialize(uint32_t srcpklen, const char *srcpk, int argc, char **argv) { void DrivenEngine::drv_initialize(uint32_t srcpklen, const char *srcpk, int argc, char **argv) {
drv_set_lua_source(srcpklen, srcpk); drv_set_lua_source_pack(srcpklen, srcpk);
event_init(argc, argv); event_init(argc, argv);
} }
@@ -481,22 +483,12 @@ void DrivenEngine::drv_invoke_event_update(double clock) {
event_update(); event_update();
} }
void DrivenEngine::drv_set_lua_source(uint32_t srcpklen, const char *srcpk) { void DrivenEngine::drv_set_lua_source_pack(uint32_t srcpklen, const char *srcpk) {
StreamBuffer sb(std::string_view(srcpk, srcpklen)); lua_source_pack_ = std::string_view(srcpk, srcpklen);
uint32_t nfiles = sb.read_uint32();
lua_source_.reset(new util::LuaSourceVec);
lua_source_->resize(nfiles);
for (uint32_t i = 0; i < nfiles; i++) {
(*lua_source_)[i].first = sb.read_string();
}
for (uint32_t i = 0; i < nfiles; i++) {
(*lua_source_)[i].second = sb.read_string();
}
rescan_lua_source_ = false; rescan_lua_source_ = false;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@@ -821,25 +813,25 @@ static void replay_invoke_event_update(EngineWrapper *w) {
//////////////////////// ////////////////////////
void play_set_lua_source(EngineWrapper *w, uint32_t srcpklen, const char *srcpk) { void play_set_lua_source_pack(EngineWrapper *w, uint32_t srcpklen, const char *srcpk) {
assert(w->rlog == nullptr); assert(w->rlog == nullptr);
if (w->wlog != nullptr) { if (w->wlog != nullptr) {
w->wlog->write_cmd_hash(PLAY_SET_LUA_SOURCE, eng::memhash()); w->wlog->write_cmd_hash(PLAY_SET_LUA_SOURCE_PACK, eng::memhash());
w->wlog->write_string(std::string_view(srcpk, srcpklen)); w->wlog->write_string(std::string_view(srcpk, srcpklen));
w->wlog->flush(); w->wlog->flush();
} }
w->engine->drv_set_lua_source(srcpklen, srcpk); w->engine->drv_set_lua_source_pack(srcpklen, srcpk);
} }
void replay_set_lua_source(EngineWrapper *w) { void replay_set_lua_source_pack(EngineWrapper *w) {
std::string srcpack = w->rlog->read_string(); std::string srcpack = w->rlog->read_string();
if (!w->rlog->good()) { if (!w->rlog->good()) {
return reset_wrapper(w, "replay log corrupt in replay_set_lua_source"); return reset_wrapper(w, "replay log corrupt in replay_set_lua_source_pack");
} }
w->engine->drv_set_lua_source(srcpack.size(), srcpack.c_str()); w->engine->drv_set_lua_source_pack(srcpack.size(), srcpack.c_str());
} }
@@ -910,7 +902,7 @@ static void replaycore_step(EngineWrapper *w) {
case PLAY_NOTIFY_CLOSE: replay_notify_close(w); return; case PLAY_NOTIFY_CLOSE: replay_notify_close(w); return;
case PLAY_NOTIFY_ACCEPT: replay_notify_accept(w); return; case PLAY_NOTIFY_ACCEPT: replay_notify_accept(w); return;
case PLAY_INVOKE_EVENT_UPDATE: replay_invoke_event_update(w); return; case PLAY_INVOKE_EVENT_UPDATE: replay_invoke_event_update(w); return;
case PLAY_SET_LUA_SOURCE: replay_set_lua_source(w); return; case PLAY_SET_LUA_SOURCE_PACK: replay_set_lua_source_pack(w); return;
case PLAY_RELEASE: release(w); return; case PLAY_RELEASE: release(w); return;
default: return reset_wrapper(w, "Replay log corrupt in command dispatcher"); default: return reset_wrapper(w, "Replay log corrupt in command dispatcher");
} }
@@ -971,7 +963,7 @@ static void init_engine_wrapper_helper(EngineWrapper *w) {
w->play_notify_close = play_notify_close; w->play_notify_close = play_notify_close;
w->play_notify_accept = play_notify_accept; w->play_notify_accept = play_notify_accept;
w->play_invoke_event_update = play_invoke_event_update; w->play_invoke_event_update = play_invoke_event_update;
w->play_set_lua_source = play_set_lua_source; w->play_set_lua_source_pack = play_set_lua_source_pack;
w->replay_initialize = replaycore_initialize; w->replay_initialize = replaycore_initialize;
w->replay_step = replaycore_step; w->replay_step = replaycore_step;

View File

@@ -210,10 +210,13 @@ public:
// //
void set_console_prompt(const eng::string &prompt); void set_console_prompt(const eng::string &prompt);
// Fetches the lua source, and takes ownership of it. The DrivenEngine // Fetches the lua 'sourcepack'. The sourcepack is a packaged collection
// no longer contains the source after calling this. // of all the lua sourcefiles, see drvutil::package_lua_source for
// documentation of the format. This also clears the sourcepack stored
// in the DrivenEngine. Returns empty string if there is no sourcepack
// in the DrivenEngine.
// //
util::LuaSourcePtr get_lua_source(); eng::string get_lua_source_pack();
// Rescan the lua source directory. The lua source directory is read once, // Rescan the lua source directory. The lua source directory is read once,
// automatically, at engine creation time. If you want to read it again, // automatically, at engine creation time. If you want to read it again,
@@ -291,7 +294,7 @@ public:
void drv_notify_close(uint32_t chid, uint32_t len, const char *data); void drv_notify_close(uint32_t chid, uint32_t len, const char *data);
uint32_t drv_notify_accept(uint32_t port); uint32_t drv_notify_accept(uint32_t port);
void drv_invoke_event_update(double clock); void drv_invoke_event_update(double clock);
void drv_set_lua_source(uint32_t srcpklen, const char *srcpk); void drv_set_lua_source_pack(uint32_t srcpklen, const char *srcpk);
private: private:
// Find a currently-unused channel ID. Channel IDs // Find a currently-unused channel ID. Channel IDs
@@ -308,12 +311,12 @@ private:
std::unique_ptr<std::ostream> stdostream_; std::unique_ptr<std::ostream> stdostream_;
eng::vector<SharedChannel> accepted_channels_; eng::vector<SharedChannel> accepted_channels_;
eng::vector<uint32_t> new_outgoing_; eng::vector<uint32_t> new_outgoing_;
util::LuaSourcePtr lua_source_;
eng::vector<uint32_t> listen_ports_; eng::vector<uint32_t> listen_ports_;
World *visible_world_; World *visible_world_;
int64_t visible_actor_id_; int64_t visible_actor_id_;
util::IdVector scan_result_; util::IdVector scan_result_;
std::vector<util::SharedStdString> anim_queues_; std::vector<util::SharedStdString> anim_queues_;
eng::string lua_source_pack_;
bool rescan_lua_source_; bool rescan_lua_source_;
double clock_; double clock_;
bool stop_driver_; bool stop_driver_;

View File

@@ -115,7 +115,7 @@ private:
void event_init(int argc, char *argv[]) void event_init(int argc, char *argv[])
{ {
world_.reset(new World(WORLD_TYPE_MASTER)); world_.reset(new World(WORLD_TYPE_MASTER));
world_->update_source(get_lua_source()); world_->update_source(get_lua_source_pack());
world_->run_unittests(); world_->run_unittests();
stop_driver(); stop_driver();
} }

View File

@@ -102,7 +102,7 @@ struct EngineWrapper {
// Check the 'rescan_lua_source' flag. If this flag is set, it means // Check the 'rescan_lua_source' flag. If this flag is set, it means
// that the engine wants the driver to rescan the lua source code. // that the engine wants the driver to rescan the lua source code.
// When the driver sees this flag, it should rescan the source and call // When the driver sees this flag, it should rescan the source and call
// set_lua_source. // set_lua_source_pack.
// //
bool (*get_rescan_lua_source)(EngineWrapper *w); bool (*get_rescan_lua_source)(EngineWrapper *w);
@@ -199,7 +199,7 @@ struct EngineWrapper {
// Store the lua source code. // Store the lua source code.
// //
void (*play_set_lua_source)(EngineWrapper *w, uint32_t srcpklen, const char *srcpk); void (*play_set_lua_source_pack)(EngineWrapper *w, uint32_t srcpklen, const char *srcpk);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@@ -30,7 +30,7 @@ void Gui::menu_item(const eng::string &action, const eng::string &label) {
elts_.push_back(elt); elts_.push_back(elt);
} }
bool Gui::has_action(const eng::string &action) const { bool Gui::has_action(std::string_view action) const {
for (const GuiElt &elt : elts_) { for (const GuiElt &elt : elts_) {
if (elt.action_ == action) { if (elt.action_ == action) {
return true; return true;

View File

@@ -38,7 +38,7 @@ public:
int64_t place() { return place_; } int64_t place() { return place_; }
const EltVec &elts() const { return elts_; } const EltVec &elts() const { return elts_; }
void clear(int64_t p) { place_ = p; elts_.clear(); } void clear(int64_t p) { place_ = p; elts_.clear(); }
bool has_action(const eng::string &action) const; bool has_action(std::string_view action) const;
void menu_item(const eng::string &action, const eng::string &label); void menu_item(const eng::string &action, const eng::string &label);
eng::string get_action(int64_t index); eng::string get_action(int64_t index);
eng::string menu_debug_string() const; eng::string menu_debug_string() const;

View File

@@ -6,57 +6,24 @@
#include "invocation.hpp" #include "invocation.hpp"
const eng::string &InvocationData::get(const eng::string &key) const {
static eng::string blank_;
auto iter = find(key);
if (iter == end()) {
return blank_;
} else {
return iter->second;
}
}
void InvocationData::serialize(StreamBuffer *sb) const {
assert(int(size()) < 65536);
sb->write_uint16(size());
for (const auto &pair : *this) {
sb->write_string(pair.first);
sb->write_string(pair.second);
}
}
void InvocationData::deserialize(StreamBuffer *sb) {
clear();
int size = sb->read_uint16();
for (int i = 0; i < size; i++) {
eng::string key = sb->read_string();
eng::string val = sb->read_string();
(*this)[key] = val;
}
}
Invocation::Invocation() : kind_(KIND_INVALID), actor_(0), place_(0) {} Invocation::Invocation() : kind_(KIND_INVALID), actor_(0), place_(0) {}
Invocation::Invocation(Kind kind, int64_t actor, int64_t place, const eng::string &action, const InvocationData &data) Invocation::Invocation(Kind kind, int64_t actor, int64_t place, std::string_view datapack)
: kind_(kind), actor_(actor), place_(place), action_(action), data_(data) {} : kind_(kind), actor_(actor), place_(place), datapack_(datapack) {}
Invocation::Invocation(Kind kind, int64_t actor, int64_t place, const eng::string &action)
: kind_(kind), actor_(actor), place_(place), action_(action) {}
void Invocation::serialize(StreamBuffer *sb) const { void Invocation::serialize(StreamBuffer *sb) const {
sb->write_uint8(kind_); sb->write_uint8(kind_);
sb->write_int64(actor_); sb->write_int64(actor_);
sb->write_int64(place_); sb->write_int64(place_);
sb->write_string(action_); sb->write_string(datapack_);
data_.serialize(sb);
} }
void Invocation::deserialize(StreamBuffer *sb) { void Invocation::deserialize(StreamBuffer *sb) {
kind_ = Kind(sb->read_uint8()); kind_ = Kind(sb->read_uint8());
actor_ = sb->read_int64(); actor_ = sb->read_int64();
place_ = sb->read_int64(); place_ = sb->read_int64();
action_ = sb->read_string(); datapack_ = sb->read_string();
data_.deserialize(sb);
} }
eng::string Invocation::debug_string() const { eng::string Invocation::debug_string() const {
@@ -73,12 +40,7 @@ eng::string Invocation::debug_string() const {
} }
oss << " a=" << actor_; oss << " a=" << actor_;
oss << " p=" << place_; oss << " p=" << place_;
if (kind_ != KIND_LUA_SOURCE) { oss << " dp=" << datapack_.size() << " bytes";
oss << " " << action_;
}
for (const auto &pair : data_) {
oss << " " << pair.first << "=" << pair.second;
}
oss << "]"; oss << "]";
return oss.str(); return oss.str();
} }

View File

@@ -1,3 +1,39 @@
//////////////////////////////////////////////////////////////////////////
//
// DATAPACK
//
// Invocations contain a field 'datapack' which contains additional
// data for the invocation, packed up in a serialized format. Executing
// the invocation involves unpacking the datapack.
//
// The actual contents of the datapack depends on the type of invocation:
//
// KIND_INVALID:
//
// Nothing.
//
// KIND_PLAN:
//
// Name of a callback function, in plaintext.
//
// KIND_LUA:
//
// A block of lua source code, in plaintext.
//
// KIND_FLUSH_PRINTS:
//
// Line number in ascii.
//
// KIND_TICK:
//
// Nothing.
//
// KIND_LUA_SOURCE:
//
// Packaged lua sourcecode. See drvutil::package_lua_source.
//
//////////////////////////////////////////////////////////////////////////
#ifndef INVOCATION_HPP #ifndef INVOCATION_HPP
#define INVOCATION_HPP #define INVOCATION_HPP
@@ -8,14 +44,6 @@
#include "streambuffer.hpp" #include "streambuffer.hpp"
class InvocationData : public eng::map<eng::string, eng::string> {
public:
const eng::string &get(const eng::string &key) const;
void serialize(StreamBuffer *sb) const;
void deserialize(StreamBuffer *sb);
};
class Invocation : public eng::nevernew { class Invocation : public eng::nevernew {
public: public:
enum Kind { enum Kind {
@@ -31,19 +59,16 @@ private:
Kind kind_; Kind kind_;
int64_t actor_; int64_t actor_;
int64_t place_; int64_t place_;
eng::string action_; eng::string datapack_;
InvocationData data_;
public: public:
Invocation(); Invocation();
Invocation(Kind kind, int64_t actor, int64_t place, const eng::string &action, const InvocationData &data); Invocation(Kind kind, int64_t actor, int64_t place, std::string_view datapack);
Invocation(Kind kind, int64_t actor, int64_t place, const eng::string &action);
bool valid() const { return kind_ != KIND_INVALID; } bool valid() const { return kind_ != KIND_INVALID; }
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
int64_t actor() const { return actor_; } int64_t actor() const { return actor_; }
int64_t place() const { return place_; } int64_t place() const { return place_; }
const eng::string &action() const { return action_; } const eng::string &datapack() const { return datapack_; }
const InvocationData &data() const { return data_; }
void serialize(StreamBuffer *sb) const; void serialize(StreamBuffer *sb) const;
void deserialize(StreamBuffer *sb); void deserialize(StreamBuffer *sb);

View File

@@ -81,7 +81,7 @@ public:
// The driver loads the lua source automatically. // The driver loads the lua source automatically.
// However, we don't need it. Throw it out. // However, we don't need it. Throw it out.
get_lua_source(); get_lua_source_pack();
} }
void send_invocation(const Invocation &inv) { void send_invocation(const Invocation &inv) {
@@ -97,11 +97,8 @@ public:
inv.serialize(sb); inv.serialize(sb);
} }
void send_lua_source(const util::LuaSourceVec &sv) { void send_lua_source(std::string_view sourcepack) {
StreamBuffer serial; Invocation inv(Invocation::KIND_LUA_SOURCE, actor_id_, actor_id_, sourcepack);
SourceDB::serialize_source(sv, &serial);
eng::string sstr(serial.view());
Invocation inv(Invocation::KIND_LUA_SOURCE, actor_id_, actor_id_, sstr);
send_invocation(inv); send_invocation(inv);
} }
@@ -239,10 +236,10 @@ public:
virtual void event_update() { virtual void event_update() {
// Check for lua source code. If this returns non-null, // Check for lua source code. If this returns non-null,
// it is because somebody typed CPL. // it is because somebody typed CPL.
util::LuaSourcePtr lua_source = get_lua_source(); eng::string lua_source_pack = get_lua_source_pack();
if (lua_source != nullptr) { if (!lua_source_pack.empty()) {
send_lua_source(*lua_source); send_lua_source(lua_source_pack);
lua_source.reset(); lua_source_pack.clear();
} }
// Check for keyboard input on stdin. // Check for keyboard input on stdin.

View File

@@ -36,7 +36,7 @@ public:
master_.reset(new World(WORLD_TYPE_MASTER)); master_.reset(new World(WORLD_TYPE_MASTER));
// Update the source code of the master model. // Update the source code of the master model.
master_->update_source(get_lua_source()); master_->update_source(get_lua_source_pack());
// Create an actor for administrative commands. // Create an actor for administrative commands.
admin_id_ = master_->create_login_actor(); admin_id_ = master_->create_login_actor();
@@ -168,7 +168,7 @@ public:
virtual void event_update() { virtual void event_update() {
// If the driver has reloaded the source, put it into master model. // If the driver has reloaded the source, put it into master model.
master_->update_source(get_lua_source()); master_->update_source(get_lua_source_pack());
// Check for keyboard input on stdin. // Check for keyboard input on stdin.
while (true) { while (true) {

View File

@@ -192,7 +192,7 @@ bool PrintChanneler::channel(const PrintBuffer *printbuffer, std::ostream &ostre
Invocation PrintChanneler::invocation(int64_t actor_id) { Invocation PrintChanneler::invocation(int64_t actor_id) {
char buf[80]; char buf[80];
sprintf(buf, "%" PRId64, line_); sprintf(buf, "%" PRId64, line_);
return Invocation(Invocation::KIND_FLUSH_PRINTS, actor_id, actor_id, buf, InvocationData()); return Invocation(Invocation::KIND_FLUSH_PRINTS, actor_id, actor_id, buf);
} }
LuaDefine(unittests_printbuffer, "", "some unit tests") { LuaDefine(unittests_printbuffer, "", "some unit tests") {

View File

@@ -99,7 +99,7 @@ private:
void event_init(int argc, char *argv[]) void event_init(int argc, char *argv[])
{ {
world_.reset(new World(WORLD_TYPE_MASTER)); world_.reset(new World(WORLD_TYPE_MASTER));
world_->update_source(get_lua_source()); world_->update_source(get_lua_source_pack());
world_->run_unittests(); world_->run_unittests();
actor_id_ = world_->create_login_actor(); actor_id_ = world_->create_login_actor();
stdostream() << "Login actor ID: " << actor_id_ << std::endl; stdostream() << "Login actor ID: " << actor_id_ << std::endl;
@@ -108,7 +108,7 @@ private:
void event_update() void event_update()
{ {
world_->update_source(get_lua_source()); world_->update_source(get_lua_source_pack());
while (true) { while (true) {
eng::string line = get_stdio_channel()->in()->readline(); eng::string line = get_stdio_channel()->in()->readline();
if (line == "") break; if (line == "") break;

View File

@@ -357,12 +357,6 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
} }
} }
void World::update_source(const util::LuaSourcePtr &source) {
if (source != nullptr) {
update_source(*source);
}
}
// This is called from World::update_source, and also // This is called from World::update_source, and also
// from World::patch_source in the difference transmitter. // from World::patch_source in the difference transmitter.
// //
@@ -397,6 +391,25 @@ void World::update_source(const util::LuaSourceVec &source) {
assert(stack_is_clear()); assert(stack_is_clear());
} }
void World::update_source(const util::LuaSourcePtr &source) {
if (source != nullptr) {
update_source(*source);
}
}
void World::update_source(std::string_view sourcepack) {
if (!sourcepack.empty()) {
try {
StreamBuffer sb(sourcepack);
util::LuaSourceVec sv;
SourceDB::deserialize_source(&sv, &sb);
update_source(sv);
} catch (const StreamException &ex) {
return;
}
}
}
void World::http_response(const HttpParser &response) { void World::http_response(const HttpParser &response) {
// Find the request. // Find the request.
auto iter = http_requests_.find(response.request_id()); auto iter = http_requests_.find(response.request_id());
@@ -554,19 +567,19 @@ void World::run_unittests() {
void World::invoke(const Invocation &inv) { void World::invoke(const Invocation &inv) {
switch (inv.kind()) { switch (inv.kind()) {
case Invocation::KIND_PLAN: case Invocation::KIND_PLAN:
invoke_plan(inv.actor(), inv.place(), inv.action(), inv.data()); invoke_plan(inv.actor(), inv.place(), inv.datapack());
break; break;
case Invocation::KIND_LUA: case Invocation::KIND_LUA:
invoke_lua(inv.actor(), inv.place(), inv.action(), inv.data()); invoke_lua(inv.actor(), inv.place(), inv.datapack());
break; break;
case Invocation::KIND_FLUSH_PRINTS: case Invocation::KIND_FLUSH_PRINTS:
invoke_flush_prints(inv.actor(), inv.place(), inv.action(), inv.data()); invoke_flush_prints(inv.actor(), inv.place(), inv.datapack());
break; break;
case Invocation::KIND_TICK: case Invocation::KIND_TICK:
invoke_tick(inv.actor(), inv.place(), inv.action(), inv.data()); invoke_tick(inv.actor(), inv.place(), inv.datapack());
break; break;
case Invocation::KIND_LUA_SOURCE: case Invocation::KIND_LUA_SOURCE:
invoke_lua_source(inv.actor(), inv.place(), inv.action(), inv.data()); invoke_lua_source(inv.actor(), inv.place(), inv.datapack());
break; break;
default: default:
// Do nothing. Standard behavior for any invalid command is to // Do nothing. Standard behavior for any invalid command is to
@@ -578,13 +591,13 @@ void World::invoke(const Invocation &inv) {
} }
} }
void World::invoke_flush_prints(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data) { void World::invoke_flush_prints(int64_t actor_id, int64_t place_id, std::string_view datapack) {
assert(stack_is_clear()); assert(stack_is_clear());
// Check argument sanity. // Check argument sanity.
if (actor_id != place_id) { if (actor_id != place_id) {
return; return;
} }
int64_t line = sv::to_int64(action, -1); int64_t line = sv::to_int64(datapack, -1);
if ((line < 0)||(line > INT_MAX)) { if ((line < 0)||(line > INT_MAX)) {
return; return;
} }
@@ -598,7 +611,7 @@ void World::invoke_flush_prints(int64_t actor_id, int64_t place_id, const eng::s
void World::invoke_lua(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data) { void World::invoke_lua(int64_t actor_id, int64_t place_id, std::string_view datapack) {
assert(stack_is_clear()); assert(stack_is_clear());
// Make sure that actor and place exist and are not stubs. // Make sure that actor and place exist and are not stubs.
@@ -618,7 +631,7 @@ void World::invoke_lua(int64_t actor_id, int64_t place_id, const eng::string &ac
LuaExtStack LS(L, func, tangibles, place, mt, thread, thinfo, threads); LuaExtStack LS(L, func, tangibles, place, mt, thread, thinfo, threads);
// create the compiled closure. // create the compiled closure.
int status = luaL_loadbuffer(L, action.c_str(), action.size(), "=invoke"); int status = luaL_loadbuffer(L, datapack.data(), datapack.size(), "=invoke");
lua_replace(L, func.index()); lua_replace(L, func.index());
if (status != LUA_OK) { if (status != LUA_OK) {
// The closure is actually an error message. Do nothing. // The closure is actually an error message. Do nothing.
@@ -666,18 +679,18 @@ void World::invoke_lua(int64_t actor_id, int64_t place_id, const eng::string &ac
assert(stack_is_clear()); assert(stack_is_clear());
} }
void World::invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data) { void World::invoke_plan(int64_t actor_id, int64_t place_id, std::string_view datapack) {
assert(stack_is_clear()); assert(stack_is_clear());
// Validate that the action is legal. // Validate that the action is legal.
Gui validation_gui; Gui validation_gui;
update_gui(actor_id, place_id, &validation_gui); update_gui(actor_id, place_id, &validation_gui);
if (!validation_gui.has_action(action)) { if (!validation_gui.has_action(datapack)) {
return; return;
} }
// Make sure the action starts with "cb_" // Make sure the action starts with "cb_"
if (!sv::has_prefix(action, "cb_")) { if (!sv::has_prefix(datapack, "cb_")) {
return; return;
} }
@@ -715,16 +728,14 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &a
if (!LS.istable(index)) { if (!LS.istable(index)) {
return; return;
} }
LS.rawget(func, index, action); LS.rawget(func, index, datapack);
if (!LS.isfunction(func)) { if (!LS.isfunction(func)) {
return; return;
} }
// Convert the InvocationData into a lua table. // TODO: maybe add the ability to pass data in as a table?
// For now the table is always empty.
LS.newtable(invdata); LS.newtable(invdata);
for (const auto &p : data) {
LS.rawset(invdata, p.first, p.second);
}
// Create a new thread, set up function and parameters. // Create a new thread, set up function and parameters.
lua_State *CO = LS.newthread(thread); lua_State *CO = LS.newthread(thread);
@@ -757,7 +768,7 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &a
assert(stack_is_clear()); assert(stack_is_clear());
} }
void World::invoke_tick(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data) { void World::invoke_tick(int64_t actor_id, int64_t place_id, std::string_view datapack) {
if (!is_authoritative()) { if (!is_authoritative()) {
return; return;
} }
@@ -765,19 +776,12 @@ void World::invoke_tick(int64_t actor_id, int64_t place_id, const eng::string &a
run_scheduled_threads(); run_scheduled_threads();
} }
void World::invoke_lua_source(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data) { void World::invoke_lua_source(int64_t actor_id, int64_t place_id, std::string_view datapack) {
if (!is_authoritative()) { if (!is_authoritative()) {
return; return;
} }
// We need some kind of authentication here. // We need some kind of authentication here.
try { update_source(datapack);
StreamBuffer sb(action);
util::LuaSourceVec sv;
SourceDB::deserialize_source(&sv, &sb);
update_source(sv);
} catch (const StreamException &ex) {
return;
}
} }
void World::guard_blockable(lua_State *L, const char *fn) { void World::guard_blockable(lua_State *L, const char *fn) {

View File

@@ -220,9 +220,12 @@ public:
// Update the source database from disk. // Update the source database from disk.
// //
// Special case: if the source pointer is nullptr, does not update. // Special case: if the source pointer is nullptr, does not update.
// The final form takes a sourcepk, a serialized representation
// of a LuaSourceVec.
// //
void update_source(const util::LuaSourcePtr &source);
void update_source(const util::LuaSourceVec &source); void update_source(const util::LuaSourceVec &source);
void update_source(const util::LuaSourcePtr &source);
void update_source(std::string_view sourcepk);
// Rebuild the source database. // Rebuild the source database.
// //
@@ -348,23 +351,23 @@ private:
// Invoke a plan. // Invoke a plan.
// //
void invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data); void invoke_plan(int64_t actor_id, int64_t place_id, std::string_view datapack);
// Invoke a lua string. // Invoke a lua string.
// //
void invoke_lua(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data); void invoke_lua(int64_t actor_id, int64_t place_id, std::string_view datapack);
// Invoke the flush-prints operation. // Invoke the flush-prints operation.
// //
void invoke_flush_prints(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data); void invoke_flush_prints(int64_t actor_id, int64_t place_id, std::string_view datapack);
// Invoke the tick operation. // Invoke the tick operation.
// //
void invoke_tick(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data); void invoke_tick(int64_t actor_id, int64_t place_id, std::string_view datapack);
// Invoke the lua_source operation. // Invoke the lua_source operation.
// //
void invoke_lua_source(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data); void invoke_lua_source(int64_t actor_id, int64_t place_id, std::string_view datapack);
public: public:
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////

View File

@@ -193,7 +193,7 @@ class Driver {
std::string err = drvutil::package_lua_source(".", &oss); std::string err = drvutil::package_lua_source(".", &oss);
if_error_print_and_exit(err); if_error_print_and_exit(err);
std::string_view ossv = oss.view(); std::string_view ossv = oss.view();
engw.play_set_lua_source(&engw, ossv.size(), ossv.data()); engw.play_set_lua_source_pack(&engw, ossv.size(), ossv.data());
} }
} }

View File

@@ -345,8 +345,6 @@ std::string package_lua_source(const std::filesystem::path &base, std::ostream *
sbwrite_uint32(s, names.size()); sbwrite_uint32(s, names.size());
for (int i = 0; i < int(names.size()); i++) { for (int i = 0; i < int(names.size()); i++) {
sbwrite_string(s, names[i]); sbwrite_string(s, names[i]);
}
for (int i = 0; i < int(names.size()); i++) {
std::filesystem::path lfn = base / "lua" / names[i]; std::filesystem::path lfn = base / "lua" / names[i];
if (!sbwrite_file(s, lfn)) { if (!sbwrite_file(s, lfn)) {
return std::string("Cannot read source file: ") + lfn.u8string(); return std::string("Cannot read source file: ") + lfn.u8string();