Implement the core of the login system

This commit is contained in:
2021-03-30 18:35:08 -04:00
parent 795a45c950
commit aa7de03c57
4 changed files with 113 additions and 32 deletions

View File

@@ -81,7 +81,7 @@ void TextGame::do_view_command(const StringVec &cmd) {
std::cerr << "v command (view) takes no arguments" << std::endl; std::cerr << "v command (view) takes no arguments" << std::endl;
return; return;
} }
for (int64_t id : world_->get_near(1, 100, true)) { for (int64_t id : world_->get_near(actor_id_, 100, true)) {
const Tangible *tan = world_->tangible_get(id); const Tangible *tan = world_->tangible_get(id);
const AnimStep &aqback = tan->anim_queue_.back(); const AnimStep &aqback = tan->anim_queue_.back();
std::cerr << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz() << std::endl; std::cerr << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz() << std::endl;
@@ -91,15 +91,15 @@ void TextGame::do_view_command(const StringVec &cmd) {
void TextGame::do_menu_command(const StringVec &cmd) { void TextGame::do_menu_command(const StringVec &cmd) {
int64_t id; int64_t id;
if (cmd.size() == 1) { if (cmd.size() == 1) {
id = 1; id = actor_id_;
} else if (cmd.size() == 2) { } else if (cmd.size() == 2) {
id = util::strtoint(cmd[1], -1); id = util::strtoint(cmd[1], -1);
} else { } else {
std::cerr << "m command (menu) expects a tangible ID or defaults to 1" << std::endl; std::cerr << "m command (menu) expects a tangible ID or defaults to actor_id" << std::endl;
return; return;
} }
gui_place_ = id; gui_place_ = id;
world_->update_gui(1, id, &gui_); world_->update_gui(actor_id_, id, &gui_);
int index = 0; int index = 0;
for (const GuiElt &elt : gui_.elts()) { for (const GuiElt &elt : gui_.elts()) {
std::cerr << index << " " << elt.label() << std::endl; std::cerr << index << " " << elt.label() << std::endl;
@@ -125,7 +125,7 @@ void TextGame::do_choose_command(const StringVec &cmd) {
GuiResult dummyresult; GuiResult dummyresult;
dummyresult["flavor"] = "chocolate"; dummyresult["flavor"] = "chocolate";
dummyresult["color"] = "blue"; dummyresult["color"] = "blue";
world_->invoke_plan(1, gui_place_, action, dummyresult); world_->invoke_plan(actor_id_, gui_place_, action, dummyresult);
} }
void TextGame::do_snapshot_command(const StringVec &cmd) { void TextGame::do_snapshot_command(const StringVec &cmd) {
@@ -164,12 +164,26 @@ void TextGame::do_command(const StringVec &words) {
} }
} }
void TextGame::check_redirects() {
World::Redirects redir = world_->fetch_redirects();
for (const auto &p : redir) {
if (p.first == actor_id_) {
actor_id_ = p.second;
std::cerr << "Login actor ID: " << actor_id_ << std::endl;
gui_.clear();
}
}
}
void TextGame::run() void TextGame::run()
{ {
world_.reset(new World); world_.reset(new World);
world_->init_standalone(); world_->init_standalone();
actor_id_ = world_->create_login_actor();
std::cerr << "Login actor ID: " << actor_id_ << std::endl;
console_.clear(); console_.clear();
while (true) { while (true) {
check_redirects();
console_.add_stdin(); console_.add_stdin();
int action = console_.action(); int action = console_.action();
if (action == LuaConsole::DO_LUA) { if (action == LuaConsole::DO_LUA) {

View File

@@ -13,6 +13,7 @@ private:
LuaConsole console_; LuaConsole console_;
Gui gui_; Gui gui_;
int64_t gui_place_; int64_t gui_place_;
int64_t actor_id_;
void do_view_command(const StringVec &cmd); void do_view_command(const StringVec &cmd);
void do_menu_command(const StringVec &cmd); void do_menu_command(const StringVec &cmd);
@@ -23,6 +24,8 @@ private:
void do_lua(const std::string &exp); void do_lua(const std::string &exp);
void do_command(const StringVec &exp); void do_command(const StringVec &exp);
void check_redirects();
public: public:
void run(); void run();
}; };

View File

@@ -72,29 +72,9 @@ void Tangible::deserialize(StreamBuffer *sb) {
update_plane_item(); update_plane_item();
} }
void Tangible::be_a_player() {
if (!id_player_pool_.fifo_enabled()) {
id_player_pool_.enable_fifo();
AnimStep asinit;
asinit.set_graphic("player");
anim_queue_.add(world_->id_global_pool_.get_one(), asinit);
anim_queue_.keep_only(1);
update_plane_item();
LuaVar classtab, mt, place, tangibles;
LuaStack LS(world_->state(), classtab, mt, place, tangibles);
LS.makeclass(classtab, "player");
LS.rawget(tangibles, LuaRegistry, "tangibles");
LS.rawget(place, tangibles, id());
LS.getmetatable(mt, place);
LS.rawset(mt, "__index", classtab);
LS.result();
}
}
void World::init_standalone() { void World::init_standalone() {
assert(stack_is_clear());
// Load the lua source from disk then rebuild the environment. // Load the lua source from disk then rebuild the environment.
source_db_.update(); source_db_.update();
source_db_.rebuild(); source_db_.rebuild();
@@ -102,9 +82,7 @@ void World::init_standalone() {
// Run unit tests. // Run unit tests.
source_db_.run_unittests(); source_db_.run_unittests();
// Create the player tangible. assert(stack_is_clear());
Tangible *player = tangible_make(state(), 1, false);
player->be_a_player();
} }
Tangible *World::tangible_get(int64_t id) { Tangible *World::tangible_get(int64_t id) {
@@ -207,7 +185,50 @@ Tangible *World::tangible_make(lua_State *L, int64_t id, bool pushdb) {
return t.get(); return t.get();
} }
World::Redirects World::fetch_redirects() {
World::Redirects result = std::move(redirects_);
redirects_.clear();
return std::move(result);
}
// void Tangible::be_a_player() {
// if (!id_player_pool_.fifo_enabled()) {
// id_player_pool_.enable_fifo();
// AnimStep asinit;
// asinit.set_graphic("player");
// anim_queue_.add(world_->id_global_pool_.get_one(), asinit);
// anim_queue_.keep_only(1);
// update_plane_item();
// LuaVar classtab, mt, place, tangibles;
// LuaStack LS(world_->state(), classtab, mt, place, tangibles);
// LS.makeclass(classtab, "player");
// LS.rawget(tangibles, LuaRegistry, "tangibles");
// LS.rawget(place, tangibles, id());
// LS.getmetatable(mt, place);
// LS.rawset(mt, "__index", classtab);
// LS.result();
// }
// }
int64_t World::create_login_actor() {
Tangible *tan = tangible_make(state(), 0, true);
LuaArg database;
LuaVar classtab, mt;
LuaStack LS(state(), database, classtab, mt);
LS.makeclass(classtab, "login");
LS.getmetatable(mt, database);
LS.rawset(mt, "__index", classtab);
LS.result();
tan->id_player_pool_.enable_fifo();
assert(stack_is_clear());
return tan->id();
}
void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) { void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
assert(stack_is_clear());
gui->clear(); gui->clear();
lua_State *L = state(); lua_State *L = state();
@@ -256,9 +277,12 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
// And we're done. // And we're done.
LS.result(); LS.result();
assert(stack_is_clear());
} }
void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, const GuiResult &gres) { void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, const GuiResult &gres) {
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);
@@ -334,9 +358,11 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &a
// then run the thread queue. // then run the thread queue.
thread_sched_.add(0, tid, place_id); thread_sched_.add(0, tid, place_id);
run_scheduled_threads(0); run_scheduled_threads(0);
assert(stack_is_clear());
} }
void World::run_scheduled_threads(int64_t clk) { void World::run_scheduled_threads(int64_t clk) {
assert(stack_is_clear());
lua_State *L = state(); lua_State *L = state();
LuaVar tangibles, place, mt, threads, thread; LuaVar tangibles, place, mt, threads, thread;
LuaStack LS(L, tangibles, place, mt, threads, thread); LuaStack LS(L, tangibles, place, mt, threads, thread);
@@ -391,9 +417,12 @@ void World::run_scheduled_threads(int64_t clk) {
} }
} }
LS.result(); LS.result();
assert(stack_is_clear());
} }
void World::serialize(StreamBuffer *sb) { void World::serialize(StreamBuffer *sb) {
assert(stack_is_clear());
assert(redirects_.empty());
int64_t wc0 = sb->write_count(); int64_t wc0 = sb->write_count();
lua_snap_.serialize(sb); lua_snap_.serialize(sb);
id_global_pool_.serialize(sb); id_global_pool_.serialize(sb);
@@ -405,9 +434,12 @@ void World::serialize(StreamBuffer *sb) {
} }
int64_t wc1 = sb->write_count(); int64_t wc1 = sb->write_count();
std::cerr << "World serialized to " << wc1-wc0 << " bytes." << std::endl; std::cerr << "World serialized to " << wc1-wc0 << " bytes." << std::endl;
assert(stack_is_clear());
} }
void World::deserialize(StreamBuffer *sb) { void World::deserialize(StreamBuffer *sb) {
assert(stack_is_clear());
redirects_.clear();
lua_snap_.deserialize(sb); lua_snap_.deserialize(sb);
id_global_pool_.deserialize(sb); id_global_pool_.deserialize(sb);
thread_sched_.deserialize(sb); thread_sched_.deserialize(sb);
@@ -435,6 +467,7 @@ void World::deserialize(StreamBuffer *sb) {
++iter; ++iter;
} }
} }
assert(stack_is_clear());
} }
void World::snapshot() { void World::snapshot() {
@@ -561,6 +594,16 @@ LuaDefine(tangible_get, "c") {
return LS.result(); return LS.result();
} }
LuaDefine(tangible_redirect, "c") {
LuaArg actor1, actor2;
LuaStack LS(L, actor1, actor2);
World *w = World::fetch_global_pointer(L);
Tangible *tan1 = w->tangible_get(L, actor1.index());
Tangible *tan2 = w->tangible_get(L, actor2.index());
w->redirects_[tan1->id()] = tan2->id();
return LS.result();
}
LuaDefine(world_wait, "f") { LuaDefine(world_wait, "f") {
if ((lua_gettop(L) != 1) || (lua_type(L, -1) != LUA_TNUMBER)) { if ((lua_gettop(L) != 1) || (lua_type(L, -1) != LUA_TNUMBER)) {
luaL_error(L, "Argument to wait must be a number."); luaL_error(L, "Argument to wait must be a number.");

View File

@@ -68,12 +68,13 @@ public:
// //
int64_t id() { return plane_item_.id(); } int64_t id() { return plane_item_.id(); }
void be_a_player(); // void be_a_player();
void update_plane_item(); void update_plane_item();
}; };
class World { class World {
public: public:
// A lua intepreter with snapshot function. // A lua intepreter with snapshot function.
// //
LuaSnap lua_snap_; LuaSnap lua_snap_;
@@ -99,8 +100,16 @@ public:
// Serialized snapshot of world model. // Serialized snapshot of world model.
StreamBuffer snapshot_; StreamBuffer snapshot_;
// Redirects.
//
using Redirects = std::map<int64_t, int64_t>;
Redirects redirects_;
void run_scheduled_threads(int64_t clk); void run_scheduled_threads(int64_t clk);
static void store_global_pointer(lua_State *L, World *w); static void store_global_pointer(lua_State *L, World *w);
// Check if main thread has nothing on the stack
bool stack_is_clear() const { return lua_gettop(state()) == 0; }
public: public:
// Constructor. // Constructor.
// //
@@ -125,7 +134,7 @@ public:
// //
// Get the lua interpreter associated with this world model. // Get the lua interpreter associated with this world model.
// //
lua_State *state() { return lua_snap_.state(); } lua_State *state() const { return lua_snap_.state(); }
// get_near // get_near
// //
@@ -157,6 +166,18 @@ public:
// //
void tangible_delete(lua_State *L, int64_t id); void tangible_delete(lua_State *L, int64_t id);
// Create a login actor.
//
// Creates a tangible of class 'login' and returns its ID.
// This is used to create a temporary actor which is used during
// the login process.
//
int64_t create_login_actor();
// Fetch all redirects and clear the redirects table.
//
Redirects fetch_redirects();
// Probe the 'interface' function of the specified sprite. // Probe the 'interface' function of the specified sprite.
// //
void update_gui(int64_t actor_id, int64_t place_id, Gui *gui); void update_gui(int64_t actor_id, int64_t place_id, Gui *gui);