From 3e424f3fa6344129c01a27959764bb0c7560b701 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Thu, 25 Mar 2021 15:34:43 -0400 Subject: [PATCH] PlaneMap now tracks all tangibles, including those on nowhere plane. --- luprex/core/cpp/planemap.cpp | 78 ++++++++++++------------------------ luprex/core/cpp/planemap.hpp | 3 +- luprex/core/cpp/textgame.cpp | 2 +- luprex/core/cpp/world.cpp | 7 +++- luprex/core/cpp/world.hpp | 5 ++- 5 files changed, 36 insertions(+), 59 deletions(-) diff --git a/luprex/core/cpp/planemap.cpp b/luprex/core/cpp/planemap.cpp index 3baa673e..dabda1e0 100644 --- a/luprex/core/cpp/planemap.cpp +++ b/luprex/core/cpp/planemap.cpp @@ -10,7 +10,6 @@ // #define CELL_LIMIT 0x7FFFFF #define CELL_SCALE 10.0 -#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) { @@ -34,16 +33,16 @@ struct CellRange { // Get the range of cells that includes everything in the rectangle. // -// Gracefully handles the case that some or all of the rectangle is off -// the map: in that case, returns exactly the valid cells and not the -// invalid ones. +// Gracefully handles the case that some or all of the rectangle is +// beyond the maximum cell range. In that case, it clamps to the edge +// of the cell range. // static CellRange rect_cell_range(double x1, double y1, double x2, double 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); - result.xhi = round_and_clamp(x2 / CELL_SCALE, -CELL_LIMIT - 1, CELL_LIMIT); - result.yhi = round_and_clamp(y2 / CELL_SCALE, -CELL_LIMIT - 1, CELL_LIMIT); + result.xlo = round_and_clamp(x1 / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT); + result.ylo = round_and_clamp(y1 / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT); + result.xhi = round_and_clamp(x2 / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT); + result.yhi = round_and_clamp(y2 / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT); return result; } @@ -53,23 +52,14 @@ static int64_t cell_id(int64_t cellx, int64_t celly) { return 0x0001000000000000 | (icellx << 24) | (icelly << 0); } -// Get the cell ID of the specified point, or CELL_INVALID if the point is off the map. +// Get the cell ID of the specified point static int64_t point_cell_id(double x, double y) { - double cellx = round(x / CELL_SCALE); - double celly = round(y / CELL_SCALE); - if ((cellx < -CELL_LIMIT) || (celly < -CELL_LIMIT) || (cellx > CELL_LIMIT) || (celly > CELL_LIMIT)) { - return CELL_INVALID; - } + double cellx = round_and_clamp(x / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT); + double celly = round_and_clamp(y / CELL_SCALE, -CELL_LIMIT, CELL_LIMIT); return cell_id(int64_t(cellx), int64_t(celly)); } void PlaneMap::remove(const std::string &plane, int64_t cellid, PlaneItem *client) { - if (cellid == CELL_INVALID) { - return; - } - if ((plane == "") || (plane == "nowhere")) { - return; - } auto piter = planes_.find(plane); if (piter == planes_.end()) { return; @@ -90,12 +80,6 @@ void PlaneMap::remove(const std::string &plane, int64_t cellid, PlaneItem *clien } void PlaneMap::insert(const std::string &plane, int64_t cellid, PlaneItem *client) { - if (cellid == CELL_INVALID) { - return; - } - if ((plane == "") || (plane == "nowhere")) { - return; - } Plane &p = planes_[plane]; EltVec &l = p[cellid]; l.push_back(client); @@ -127,11 +111,11 @@ void PlaneItem::untrack() { } } -void PlaneMap::track(PlaneItem *item) { - if (item->pmap_ != this) { - item->untrack(); - insert(item->plane(), point_cell_id(item->x(), item->y()), item); - item->pmap_ = this; +void PlaneItem::track(PlaneMap *pmap) { + if (pmap_ != pmap) { + untrack(); + pmap->insert(plane_, point_cell_id(x_, y_), this); + pmap_ = pmap; } } @@ -224,13 +208,13 @@ LuaDefine(unittests_planemap, "c") { LuaAssert(L, rect_cell_range((HI-7)*SC, (HI-5)*SC, (HI+3)*SC, (HI+6)*SC).equal(HI-7, HI-5, HI, HI)); // Rectangle that exceeds the high end of the range. - LuaAssert(L, rect_cell_range((HI+7)*SC, (HI+5)*SC, (HI+15)*SC, (HI+12)*SC).equal(HI+1, HI+1, HI, HI)); + LuaAssert(L, rect_cell_range((HI+7)*SC, (HI+5)*SC, (HI+15)*SC, (HI+12)*SC).equal(HI, HI, HI, HI)); // Rectangle that crosses the low end of the range. LuaAssert(L, rect_cell_range((LO-7)*SC, (LO-5)*SC, (LO+3)*SC, (LO+4)*SC).equal(LO, LO, LO+3, LO+4)); // Rectangle that exceeds the low end of the range. - LuaAssert(L, rect_cell_range((LO-15)*SC, (LO-17)*SC, (LO-7)*SC, (LO-5)*SC).equal(LO, LO, LO-1, LO-1)); + LuaAssert(L, rect_cell_range((LO-15)*SC, (LO-17)*SC, (LO-7)*SC, (LO-5)*SC).equal(LO, LO, LO, LO)); // Simple test. LuaAssert(L, point_cell_id(-7*SC, 15*SC) == cell_id(-7, 15)); @@ -245,10 +229,10 @@ LuaDefine(unittests_planemap, "c") { LuaAssert(L, point_cell_id(LO*SC, LO*SC) == cell_id(LO, LO)); // Beyond various edges. - LuaAssert(L, point_cell_id((LO-1)*SC, 0) == CELL_INVALID); - LuaAssert(L, point_cell_id((HI+1)*SC, 0) == CELL_INVALID); - LuaAssert(L, point_cell_id(0, (LO-1)*SC) == CELL_INVALID); - LuaAssert(L, point_cell_id(0, (HI+1)*SC) == CELL_INVALID); + LuaAssert(L, point_cell_id((LO-1)*SC, 0) == point_cell_id(LO*SC, 0)); + LuaAssert(L, point_cell_id((HI+1)*SC, 0) == point_cell_id(HI*SC, 0)); + LuaAssert(L, point_cell_id(0, (LO-1)*SC) == point_cell_id(0, LO*SC)); + LuaAssert(L, point_cell_id(0, (HI+1)*SC) == point_cell_id(0, HI*SC)); // Test using the insert function. pm.clear(); @@ -270,20 +254,8 @@ LuaDefine(unittests_planemap, "c") { LuaAssert(L, elts[0] == &pib); pm.remove("foo", 12345, &pib); LuaAssert(L, pm.total_cells() == 0); - - // Test the insert function on the nowhere plane. - pm.clear(); - pm.insert("nowhere", 12345, &pia); - pm.insert("nowhere", 12345, &pib); - LuaAssert(L, pm.total_cells() == 0); - // Test the insert function on an invalid cell. - pm.clear(); - pm.insert("foo", CELL_INVALID, &pia); - pm.insert("foo", CELL_INVALID, &pib); - LuaAssert(L, pm.total_cells() == 0); - - // Try moving a plane item around without it being connected to a grid. + // Try moving a plane item around without it being tracked to a grid. pia.set_pos("foo", 3, 4, 5); LuaAssert(L, pia.plane() == "foo"); LuaAssert(L, pia.x() == 3.0); @@ -292,7 +264,7 @@ LuaDefine(unittests_planemap, "c") { // Attach pia to the grid. This should record it. pm.clear(); - pm.track(&pia); + pia.track(&pm); elts = pm.get_cell("foo", point_cell_id(3.0, 4.0)); LuaAssert(L, elts.size() == 1); LuaAssert(L, elts[0] == &pia); @@ -302,7 +274,7 @@ LuaDefine(unittests_planemap, "c") { LuaAssert(L, pm.total_cells() == 0); // Reattach pia to the grid, then move it. - pm.track(&pia); + pia.track(&pm); LuaAssert(L, pm.total_cells() == 1); pia.set_pos("bar", 1000.0, 1000.0, 0.0); LuaAssert(L, pm.total_cells() == 1); @@ -311,7 +283,7 @@ LuaDefine(unittests_planemap, "c") { LuaAssert(L, elts[0] == &pia); // Insert the four elements, then test the scan function. - pm.track(&pib); + pib.track(&pm); pia.set_id(123); pib.set_id(456); pib.set_pos("bar", 1100.0, 1000.0, 0.0); diff --git a/luprex/core/cpp/planemap.hpp b/luprex/core/cpp/planemap.hpp index a5a25747..f3d98e2f 100644 --- a/luprex/core/cpp/planemap.hpp +++ b/luprex/core/cpp/planemap.hpp @@ -102,6 +102,8 @@ public: const double z() const { return z_; } void untrack(); + void track(PlaneMap *pmap); + 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); } }; @@ -119,7 +121,6 @@ public: using IdVec = std::vector; PlaneMap(); ~PlaneMap(); - void track(PlaneItem *item); IdVec scan_radius(const std::string &plane, double x, double y, double radius, int64_t prepend) const; private: diff --git a/luprex/core/cpp/textgame.cpp b/luprex/core/cpp/textgame.cpp index 3ef81638..f9741cb0 100644 --- a/luprex/core/cpp/textgame.cpp +++ b/luprex/core/cpp/textgame.cpp @@ -81,7 +81,7 @@ void TextGame::do_view_command(const StringVec &cmd) { std::cerr << "v command (view) takes no arguments" << std::endl; return; } - for (int64_t id : world_->get_near(1, 100)) { + for (int64_t id : world_->get_near(1, 100, true)) { const Tangible *tan = world_->tangible_get(id); const AnimQueue &aq = tan->anim_queue_; std::cerr << id << ": " << aq.get_graphic() << " " << aq.get_plane() << " " << aq.get_xyz() << std::endl; diff --git a/luprex/core/cpp/world.cpp b/luprex/core/cpp/world.cpp index fae66db9..209f1f4b 100644 --- a/luprex/core/cpp/world.cpp +++ b/luprex/core/cpp/world.cpp @@ -53,7 +53,7 @@ World::World() { Tangible::Tangible(World *w, int64_t id) : world_(w), id_player_pool_(&w->id_global_pool_) { plane_item_.set_id(id); - w->plane_map_.track(&plane_item_); + plane_item_.track(&w->plane_map_); } void Tangible::update_plane_item() { @@ -160,11 +160,14 @@ void World::tangible_delete(lua_State *L, int64_t id) { LS.result(); } -std::vector World::get_near(int64_t player_id, float radius) { +std::vector World::get_near(int64_t player_id, float radius, bool exclude_nowhere) { Tangible *player = tangible_get(player_id); // Find out where's the center of the world. std::string plane = player->anim_queue_.get_plane(); + if (exclude_nowhere && (plane == "nowhere")) { + return std::vector(); + } util::XYZ xyz = player->anim_queue_.get_xyz(); return plane_map_.scan_radius(plane, xyz.x, xyz.y, radius, player_id); diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index e0ac182a..1a37d383 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -129,9 +129,10 @@ public: // get_near // - // Get a list of the tangibles that are near the player. + // Get a list of the tangibles that are near the player. If 'exclude_nowhere' is + // true, exclude any tangibles on the nowhere plane. // - std::vector get_near(int64_t player_id, float radius); + std::vector get_near(int64_t player_id, float radius, bool exclude_nowhere); // Make a tangible. //