From b0440a4e1218fb00f585f830a818b89e00edac72 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Fri, 22 Jan 2021 17:35:23 -0500 Subject: [PATCH] Viewer is ready to go, I think --- luprex/build.bat | 2 +- luprex/debug.log | 1 + luprex/syscpp/animqueue.cpp | 5 +++ luprex/syscpp/animqueue.hpp | 25 ++++++++++- luprex/syscpp/main.cpp | 6 +-- luprex/syscpp/planemap.cpp | 27 +++++++----- luprex/syscpp/planemap.hpp | 8 +++- luprex/syscpp/viewer.cpp | 88 +++++++++++++++++++++++++++++++++++++ luprex/syscpp/viewer.hpp | 32 +++++++++++--- luprex/syscpp/world.cpp | 38 +++++++++++++--- luprex/syscpp/world.hpp | 36 ++++++++++++--- 11 files changed, 234 insertions(+), 34 deletions(-) create mode 100644 luprex/debug.log diff --git a/luprex/build.bat b/luprex/build.bat index e0243437..d92e9382 100644 --- a/luprex/build.bat +++ b/luprex/build.bat @@ -1,2 +1,2 @@ clear -g++ -std=c++17 -Wall -g -o main syscpp/util.cpp syscpp/main.cpp syscpp/animqueue.cpp syscpp/planemap.cpp syscpp/world.cpp syscpp/traceback.cpp syscpp/luastack.cpp syscpp/source.cpp syscpp/table.cpp syscpp/idalloc.cpp syscpp/globaldb.cpp -Iinc -Llib lib/libluajit-dbg.a -Isyscpp +g++ -std=c++17 -Wall -g -o main syscpp/util.cpp syscpp/viewer.cpp syscpp/main.cpp syscpp/animqueue.cpp syscpp/planemap.cpp syscpp/world.cpp syscpp/traceback.cpp syscpp/luastack.cpp syscpp/source.cpp syscpp/table.cpp syscpp/idalloc.cpp syscpp/globaldb.cpp -Iinc -Llib lib/libluajit-dbg.a -Isyscpp diff --git a/luprex/debug.log b/luprex/debug.log new file mode 100644 index 00000000..14d7d56d --- /dev/null +++ b/luprex/debug.log @@ -0,0 +1 @@ +[0118/005706.947:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3) diff --git a/luprex/syscpp/animqueue.cpp b/luprex/syscpp/animqueue.cpp index a969a80e..1171f9b0 100644 --- a/luprex/syscpp/animqueue.cpp +++ b/luprex/syscpp/animqueue.cpp @@ -65,6 +65,11 @@ void AnimQueue::set_plane(const std::string &p) { last.plane_ = p; } +const std::string &AnimQueue::get_graphic() const { + const AnimStep &last = steps_.back(); + return last.graphic_; +} + const std::string &AnimQueue::get_plane() const { const AnimStep &last = steps_.back(); return last.plane_; diff --git a/luprex/syscpp/animqueue.hpp b/luprex/syscpp/animqueue.hpp index e6e7f080..df586aa2 100644 --- a/luprex/syscpp/animqueue.hpp +++ b/luprex/syscpp/animqueue.hpp @@ -87,7 +87,8 @@ public: void set_graphic(const std::string &g); void set_plane(const std::string &p); - // Get the final resting place. + // Get the final resting place after all animations are complete. + const std::string &get_graphic() const; const std::string &get_plane() const; const util::XYZ &get_xyz() const; @@ -95,5 +96,27 @@ public: void set_size_limit(int n); }; +class AnimView { +private: + std::string graphic_; + std::string plane_; + util::XYZ xyz_; + bool updated_; +public: + const std::string &get_graphic() { return graphic_; } + const std::string &get_plane() { return plane_; } + const util::XYZ &get_xyz() { return xyz_; } + bool updated() { return updated_; } + + void update_from(const AnimQueue &queue) { + graphic_ = queue.get_graphic(); + plane_ = queue.get_plane(); + xyz_ = queue.get_xyz(); + updated_ = true; + } + + void set_updated(bool u) { updated_ = u; } +}; + #endif // ANIMQUEUE_HPP diff --git a/luprex/syscpp/main.cpp b/luprex/syscpp/main.cpp index 93bd89a2..eed2e186 100644 --- a/luprex/syscpp/main.cpp +++ b/luprex/syscpp/main.cpp @@ -14,7 +14,7 @@ #include #include "luastack.hpp" #include "util.hpp" -#include "world.hpp" +#include "viewer.hpp" #include "traceback.hpp" @@ -177,7 +177,7 @@ static void dotty(lua_State *L) int main(int argc, char **argv) { LUAJIT_VERSION_SYM(); // Linker-enforced version check. - World w; - dotty(w.get_lua_state()); + Viewer v; + dotty(v.get_lua_state()); return 0; } diff --git a/luprex/syscpp/planemap.cpp b/luprex/syscpp/planemap.cpp index 54259b46..9b822ebf 100644 --- a/luprex/syscpp/planemap.cpp +++ b/luprex/syscpp/planemap.cpp @@ -176,8 +176,8 @@ int PlaneMap::total_cells() const { return total; } -PlaneMap::EltVec PlaneMap::scan_radius(const std::string &plane, double x, double y, double radius) const { - PlaneMap::EltVec result; +PlaneMap::IdVec PlaneMap::scan_radius(const std::string &plane, double x, double y, double radius) const { + PlaneMap::IdVec result; auto piter = planes_.find(plane); if (piter != planes_.end()) { const Plane &p = piter->second; @@ -189,7 +189,7 @@ PlaneMap::EltVec PlaneMap::scan_radius(const std::string &plane, double x, doubl if (liter != p.end()) { for (PlaneItem *client : liter->second) { if (util::distance_squared(client->x(), client->y(), x, y) <= radsq) { - result.push_back(client); + result.push_back(client->id()); } } } @@ -207,6 +207,7 @@ LuaDefine(unittests_planemap, "c") { PlaneMap pm; PlaneItem pia, pib; PlaneMap::EltVec elts; + PlaneMap::IdVec ids; // Simple test. LuaAssert(L, rect_cell_range(-7*SC, -15*SC, 87*SC, 21*SC).equal(-7, -15, 87, 21)); @@ -306,13 +307,19 @@ LuaDefine(unittests_planemap, "c") { // Insert the four elements, then test the scan function. pm.track(&pib); + pia.set_id(123); + pib.set_id(456); pib.set_pos("bar", 1100.0, 1000.0, 0.0); - elts = pm.scan_radius("bar", 1000.0, 1000.0, 1.0); - LuaAssert(L, elts.size() == 1); - elts = pm.scan_radius("bar", 1000.0, 1000.0, 99.9); - LuaAssert(L, elts.size() == 1); - elts = pm.scan_radius("bar", 1000.0, 1000.0, 100.0); - LuaAssert(L, elts.size() == 2); - + ids = pm.scan_radius("bar", 1000.0, 1000.0, 1.0); + LuaAssert(L, ids.size() == 1); + LuaAssert(L, ids[0] == 123); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 99.9); + LuaAssert(L, ids.size() == 1); + LuaAssert(L, ids[0] == 123); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 100.0); + LuaAssert(L, ids.size() == 2); + LuaAssert(L, ids[0] == 123); + LuaAssert(L, ids[1] == 456); + return 0; } diff --git a/luprex/syscpp/planemap.hpp b/luprex/syscpp/planemap.hpp index 9970e70b..a9ca4bfc 100644 --- a/luprex/syscpp/planemap.hpp +++ b/luprex/syscpp/planemap.hpp @@ -86,11 +86,16 @@ private: PlaneMap *pmap_; std::string plane_; double x_, y_, z_; + int64_t id_; public: PlaneItem(); ~PlaneItem(); + // You may modify the ID at any time. + void set_id(int64_t id) { id_ = id; } + + int64_t id() const { return id_; } const std::string &plane() const { return plane_; } const double x() const { return x_; } const double y() const { return y_; } @@ -111,10 +116,11 @@ private: void insert(const std::string &plane, int64_t cell, PlaneItem *client); public: + using IdVec = std::vector; PlaneMap(); ~PlaneMap(); void track(PlaneItem *item); - EltVec scan_radius(const std::string &plane, double x, double y, double radius) const; + IdVec scan_radius(const std::string &plane, double x, double y, double radius) const; private: // unit testing stuff. diff --git a/luprex/syscpp/viewer.cpp b/luprex/syscpp/viewer.cpp index e69de29b..b21ace75 100644 --- a/luprex/syscpp/viewer.cpp +++ b/luprex/syscpp/viewer.cpp @@ -0,0 +1,88 @@ + +#include "viewer.hpp" + +Viewer::Viewer() { + world_.reset(new World); + world_->init_standalone(); +} + +Viewer::~Viewer() { +} + +int64_t Viewer::get_player_id() { + return 1; +} + + +void Viewer::update_view() { + // Get ready to delete views that aren't in use. + // + for (auto pair : anim_view_) { + pair.second.set_updated(false); + } + + // Update the player's AnimView first. + // + Tangible *player = world_->tangible_get(1); + AnimView *player_view = &anim_view_[1]; + player_view->update_from(player->anim_queue_); + + // Find out where's the center of the world. + // + std::string plane = player_view->get_plane(); + util::XYZ xyz = player_view->get_xyz(); + + // Get a list of everything near the player. + // + tangibles_ = world_->scan_radius(plane, xyz.x, xyz.y, 100.0); + + // Update AnimViews for every tangible near the player. + // + for (int64_t id : tangibles_) { + Tangible *tan = world_->tangible_get(id); + assert (tan != nullptr); + anim_view_[id].update_from(tan->anim_queue_); + } + + // Delete any AnimView that was not updated. + // + for (auto iter = anim_view_.begin(); iter != anim_view_.end(); ) { + if (iter->second.updated()) { + iter++; + } else { + iter = anim_view_.erase(iter); + } + } +} + +const std::vector &Viewer::get_tangibles_near_player() { + return tangibles_; +} + +AnimView *Viewer::get_animation_view(int64_t id) { + auto iter = anim_view_.find(id); + if (iter == anim_view_.end()) { + return nullptr; + } else { + return &iter->second; + } +} + +// Get the menu of the specified tangible. +// +std::vector Viewer::get_menu(int64_t id) { + std::vector result; + result.push_back("north"); + result.push_back("south"); + result.push_back("east"); + result.push_back("west"); + result.push_back("build"); + result.push_back("destroy"); + return result; +} + +void Viewer::choose_menu_item(int64_t id, const std::string &item) { +} + +void Viewer::advance_clock() { +}; diff --git a/luprex/syscpp/viewer.hpp b/luprex/syscpp/viewer.hpp index 36f8a1a0..fe80b427 100644 --- a/luprex/syscpp/viewer.hpp +++ b/luprex/syscpp/viewer.hpp @@ -1,19 +1,39 @@ #ifndef VIEWER_HPP #define VIEWER_HPP -class Viewer { -public: - // Initialize a standalone game. - // - void init_standalone(); +#include "world.hpp" +#include "animqueue.hpp" +#include +#include +#include +#include +class Viewer { +private: + std::unique_ptr world_; + std::vector tangibles_; + std::unordered_map anim_view_; + + +public: + Viewer(); + ~Viewer(); + + // Get the lua state for interaction. + // + lua_State *get_lua_state() { return world_->get_lua_state(); } + // Get the player ID of the current player. // int64_t get_player_id(); + // Update the view. + // + void update_view(); + // Get a list of the tangibles in viewing radius of the player. // - std::vector get_tangibles_near_player(); + const std::vector &get_tangibles_near_player(); // Get the animation viewer of the specified tangible. // diff --git a/luprex/syscpp/world.cpp b/luprex/syscpp/world.cpp index 582e5d7f..04ca3adb 100644 --- a/luprex/syscpp/world.cpp +++ b/luprex/syscpp/world.cpp @@ -38,27 +38,54 @@ World::World() { // Initialize the SourceDB source_db_.initialize(lua_state_); + source_db_.rebuild(); +} - // Do an initial lua source update and then environment rebuild. +void Tangible::be_a_player() { + if (id_player_pool_ == nullptr) { + id_player_pool_.reset(new IdPlayerPool(&world_->id_global_pool_)); + } +} + +void World::init_standalone() { + // Load the lua source from disk then rebuild the environment. source_db_.update(); source_db_.rebuild(); // Run unit tests. source_db_.run_unittests(); + + // Create the player tangible. + Tangible *player = tangible_make(lua_state_, 1, false); + player->be_a_player(); } -Tangible *World::tangible_make(lua_State *L) { +std::vector World::scan_radius(const std::string &plane, float x, float y, float radius) { + return plane_map_.scan_radius(plane, x, y, radius); +} + +Tangible *World::tangible_get(int64_t id) { + auto iter = tangibles_.find(id); + if (iter == tangibles_.end()) { + return nullptr; + } else { + return &iter->second; + } +} + +Tangible *World::tangible_make(lua_State *L, int64_t id, bool pushdb) { LuaVar tangibles, metatab; LuaRet database; LuaStack LS(L, tangibles, database, metatab); - // Get a fresh ID. - int64_t id = id_global_pool_.alloc_id_for_thread(L); + // Allocate an ID if we don't already have one. + if (id == 0) id = id_global_pool_.alloc_id_for_thread(L); // Create the C++ part of the structure. Tangible *t = &tangibles_[id]; assert(t->world_ == nullptr); t->world_ = this; + t->plane_item_.set_id(id); plane_map_.track(&t->plane_item_); // Create the tangible's database and metatable. @@ -77,6 +104,7 @@ Tangible *World::tangible_make(lua_State *L) { // LS.setfield(metatab, "__metatable", LuaNil); LS.result(); + if (!pushdb) lua_pop(L, 1); return t; } @@ -101,6 +129,6 @@ LuaDefine(tangible_get, "c") { } LuaDefine(tangible_make, "c") { - World::fetch(L)->tangible_make(L); + World::fetch(L)->tangible_make(L, 0, true); return 1; } diff --git a/luprex/syscpp/world.hpp b/luprex/syscpp/world.hpp index 29087aff..61f4035e 100644 --- a/luprex/syscpp/world.hpp +++ b/luprex/syscpp/world.hpp @@ -21,17 +21,23 @@ public: // Always points back to the world model. World *world_; - // Animation queue and plane item. + // Animation queue. // - // To update the position of this tangible, first add an animation in which - // the tangible moves, then call plane_item.set_pos_from(anim_queue_). - PlaneItem plane_item_; AnimQueue anim_queue_; + // Plane Item. + // + // The PlaneItem also contains this tangible's ID. + // To move this Tangible, update the anim_queue first, then update + // this plane_item_ from the anim_queue. + PlaneItem plane_item_; + // Player ID pool // // Note: this is only allocated if this Tangible is a player. std::unique_ptr id_player_pool_; + + void be_a_player(); }; class World { @@ -66,18 +72,34 @@ public: // ~World(); + // Initialize for single-player mode. + // + void init_standalone(); + // get_lua_state // // Get the lua interpreter associated with this world model. // lua_State *get_lua_state() { return lua_state_; } - // Make a tangible with a generated ID. + // scan_near // - // Pushes the database onto the lua stack and returns the tangible pointer. + // Get a list of the tangibles near the specified player ID. // - Tangible *tangible_make(lua_State *L); + std::vector scan_radius(const std::string &plane, float x, float y, float radius); + + // Make a tangible. + // + // If the ID is zero, allocates an ID using the thread's ID allocator. If + // pushdb is true, pushes the tangible's database onto the lua stack. + // Otherwise, leaves the lua stack untouched. + // + Tangible *tangible_make(lua_State *L, int64_t id, bool pushdb); + // Get a pointer to the specified tangible. + // + Tangible *tangible_get(int64_t id); + // Delete a tangible with the specified ID. // // If the tangible doesn't exist, does nothing.