diff --git a/luprex/syscpp/animqueue.cpp b/luprex/syscpp/animqueue.cpp index d588711b..149cc5f0 100644 --- a/luprex/syscpp/animqueue.cpp +++ b/luprex/syscpp/animqueue.cpp @@ -1,5 +1,6 @@ #include "animqueue.hpp" +#include "luastack.hpp" #include @@ -16,7 +17,7 @@ AnimQueue::AnimQueue(int size_limit) { init.xyz_ = util::XYZ(0,0,0); init.graphic_ = "nothing"; init.plane_ = "nowhere"; - init.bits_ = 0; + init.bits_ = AnimStep::HAS_EVERYTHING; } void AnimQueue::add(int64_t id, const std::string &action) { @@ -33,7 +34,7 @@ void AnimQueue::add(int64_t id, const std::string &action) { AnimStep &init = steps_.front(); init.id_ = 0; init.action_ = ""; - init.bits_ = 0; + init.bits_ = AnimStep::HAS_EVERYTHING; } void AnimQueue::set_facing(float f) { @@ -59,3 +60,64 @@ void AnimQueue::set_plane(const std::string &p) { last.bits_ |= AnimStep::HAS_PLANE; last.plane_ = p; } + +const std::string &AnimQueue::get_plane() const { + const AnimStep &last = steps_.back(); + return last.plane_; +} + +const util::XYZ &AnimQueue::get_xyz() const { + const AnimStep &last = steps_.back(); + return last.xyz_; +} + +LuaDefine(unittests_animqueue, "c") { + // Check initial state. + AnimQueue aq(3); + LuaAssert(L, aq.size() == 1); + const AnimStep *st = &aq.nth(0); + LuaAssert(L, st->id() == 0); + LuaAssert(L, st->action() == ""); + LuaAssert(L, st->bits() == AnimStep::HAS_EVERYTHING); + LuaAssert(L, st->facing() == 0.0); + LuaAssert(L, st->xyz() == util::XYZ(0,0,0)); + LuaAssert(L, st->graphic() == "nothing"); + LuaAssert(L, st->plane() == "nowhere"); + + // Add a step. + aq.add(12345, "walk"); + LuaAssert(L, aq.size() == 2); + st = &aq.nth(1); + LuaAssert(L, st->id() == 12345); + LuaAssert(L, st->action() == "walk"); + LuaAssert(L, st->bits() == 0); + LuaAssert(L, st->facing() == 0.0); + LuaAssert(L, st->xyz() == util::XYZ(0,0,0)); + LuaAssert(L, st->graphic() == "nothing"); + LuaAssert(L, st->plane() == "nowhere"); + + // Test the setters. + aq.set_facing(180); + LuaAssert(L, st->facing() == 180); + LuaAssert(L, st->bits() == AnimStep::HAS_FACING); + aq.set_xyz(util::XYZ(3,4,5)); + LuaAssert(L, st->xyz() == util::XYZ(3, 4, 5)); + LuaAssert(L, st->bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ)); + aq.set_plane("somewhere"); + LuaAssert(L, st->plane() == "somewhere"); + LuaAssert(L, st->bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ | AnimStep::HAS_PLANE)); + aq.set_graphic("something"); + LuaAssert(L, st->graphic() == "something"); + LuaAssert(L, st->bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ | AnimStep::HAS_PLANE | AnimStep::HAS_GRAPHIC)); + + // Exceed the length limit, dropping first element. + aq.add(12346, "walk"); + aq.add(12347, "walk"); + LuaAssert(L, aq.size() == 3); + LuaAssert(L, aq.nth(0).id() == 0); + LuaAssert(L, aq.nth(0).action() == ""); + LuaAssert(L, aq.nth(0).bits() == AnimStep::HAS_EVERYTHING); + LuaAssert(L, aq.nth(1).id() == 12346); + LuaAssert(L, aq.nth(2).id() == 12347); + return 0; +} diff --git a/luprex/syscpp/animqueue.hpp b/luprex/syscpp/animqueue.hpp index 002b0c9d..c3164bd6 100644 --- a/luprex/syscpp/animqueue.hpp +++ b/luprex/syscpp/animqueue.hpp @@ -39,6 +39,7 @@ public: HAS_XYZ = 2, HAS_GRAPHIC = 4, HAS_PLANE = 8, + HAS_EVERYTHING = 15, }; private: @@ -85,6 +86,10 @@ public: void set_xyz(util::XYZ xyz); void set_graphic(const std::string &g); void set_plane(const std::string &p); + + // Get the final resting place. + const std::string &get_plane() const; + const util::XYZ &get_xyz() const; }; #endif // ANIMQUEUE_HPP diff --git a/luprex/syscpp/idalloc.hpp b/luprex/syscpp/idalloc.hpp index c50a5ecc..17213519 100644 --- a/luprex/syscpp/idalloc.hpp +++ b/luprex/syscpp/idalloc.hpp @@ -129,7 +129,7 @@ private: public: // Construct a player pool. // The Player pool stores a pointer to the global pool. - IdPlayerPool(IdGlobalPool *gp); + IdPlayerPool(IdGlobalPool *igp); ~IdPlayerPool(); // Refill the fifo queue of batches from the global pool. diff --git a/luprex/syscpp/main.cpp b/luprex/syscpp/main.cpp index 1ff058d0..93bd89a2 100644 --- a/luprex/syscpp/main.cpp +++ b/luprex/syscpp/main.cpp @@ -14,7 +14,7 @@ #include #include "luastack.hpp" #include "util.hpp" -#include "source.hpp" +#include "world.hpp" #include "traceback.hpp" @@ -174,43 +174,10 @@ static void dotty(lua_State *L) fflush(stdout); } -static int pmain(lua_State *L) -{ - globalL = L; - - LUAJIT_VERSION_SYM(); /* Linker-enforced version check. */ - - LuaStack::register_all_userdata(L); - - // Initialize the builtins, then copy a snapshot of the - // builtins to the registry. The snapshot will allow us to restore - // the builtins during source_rebuild operations. - source_install_and_snapshot_builtins(L); - - // Load the lua source. - source_update(L); - - // Rebuild the global environment. - source_rebuild(L); - - // Run unit tests. - source_run_unittests(L); - - dotty(L); - return 0; -} - int main(int argc, char **argv) { - int status; - lua_State *L = lua_open(); - if (L == NULL) - { - l_message("cannot create state: not enough memory"); - return -1; - } - status = lua_cpcall(L, pmain, NULL); - report(L, status); - lua_close(L); - return status ? -1 : 0; + LUAJIT_VERSION_SYM(); // Linker-enforced version check. + World w; + dotty(w.get_lua_state()); + return 0; } diff --git a/luprex/syscpp/planemap.cpp b/luprex/syscpp/planemap.cpp index 54259b46..bb6a917a 100644 --- a/luprex/syscpp/planemap.cpp +++ b/luprex/syscpp/planemap.cpp @@ -13,7 +13,7 @@ #define CELL_INVALID 0 // Round a float and return as integer. Clamp result to the specified range. -static int round_and_clamp(double x, int lo, int hi) { +static int round_and_clamp(float x, int lo, int hi) { x = round(x); if (x < lo) return lo; if (x > hi) return hi; @@ -38,7 +38,7 @@ struct CellRange { // the map: in that case, returns exactly the valid cells and not the // invalid ones. // -static CellRange rect_cell_range(double x1, double y1, double x2, double y2) { +static CellRange rect_cell_range(float x1, float y1, float x2, float y2) { CellRange result; result.xlo = round_and_clamp(x1 / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT + 1); result.ylo = round_and_clamp(y1 / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT + 1); @@ -54,9 +54,9 @@ static int64_t cell_id(int64_t cellx, int64_t celly) { } // Get the cell ID of the specified point, or CELL_INVALID if the point is off the map. -static int64_t point_cell_id(double x, double y) { - double cellx = round(x / CELL_SCALE); - double celly = round(y / CELL_SCALE); +static int64_t point_cell_id(float x, float y) { + float cellx = round(x / CELL_SCALE); + float celly = round(y / CELL_SCALE); if ((cellx < -CELL_LIMIT) || (celly < -CELL_LIMIT) || (cellx > CELL_LIMIT) || (celly > CELL_LIMIT)) { return CELL_INVALID; } @@ -101,10 +101,10 @@ void PlaneMap::insert(const std::string &plane, int64_t cellid, PlaneItem *clien l.push_back(client); } -void PlaneItem::set_pos(const std::string &plane, double x, double y, double z) { - int64_t old_cell = point_cell_id(x_, y_); - int64_t new_cell = point_cell_id(x, y); - +void PlaneItem::set_pos(const std::string &plane, const util::XYZ &xyz) { + int64_t old_cell = point_cell_id(xyz_.x, xyz_.y); + int64_t new_cell = point_cell_id(xyz.x, xyz.y); + // Update the grid. if (pmap_ != 0) { if ((plane_ != plane) || (old_cell != new_cell)) { @@ -115,14 +115,12 @@ void PlaneItem::set_pos(const std::string &plane, double x, double y, double z) // Update the client position. plane_ = plane; - x_ = x; - y_ = y; - z_ = z; + xyz_ = xyz; } void PlaneItem::untrack() { if (pmap_ != 0) { - pmap_->remove(plane_, point_cell_id(x_, y_), this); + pmap_->remove(plane_, point_cell_id(xyz_.x, xyz_.y), this); pmap_ = 0; } } @@ -135,7 +133,7 @@ void PlaneMap::track(PlaneItem *item) { } } -PlaneItem::PlaneItem() : pmap_(NULL), x_(0.0), y_(0.0), z_(0.0) { +PlaneItem::PlaneItem() : pmap_(NULL), xyz_(0,0,0) { } PlaneMap::PlaneMap() { @@ -176,13 +174,13 @@ 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 PlaneMap::scan_radius(const std::string &plane, float x, float y, float radius) const { PlaneMap::EltVec result; auto piter = planes_.find(plane); if (piter != planes_.end()) { const Plane &p = piter->second; CellRange range = rect_cell_range(x - radius, y - radius, x + radius, y + radius); - double radsq = radius*radius; + float radsq = radius*radius; for (int cy = range.ylo; cy <= range.yhi; cy++) { for (int cx = range.xlo; cx <= range.xhi; cx++) { auto liter = p.find(cell_id(cx, cy)); @@ -200,8 +198,8 @@ PlaneMap::EltVec PlaneMap::scan_radius(const std::string &plane, double x, doubl } LuaDefine(unittests_planemap, "c") { - double SC = CELL_SCALE; - double E = CELL_SCALE * 0.4; + float SC = CELL_SCALE; + float E = CELL_SCALE * 0.4; int LO = -CELL_LIMIT; int HI = CELL_LIMIT; PlaneMap pm; @@ -314,5 +312,15 @@ LuaDefine(unittests_planemap, "c") { elts = pm.scan_radius("bar", 1000.0, 1000.0, 100.0); LuaAssert(L, elts.size() == 2); + // Test static_field_cast. + struct MyTangible { + int x, y, z; + PlaneItem plane_item_; + }; + MyTangible tan; + PlaneItem *pip = &tan.plane_item_; + MyTangible *tanp = pip->static_field_cast(); + LuaAssert(L, tanp == &tan); + return 0; } diff --git a/luprex/syscpp/planemap.hpp b/luprex/syscpp/planemap.hpp index 9970e70b..b089c655 100644 --- a/luprex/syscpp/planemap.hpp +++ b/luprex/syscpp/planemap.hpp @@ -74,8 +74,10 @@ #define PLANEMAP_HPP #include +#include #include #include +#include "util.hpp" class PlaneMap; @@ -85,20 +87,38 @@ class PlaneItem { private: PlaneMap *pmap_; std::string plane_; - double x_, y_, z_; + util::XYZ xyz_; public: PlaneItem(); ~PlaneItem(); const std::string &plane() const { return plane_; } - const double x() const { return x_; } - const double y() const { return y_; } - const double z() const { return z_; } + const util::XYZ &xyz() const { return xyz_; } + const float x() const { return xyz_.x; } + const float y() const { return xyz_.y; } + const float z() const { return xyz_.z; } void untrack(); - void set_pos(const std::string &plane, double x, double y, double z); - void set_xyz(double x, double y, double z) { set_pos(plane_, x, y, z); } + void set_pos(const std::string &plane, const util::XYZ &xyz); + void set_pos(const std::string &plane, float x, float y, float z) { set_pos(plane, util::XYZ(x,y,z)); } + void set_xyz(const util::XYZ &xyz) { set_pos(plane_, xyz); } + void set_xyz(float x, float y, float z) { set_pos(plane_, util::XYZ(x, y, z)); } + + // Assume that some other object has methods 'get_plane' and 'get_xyz'. + // Get the plane and XYZ from that object and store it in this PlaneItem. + template + void set_pos_from(const T &obj) { + set_pos(obj.get_plane(), obj.get_xyz()); + } + + // Assume that the PlaneItem is a field in an object of class T. + // Static cast the PlaneItem pointer to a type T pointer. + template + T *static_field_cast() { + const std::size_t offset = offsetof(T, plane_item_); + return reinterpret_cast(reinterpret_cast(this) - offset); + } }; class PlaneMap { @@ -114,7 +134,7 @@ public: PlaneMap(); ~PlaneMap(); void track(PlaneItem *item); - EltVec scan_radius(const std::string &plane, double x, double y, double radius) const; + EltVec scan_radius(const std::string &plane, float x, float y, float radius) const; private: // unit testing stuff. diff --git a/luprex/syscpp/source.cpp b/luprex/syscpp/source.cpp index 167cebc0..55beb5d1 100644 --- a/luprex/syscpp/source.cpp +++ b/luprex/syscpp/source.cpp @@ -64,7 +64,7 @@ static void load_builtin(lua_State *L, const char *name, lua_CFunction func) { lua_call(L, 1, 0); } -LuaDefine(source_install_builtins, "") { +static void source_install_builtins(lua_State *L) { LuaStack LS(L); load_builtin(L, "base", luaopen_base); load_builtin(L, "table", luaopen_table); @@ -72,11 +72,10 @@ LuaDefine(source_install_builtins, "") { load_builtin(L, "math", luaopen_math); load_builtin(L, "bit", luaopen_math); load_builtin(L, "debug", luaopen_debug); - // Do not load: package, io, os, debug, jit - return 0; } -LuaDefine(source_install_and_snapshot_builtins, "") { +void SourceDB::initialize(lua_State *L) { + lua_state_ = L; LuaVar key, value, skey, svalue, snapshot, ssnapshot; LuaStack LS(L, snapshot, key, value, skey, svalue, ssnapshot); @@ -99,10 +98,10 @@ LuaDefine(source_install_and_snapshot_builtins, "") { } } LS.setfield(LuaRegistry, "source_snapshot_builtins", snapshot); - return LS.result(); + LS.result(); } -LuaDefine(source_updatefile, "") { +static int source_updatefile(lua_State *L) { LuaArg source, fn; LuaRet info; LuaVar fingerprint, null; @@ -127,7 +126,7 @@ LuaDefine(source_updatefile, "") { if (LS.isstring(fingerprint)) { old_fingerprint = LS.ckstring(fingerprint); } - std::cerr << "Probing " << cfn << std::endl; + // std::cerr << "Probing " << cfn << std::endl; std::string new_fingerprint = util::get_file_fingerprint("syslua/" + cfn); LS.set(null, LuaNil); if ((old_fingerprint == "") || (old_fingerprint != new_fingerprint)) { @@ -147,7 +146,8 @@ LuaDefine(source_updatefile, "") { return LS.result(); } -LuaDefine(source_update, "c") { +void SourceDB::update() { + lua_State *L = lua_state_; LuaVar sourcedb, newdb, info, fn, seq; LuaStack LS(L, newdb, sourcedb, info, fn, seq); @@ -180,13 +180,13 @@ LuaDefine(source_update, "c") { // Store the new source db. LS.setfield(LuaRegistry, "sourcedb", newdb); - return LS.result(); + LS.result(); } // Delete everything from the global environment except // the class tables and the class action tables. // -LuaDefine(source_clear_globals, "") { +static void source_clear_globals(lua_State *L) { LuaVar classname, classtab, action, key; LuaStack LS(L, classname, classtab, action, key); @@ -209,12 +209,12 @@ LuaDefine(source_clear_globals, "") { } } LS.setfield(LuaGlobals, "_G", LuaGlobals); - return LS.result(); + LS.result(); } // Restore the lua builtins from the backup snapshot. // -LuaDefine(source_restore_builtins, "") { +static void source_restore_builtins(lua_State *L) { LuaVar snapshot, key, value, skey, svalue, subglobal; LuaStack LS(L, snapshot, key, value, skey, svalue, subglobal); @@ -229,12 +229,12 @@ LuaDefine(source_restore_builtins, "") { LS.rawset(subglobal, skey, svalue); } } - return LS.result(); + LS.result(); } // Load all the 'LuaDefine' C functions into the lua state. // -LuaDefine(source_load_cfunctions, "") { +static void source_load_cfunctions(lua_State *L) { auto regs = LuaFunctionReg::all(); for (const LuaFunctionReg *r : regs) { const std::string &name = r->get_name(); @@ -260,12 +260,11 @@ LuaDefine(source_load_cfunctions, "") { lua_setglobal(L, funcname.c_str()); } } - return 0; } // Run all the closures from the source database. // -LuaDefine(source_load_lfunctions, "") { +static void source_load_lfunctions(lua_State *L) { LuaRet errors; LuaVar sourcedb, key, info, seq, closure, err; LuaStack LS(L, sourcedb, errors, key, info, seq, closure, err); @@ -305,10 +304,11 @@ LuaDefine(source_load_lfunctions, "") { } } LS.set(errors, errss.str()); - return LS.result(); + LS.result(); } -LuaDefine(source_rebuild, "c") { +void SourceDB::rebuild() { + lua_State *L = lua_state_; LuaVar errs; LuaStack LS(L, errs); source_clear_globals(L); @@ -318,13 +318,13 @@ LuaDefine(source_rebuild, "c") { lua_replace(L, errs.index()); std::string errstr = LS.ckstring(errs); std::cerr << errstr; - return LS.result(); + LS.result(); } -LuaDefine(source_run_unittests, "c") { +void SourceDB::run_unittests() { + lua_State *L = lua_state_; LuaVar unittests, name, func, err; - LuaRet rescode; - LuaStack LS(L, unittests, name, func, err, rescode); + LuaStack LS(L, unittests, name, func, err); LS.getfield(unittests, LuaGlobals, "unittests"); @@ -351,8 +351,9 @@ LuaDefine(source_run_unittests, "c") { } } - // Return 1 if any errors. - LS.set(rescode, any ? 1 : 0); - return LS.result(); + if (any) { + exit(1); + } + LS.result(); } diff --git a/luprex/syscpp/source.hpp b/luprex/syscpp/source.hpp index 44ef7025..614477ac 100644 --- a/luprex/syscpp/source.hpp +++ b/luprex/syscpp/source.hpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////// // -// SOURCE +// SOURCEDB // // This module manages the loading of lua source files into the Lua environment. // Since the source files can be reloaded over and over, this module doesn't @@ -9,7 +9,6 @@ // that should be there. That way, if you delete something from a lua source // file, it gets removed from the lua global environment. // -// // THE MAKECLASS OPERATOR // // This module provides a new lua 'builtin' operator: "makeclass". This creates @@ -31,12 +30,15 @@ // // THE LUA SOURCE DATABASE // -// The function 'source_update' loads the lua source code from disk, and stores -// it in the "source database." The source database is a table inside the lua -// registry. +// Class SourceDB only contains a single pointer to the lua environment. That's +// because all the data for SourceDB is stored in the lua registry. +// Specifically, the registry contains these keys: // -// The source database is a lua table where the keys are filenames, and the -// values are information about that file: +// 1. The source database proper (registry key "sourcedb") +// 2. The snapshot of builtins (registry key "source_snapshot_builtins") +// +// The source database proper is a table where the keys are filenames, and the +// values are records containing information about that file: // // "foo.lua" : { // "name": "foo.lua", @@ -55,23 +57,24 @@ // error message. Finally, "sequence" indicates the order in which the source // files are meant to be loaded. // -// The operation "source_update" refreshes the source database from disk. It +// The operation SourceDB::update refreshes the source database from disk. It // doesn't reread files whose fingerprints have not changed. In a synchronous -// model, we don't call source_update - instead, we update the source database -// by difference transmission. +// model, we don't call SourceDB::update - instead, we update the source +// database by difference transmission. // // Note that updating the source database has *no effect* on the lua global -// variables (or lua function definitions). The source_update operation calls -// lua's "load" on the code, but all that does is return a loaded closure. +// variables (or lua function definitions). The SourceDB::update operation +// calls lua's "load" on the code, but all that does is return a loaded closure. // Nothing happens to the lua invironment until you *invoke* the loaded closure. -// That doesn't happen until you do a source_rebuild operation, described below. +// That doesn't happen until you do a SourceDB::rebuild operation, described +// below. // // // SOURCE REBUILDS, IN DEPTH // -// The function source_rebuild clears and then rebuilds the entire contents of -// the global environment. The reason to clear the environment is that if we -// didn't clear it, then removing a function from the lua source would not +// The function SourceDB::rebuild clears and then rebuilds the entire contents +// of the lua global environment. The reason to clear the environment is that +// if we didn't clear it, then removing a function from the lua source would not // remove it from the lua environment. Rebuilding the lua environment is a // multi-step process: // @@ -83,7 +86,7 @@ // // * Lua Builtin functions are reinstalled in the global environment. // -// - To make this possible, a snapshot of these builtins is kept. +// - To make this possible, the snapshot of builtins is used. // // * C++ functions registered with "LuaDefine" are reinstalled. // @@ -102,15 +105,15 @@ // UNITTESTS // // We reserve the lua class name 'unittests' for storing unit tests. Any -// function placed into this class is considered a unit test. We don't -// separate unit tests from the rest of the code - they're compiled right -// into the main binary. +// function placed into this class is considered a unit test. We don't separate +// unit tests from the rest of the code - they're compiled right into the main +// binary. // -// Unit tests can be either lua functions, or Lua-registered C functions. -// Unit tests are executed by calling 'source_run_unittests'. +// Unit tests can be either lua functions, or Lua-registered C functions. Unit +// tests are executed by calling 'source_run_unittests'. // -// Each unit test is run in a protected 'pcall' environment. Any errors -// are printed out to console. (At least for now). +// Each unit test is run in a protected 'pcall' environment. Any errors are +// printed out to console. (At least for now). // //////////////////////////////////////////////////////////// @@ -119,6 +122,46 @@ #include "luastack.hpp" +class SourceDB { +private: + lua_State *lua_state_; + +public: + // Initialize + // + // This must be called while the lua state is still pristine. + // This will install the builtin operators into the lua state + // and will snapshot those builtins to the registry. + // + void initialize(lua_State *L); + + // Update + // + // Read all the lua source files from disk and store them in the + // source database. Also compiles these files using lua's "load" + // function. Efficient: if a source file is already in the database + // and hasn't been modified, it is not reloaded. + // + void update(); + + // Rebuild + // + // Rebuild the lua environment: clear it out, then reinstall all the + // functions that should be there. See above for more information. + // If an error exists in any of the source files, or when loading any + // of the closures, the error is (currently) printed. We'll come up + // with better error handling later. + // + void rebuild(); + + // run_unittests + // + // Run all the unit tests. Print any errors to console. If there + // are any errors, exits the program. + // + void run_unittests(); +}; + // The Lua 'makeclass' operator. // // Creates a table in the global environment with the specified name. @@ -128,41 +171,6 @@ // int source_makeclass(lua_State *L); -// source_install_and_snapshot_builtins. -// -// Install the lua builtins into a brand new lua state, and then create the -// snapshot of the builtins (in the registry). This uses lua_openlibs, which -// only works if the lua environment is brand new. Do not try to use -// source_snapshot_builtins unless the lua environment has just been created -// using lua_newstate! -// -int source_install_and_snapshot_builtins(lua_State *L); - -// source_update -// -// Read all the lua source files from disk and store them in the -// source database. Also compiles these files using lua's "load" -// function. Efficient: if a source file is already in the database -// and hasn't been modified, it is not reloaded. -// -int source_update(lua_State *L); - -// source_rebuild -// -// Rebuild the lua environment: clear it out, then reinstall all the -// functions that should be there. See above for more information. -// If an error exists in any of the source files, or when loading any -// of the closures, the error is (currently) printed. We'll come up -// with better error handling later. -// -int source_rebuild(lua_State *L); - -// source_run_unittests -// -// Run all the unit tests. Print any errors to console. Pushes zero -// onto the lua stack if there are no errors, or one if there are. -// -int source_run_unittests(lua_State *L); #endif // SOURCE_HPP diff --git a/luprex/syscpp/util.hpp b/luprex/syscpp/util.hpp index 03fad372..3218c544 100644 --- a/luprex/syscpp/util.hpp +++ b/luprex/syscpp/util.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace util { @@ -48,6 +49,7 @@ struct XYZ { float x, y, z; XYZ() { x=0; y=0; z=0; } XYZ(float ix, float iy, float iz) { x=ix; y=iy; z=iz; } + bool operator ==(const XYZ &o) { return x==o.x && y == o.y && z==o.z; } }; } // namespace util diff --git a/luprex/syscpp/world.cpp b/luprex/syscpp/world.cpp index 62d4f4b7..3e801f27 100644 --- a/luprex/syscpp/world.cpp +++ b/luprex/syscpp/world.cpp @@ -1,17 +1,41 @@ #include "world.hpp" #include "idalloc.hpp" +#include LuaDefineType(World); World::~World() { } -void World::init(lua_State *L) { +World::World() { + // Create the lua state. + lua_state_ = lua_open(); + if (lua_state_ == nullptr) { + std::cerr << "Cannot create lua state." << std::endl; + exit(1); + } + + // Initialize the userdata metatables. + LuaStack::register_all_userdata(lua_state_); + + // Prepare to manipulate the lua state. LuaVar world; - LuaStack LS(L, world); - LS.newpointer(world, new World, false); + LuaStack LS(lua_state_, world); + + // Put the world pointer into the lua registry. + LS.newpointer(world, this, false); LS.setfield(LuaRegistry, "world", world); + + // Initialize the SourceDB + source_db_.initialize(lua_state_); + + // Do an initial lua source update and then environment rebuild. + source_db_.update(); + source_db_.rebuild(); + + // Run unit tests. + source_db_.run_unittests(); } World *World::fetch(lua_State *L) { @@ -23,23 +47,3 @@ World *World::fetch(lua_State *L) { return w; } -LuaDefine(world_init, "c") { - World::init(L); - return 0; -} - -LuaDefine(world_setid, "c") { - LuaArg id; - LuaStack LS(L, id); - World *w = World::fetch(L); - w->id_ = LS.ckinteger(id); - return LS.result(); -} - -LuaDefine(world_getid, "c") { - LuaRet id; - LuaStack LS(L, id); - World *w = World::fetch(L); - LS.set(id, w->id_); - return LS.result(); -}; \ No newline at end of file diff --git a/luprex/syscpp/world.hpp b/luprex/syscpp/world.hpp index b37f44d1..c1ee3a87 100644 --- a/luprex/syscpp/world.hpp +++ b/luprex/syscpp/world.hpp @@ -1,30 +1,78 @@ -// Note about header file dependencies: -// -// world.hpp contains a lot of forward declarations. -// That's because it is at the bottom of the dependency stack: -// everyone includes world.hpp. -// -// However, world.cpp is at the top of the dependency stack, -// it includes everyone else. -// #ifndef WORLD_HPP #define WORLD_HPP #include "luastack.hpp" +#include "planemap.hpp" +#include "idalloc.hpp" +#include "animqueue.hpp" +#include "source.hpp" #include +#include -class IdGlobalPool; +class World; + +class Tangible { +public: + // Always points back to the world model. + World *world_; + + // Animation queue and plane item. + // + // 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_; + + // Player ID pool + // + // Note: this is only allocated if this Tangible is a player. + std::unique_ptr id_player_pool_; +}; class World { public: - int id_; - std::unique_ptr id_pool_; - - World() : id_(0) {}; + // A pointer to the lua State. + // + lua_State *lua_state_; + + // The Global ID Pool. + // + IdGlobalPool id_global_pool_; + + // Source Database. + // + SourceDB source_db_; + PlaneMap plane_map_; + std::unordered_map tangibles_; + +public: + // Constructor. + // + // The constructor also calls 'lua_open' to create a new + // lua interpreter for this world model. The lua interpreter + // is stored in world::lua_state_. A significant amount of + // initial setup is done by this constructor. + // + World(); + + // Destructor. + // + // Not currently functional. + // ~World(); - static void init(lua_State *L); + // get_lua_state + // + // Get the lua interpreter associated with this world model. + // + lua_State *get_lua_state() { return lua_state_; } + + // fetch + // + // Given a lua state, fetch the world model associated with + // that lua state. + // static World *fetch(lua_State *L); };