Add invocation queue to DrivenEngine, use it for lua source
This commit is contained in:
@@ -90,7 +90,6 @@ OBJ_CORE=\
|
||||
build/$(OS)/core/world-diffxmit.obj\
|
||||
build/$(OS)/core/world-pairtab.obj\
|
||||
build/$(OS)/core/world-testing.obj\
|
||||
build/$(OS)/core/textgame.obj\
|
||||
build/$(OS)/core/lpxserver.obj\
|
||||
build/$(OS)/core/lpxclient.obj\
|
||||
build/$(OS)/core/eng-tests.obj\
|
||||
|
||||
@@ -165,9 +165,9 @@ void DrivenEngine::set_console_prompt(const eng::string &prompt) {
|
||||
console_prompt_ = prompt;
|
||||
}
|
||||
|
||||
eng::string DrivenEngine::get_lua_source_pack() {
|
||||
eng::string result = std::move(lua_source_pack_);
|
||||
lua_source_pack_.clear();
|
||||
eng::vector<UniqueInvocation> DrivenEngine::get_queued_invocations() {
|
||||
eng::vector<UniqueInvocation> result = std::move(queued_invocations_);
|
||||
queued_invocations_.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -392,11 +392,11 @@ bool DrivenEngine::drv_get_stop_driver() const {
|
||||
return stop_driver_;
|
||||
}
|
||||
|
||||
uint64_t DrivenEngine::drv_get_actor_id() const {
|
||||
int64_t DrivenEngine::drv_get_actor_id() const {
|
||||
return visible_actor_id_;
|
||||
}
|
||||
|
||||
void DrivenEngine::drv_get_tangibles_near(uint64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids) {
|
||||
void DrivenEngine::drv_get_tangibles_near(int64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids) {
|
||||
uint32_t hash1 = eng::memhash();
|
||||
scan_result_.clear();
|
||||
if ((visible_world_ != 0) && (tanid != 0)) {
|
||||
@@ -483,11 +483,11 @@ void DrivenEngine::drv_invoke_event_update(double clock) {
|
||||
}
|
||||
|
||||
void DrivenEngine::drv_set_lua_source_pack(uint32_t srcpklen, const char *srcpk) {
|
||||
lua_source_pack_ = std::string_view(srcpk, srcpklen);
|
||||
Invocation *inv = new Invocation(Invocation::KIND_LUA_SOURCE, visible_actor_id_, visible_actor_id_, std::string_view(srcpk, srcpklen));
|
||||
queued_invocations_.emplace_back(inv);
|
||||
rescan_lua_source_ = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "streambuffer.hpp"
|
||||
#include "enginewrapper.hpp"
|
||||
#include "planemap.hpp"
|
||||
#include "invocation.hpp"
|
||||
|
||||
class DrivenEngine;
|
||||
class World;
|
||||
@@ -144,12 +145,12 @@ public:
|
||||
// The init callback. You may override this in a subclass.
|
||||
// This will be called once at program initialization.
|
||||
//
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) {}
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) = 0;
|
||||
|
||||
// The update callback. You may override this in a subclass.
|
||||
// This will be called whenever anything changes.
|
||||
//
|
||||
virtual void event_update() {}
|
||||
virtual void event_update() = 0;
|
||||
|
||||
// Specify the set of listening ports.
|
||||
// This can only be used during the init routine.
|
||||
@@ -210,13 +211,11 @@ public:
|
||||
//
|
||||
void set_console_prompt(const eng::string &prompt);
|
||||
|
||||
// Fetches the lua 'sourcepack'. The sourcepack is a packaged collection
|
||||
// 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.
|
||||
// Fetches the invocation queue.
|
||||
//
|
||||
eng::string get_lua_source_pack();
|
||||
// This also clears the stored queue.
|
||||
//
|
||||
eng::vector<UniqueInvocation> get_queued_invocations();
|
||||
|
||||
// Rescan the lua source directory. The lua source directory is read once,
|
||||
// automatically, at engine creation time. If you want to read it again,
|
||||
@@ -283,8 +282,8 @@ public:
|
||||
double drv_get_clock() const;
|
||||
bool drv_get_rescan_lua_source() const;
|
||||
bool drv_get_stop_driver() const;
|
||||
uint64_t drv_get_actor_id() const;
|
||||
void drv_get_tangibles_near(uint64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids);
|
||||
int64_t drv_get_actor_id() const;
|
||||
void drv_get_tangibles_near(int64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids);
|
||||
void drv_get_animation_queues(uint32_t count, const int64_t *ids, uint32_t *lengths, const char **strings);
|
||||
|
||||
void drv_initialize(uint32_t srcpklen, const char *srcpk, int argc, char **argv);
|
||||
@@ -316,7 +315,7 @@ private:
|
||||
int64_t visible_actor_id_;
|
||||
util::IdVector scan_result_;
|
||||
std::vector<util::SharedStdString> anim_queues_;
|
||||
eng::string lua_source_pack_;
|
||||
eng::vector<UniqueInvocation> queued_invocations_;
|
||||
bool rescan_lua_source_;
|
||||
double clock_;
|
||||
bool stop_driver_;
|
||||
|
||||
@@ -24,9 +24,11 @@ static void dump_lines(StreamBuffer *in, StreamBuffer *out, int chid) {
|
||||
|
||||
// This test is the minimal possible DrivenEngine.
|
||||
class DriverStubTest : public DrivenEngine {
|
||||
virtual void event_init(int argc, char *argv[]) {
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
||||
stop_driver();
|
||||
}
|
||||
virtual void event_update() override {
|
||||
}
|
||||
};
|
||||
|
||||
// This test connects to a public webserver and prints
|
||||
@@ -34,13 +36,13 @@ class DriverStubTest : public DrivenEngine {
|
||||
class DriverWebServerTest : public DrivenEngine {
|
||||
public:
|
||||
eng::vector<SharedChannel> channels_;
|
||||
virtual void event_init(int argc, char *argv[]) {
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
||||
SharedChannel ch = new_outgoing_channel("cert:stanford.edu:443");
|
||||
ch->out()->write_bytes("GET https://stanford.edu/xbanankjdsh.html HTTP/1.1\n\n");
|
||||
channels_.emplace_back(std::move(ch));
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
virtual void event_update() override {
|
||||
SharedChannel stdioch = get_stdio_channel();
|
||||
dump_lines(stdioch->in(), stdioch->out(), 0);
|
||||
eng::vector<SharedChannel> keep;
|
||||
@@ -60,13 +62,13 @@ public:
|
||||
class DriverDNSFailTest : public DrivenEngine {
|
||||
public:
|
||||
eng::vector<SharedChannel> channels_;
|
||||
virtual void event_init(int argc, char *argv[]) {
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
||||
SharedChannel ch = new_outgoing_channel("akjsdkajshdakjshd.alk:80");
|
||||
ch->out()->write_bytes("GET http://stanford.edu/index.html HTTP/1.1\n\n");
|
||||
channels_.emplace_back(std::move(ch));
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
virtual void event_update() override {
|
||||
SharedChannel stdioch = get_stdio_channel();
|
||||
dump_lines(stdioch->in(), stdioch->out(), 0);
|
||||
eng::vector<SharedChannel> keep;
|
||||
@@ -87,12 +89,12 @@ class DriverPrintClockTest : public DrivenEngine {
|
||||
public:
|
||||
int count_;
|
||||
double last_clock_;
|
||||
virtual void event_init(int argc, char *argv[]) {
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
||||
count_ = 0;
|
||||
last_clock_ = 0.0;
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
virtual void event_update() override {
|
||||
double clock = get_clock();
|
||||
if (clock > last_clock_ + 0.5) {
|
||||
int ms = eng::memhash();
|
||||
@@ -112,13 +114,15 @@ class RunUnitTests : public DrivenEngine {
|
||||
private:
|
||||
UniqueWorld world_;
|
||||
|
||||
void event_init(int argc, char *argv[])
|
||||
void event_init(std::string_view srcpk, int argc, char *argv[]) override
|
||||
{
|
||||
world_.reset(new World(WORLD_TYPE_MASTER));
|
||||
world_->update_source(get_lua_source_pack());
|
||||
world_->update_source(srcpk);
|
||||
world_->run_unittests();
|
||||
stop_driver();
|
||||
}
|
||||
|
||||
void event_update() override {}
|
||||
};
|
||||
|
||||
DrivenEngineDefine("driverstubtest", DriverStubTest);
|
||||
|
||||
@@ -40,11 +40,10 @@
|
||||
#include "wrap-string.hpp"
|
||||
#include "wrap-map.hpp"
|
||||
#include "wrap-deque.hpp"
|
||||
|
||||
#include "streambuffer.hpp"
|
||||
|
||||
|
||||
class Invocation : public eng::nevernew {
|
||||
class Invocation : public eng::opnew {
|
||||
public:
|
||||
enum Kind {
|
||||
KIND_INVALID,
|
||||
@@ -76,6 +75,8 @@ public:
|
||||
eng::string debug_string() const;
|
||||
};
|
||||
|
||||
using UniqueInvocation = std::unique_ptr<Invocation>;
|
||||
|
||||
class InvocationQueue : public eng::deque<Invocation> {
|
||||
};
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ public:
|
||||
|
||||
// Clear the unack command queue.
|
||||
unack_.clear();
|
||||
|
||||
// Export stuff to the graphics engine.
|
||||
set_visible_world_and_actor(world_.get(), actor_id_);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,11 +96,6 @@ public:
|
||||
inv.serialize(sb);
|
||||
}
|
||||
|
||||
void send_lua_source(std::string_view sourcepack) {
|
||||
Invocation inv(Invocation::KIND_LUA_SOURCE, actor_id_, actor_id_, sourcepack);
|
||||
send_invocation(inv);
|
||||
}
|
||||
|
||||
void do_luainvoke_command(const StringVec &words) {
|
||||
send_invocation(Invocation(Invocation::KIND_LUA, actor_id_, actor_id_, words[1]));
|
||||
}
|
||||
@@ -176,6 +174,7 @@ public:
|
||||
stdostream() << "Actor ID changing: " << actor_id << std::endl;
|
||||
print_channeler_.reset();
|
||||
actor_id_ = actor_id;
|
||||
set_visible_world_and_actor(world_.get(), actor_id_);
|
||||
}
|
||||
|
||||
void receive_ack_from_server(StreamBuffer *sb) {
|
||||
@@ -230,12 +229,10 @@ public:
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
// Check for lua source code. If this returns non-null,
|
||||
// it is because somebody typed CPL.
|
||||
eng::string lua_source_pack = get_lua_source_pack();
|
||||
if (!lua_source_pack.empty()) {
|
||||
send_lua_source(lua_source_pack);
|
||||
lua_source_pack.clear();
|
||||
// Send invocations. We execute these using predictive execution.
|
||||
eng::vector<UniqueInvocation> invocations = get_queued_invocations();
|
||||
for (const UniqueInvocation &inv : invocations) {
|
||||
send_invocation(*inv);
|
||||
}
|
||||
|
||||
// Check for keyboard input on stdin.
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
Gui gui_;
|
||||
|
||||
public:
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) {
|
||||
virtual void event_init(std::string_view srcpk, int argc, char *argv[]) override {
|
||||
// Create the master world model.
|
||||
master_.reset(new World(WORLD_TYPE_MASTER));
|
||||
|
||||
@@ -166,9 +166,13 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
// If the driver has reloaded the source, put it into master model.
|
||||
master_->update_source(get_lua_source_pack());
|
||||
virtual void event_update() override {
|
||||
// Execute any queued invocations.
|
||||
// We just feed these directly into the master model.
|
||||
eng::vector<UniqueInvocation> invocations = get_queued_invocations();
|
||||
for (const UniqueInvocation &inv : invocations) {
|
||||
master_->invoke(*inv);
|
||||
}
|
||||
|
||||
// Check for keyboard input on stdin.
|
||||
while (true) {
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
|
||||
#include "wrap-vector.hpp"
|
||||
#include "wrap-string.hpp"
|
||||
#include "luastack.hpp"
|
||||
#include "util.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "invocation.hpp"
|
||||
#include "world.hpp"
|
||||
#include "traceback.hpp"
|
||||
#include "luaconsole.hpp"
|
||||
#include "pprint.hpp"
|
||||
#include "printbuffer.hpp"
|
||||
#include "drivenengine.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <csignal>
|
||||
|
||||
class TextGame : public DrivenEngine {
|
||||
private:
|
||||
using StringVec = LuaConsole::StringVec;
|
||||
UniqueWorld world_;
|
||||
LuaConsole console_;
|
||||
PrintChanneler print_channeler_;
|
||||
Gui gui_;
|
||||
int64_t actor_id_;
|
||||
|
||||
void do_luainvoke_command(const StringVec &words) {
|
||||
world_->invoke(Invocation(Invocation::KIND_LUA, actor_id_, actor_id_, words[1]));
|
||||
}
|
||||
|
||||
void do_luaprobe_command(const StringVec &words) {
|
||||
world_->snapshot();
|
||||
stdostream() << world_->probe_lua(actor_id_, words[1]);
|
||||
world_->rollback();
|
||||
}
|
||||
|
||||
void do_syntax_command(const StringVec &words) {
|
||||
stdostream() << "Syntax Error: " << words[1] << std::endl;
|
||||
}
|
||||
|
||||
void do_view_command(const StringVec &cmd) {
|
||||
stdostream() << world_->tangibles_near_debug_string(actor_id_, 100);
|
||||
}
|
||||
|
||||
void do_menu_command(const StringVec &cmd) {
|
||||
int64_t place = sv::to_int64(cmd[1], actor_id_);
|
||||
world_->update_gui(actor_id_, place, &gui_);
|
||||
stdostream() << gui_.menu_debug_string();
|
||||
}
|
||||
|
||||
void do_choose_command(const StringVec &cmd) {
|
||||
eng::string action = gui_.get_action(sv::to_int64(cmd[1]));
|
||||
if (action == "") {
|
||||
stdostream() << "Invalid menu item #" << std::endl;
|
||||
return;
|
||||
}
|
||||
Invocation inv(Invocation::KIND_PLAN, actor_id_, gui_.place(), action);
|
||||
stdostream() << "Invoking: " << inv.debug_string() << std::endl;
|
||||
world_->invoke(inv);
|
||||
}
|
||||
|
||||
void do_tick_command(const StringVec &cmd) {
|
||||
world_->invoke(Invocation(Invocation::KIND_TICK, actor_id_, actor_id_, ""));
|
||||
}
|
||||
|
||||
void do_quit_command(const StringVec &cmd) {
|
||||
actor_id_ = 0;
|
||||
}
|
||||
|
||||
void do_command(const StringVec &words) {
|
||||
if (words.empty()) return;
|
||||
else if (words[0] == "luainvoke") do_luainvoke_command(words);
|
||||
else if (words[0] == "luaprobe") do_luaprobe_command(words);
|
||||
else if (words[0] == "syntax") do_syntax_command(words);
|
||||
else if (words[0] == "view") do_view_command(words);
|
||||
else if (words[0] == "menu") do_menu_command(words);
|
||||
else if (words[0] == "quit") do_quit_command(words);
|
||||
else if (words[0] == "tick") do_tick_command(words);
|
||||
else if (words[0] == "choose") do_choose_command(words);
|
||||
else {
|
||||
stdostream() << "Unsupported command: " << words[0] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void check_redirects() {
|
||||
World::Redirects redir = world_->fetch_redirects();
|
||||
for (const auto &p : redir) {
|
||||
if (p.first == actor_id_) {
|
||||
actor_id_ = p.second;
|
||||
stdostream() << "Login actor ID: " << actor_id_ << std::endl;
|
||||
gui_.clear(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void event_init(int argc, char *argv[])
|
||||
{
|
||||
world_.reset(new World(WORLD_TYPE_MASTER));
|
||||
world_->update_source(get_lua_source_pack());
|
||||
world_->run_unittests();
|
||||
actor_id_ = world_->create_login_actor();
|
||||
stdostream() << "Login actor ID: " << actor_id_ << std::endl;
|
||||
set_console_prompt(console_.get_prompt());
|
||||
}
|
||||
|
||||
void event_update()
|
||||
{
|
||||
world_->update_source(get_lua_source_pack());
|
||||
while (true) {
|
||||
eng::string line = get_stdio_channel()->in()->readline();
|
||||
if (line == "") break;
|
||||
console_.add(line);
|
||||
set_console_prompt(console_.get_prompt());
|
||||
do_command(console_.get_command());
|
||||
if (print_channeler_.channel(world_->get_printbuffer(actor_id_), stdostream())) {
|
||||
world_->invoke(print_channeler_.invocation(actor_id_));
|
||||
}
|
||||
check_redirects();
|
||||
if (actor_id_ == 0) {
|
||||
stop_driver();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
UniqueDrivenEngine make_TextGame() {
|
||||
return UniqueDrivenEngine(new TextGame);
|
||||
}
|
||||
static DrivenEngineReg reg_TextGame("textgame", make_TextGame);
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
#ifndef TEXTGAME_HPP
|
||||
#define TEXTGAME_HPP
|
||||
|
||||
#include "drivenengine.hpp"
|
||||
|
||||
UniqueDrivenEngine make_TextGame();
|
||||
|
||||
#endif // TEXTGAME_HPP
|
||||
Reference in New Issue
Block a user