World model is now operational

This commit is contained in:
2021-01-16 01:24:33 -05:00
parent d7d633bd96
commit 313e78067a
11 changed files with 313 additions and 188 deletions

View File

@@ -1,5 +1,6 @@
#include "animqueue.hpp"
#include "luastack.hpp"
#include <limits>
@@ -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;
}

View File

@@ -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

View File

@@ -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.

View File

@@ -14,7 +14,7 @@
#include <string>
#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;
}

View File

@@ -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,9 +101,9 @@ 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) {
@@ -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<MyTangible>();
LuaAssert(L, tanp == &tan);
return 0;
}

View File

@@ -74,8 +74,10 @@
#define PLANEMAP_HPP
#include <cstdint>
#include <cstddef>
#include <vector>
#include <map>
#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<class T>
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<class T>
T *static_field_cast() {
const std::size_t offset = offsetof(T, plane_item_);
return reinterpret_cast<T*>(reinterpret_cast<char*>(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.

View File

@@ -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();
}

View File

@@ -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

View File

@@ -6,6 +6,7 @@
#include <algorithm>
#include <sstream>
#include <tuple>
#include <utility>
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

View File

@@ -1,17 +1,41 @@
#include "world.hpp"
#include "idalloc.hpp"
#include <iostream>
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();
};

View File

@@ -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 <memory>
#include <unordered_map>
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<IdPlayerPool> id_player_pool_;
};
class World {
public:
int id_;
std::unique_ptr<IdGlobalPool> id_pool_;
// A pointer to the lua State.
//
lua_State *lua_state_;
World() : id_(0) {};
// The Global ID Pool.
//
IdGlobalPool id_global_pool_;
// Source Database.
//
SourceDB source_db_;
PlaneMap plane_map_;
std::unordered_map<int64_t, Tangible> 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);
};