diff --git a/luprex/core/cpp/planemap.cpp b/luprex/core/cpp/planemap.cpp index 29474442..94faf2c9 100644 --- a/luprex/core/cpp/planemap.cpp +++ b/luprex/core/cpp/planemap.cpp @@ -160,10 +160,13 @@ int PlaneMap::total_cells() const { return total; } -PlaneMap::IdVector PlaneMap::scan_radius(const std::string &plane, float x, float y, float radius, int64_t prepend) const { +PlaneMap::IdVector PlaneMap::scan_radius_unsorted(const std::string &plane, float x, float y, float radius, bool exclude_nowhere, int64_t special, bool omit) const { PlaneMap::IdVector result; - if (prepend != 0) { - result.push_back(prepend); + if ((special != 0)&&(!omit)) { + result.push_back(special); + } + if (exclude_nowhere && (plane == "nowhere")) { + return result; } auto piter = planes_.find(plane); if (piter != planes_.end()) { @@ -176,7 +179,7 @@ PlaneMap::IdVector PlaneMap::scan_radius(const std::string &plane, float x, floa if (liter != p.end()) { for (PlaneItem *client : liter->second) { if (util::distance_squared(client->x(), client->y(), x, y) <= radsq) { - if (client->id() != prepend) { + if (client->id() != special) { result.push_back(client->id()); } } @@ -188,6 +191,16 @@ PlaneMap::IdVector PlaneMap::scan_radius(const std::string &plane, float x, floa return result; } +PlaneMap::IdVector PlaneMap::scan_radius(const std::string &plane, float x, float y, float radius, bool exclude_nowhere, int64_t special, bool omit) const { + PlaneMap::IdVector result = scan_radius_unsorted(plane, x, y, radius, exclude_nowhere, special, omit); + if ((special != 0)&&(!omit)) { + std::sort(result.begin() + 1, result.end()); + } else { + std::sort(result.begin(), result.end()); + } + return result; +} + LuaDefine(unittests_planemap, "c") { float SC = CELL_SCALE; float E = CELL_SCALE * 0.4; @@ -287,13 +300,13 @@ LuaDefine(unittests_planemap, "c") { pia.set_id(123); pib.set_id(456); pib.set_pos("bar", 1100.0, 1000.0, 0.0); - ids = pm.scan_radius("bar", 1000.0, 1000.0, 1.0, 0); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 1.0, false, 0, false); LuaAssert(L, ids.size() == 1); LuaAssert(L, ids[0] == 123); - ids = pm.scan_radius("bar", 1000.0, 1000.0, 99.9, 0); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 99.9, false, 0, false); LuaAssert(L, ids.size() == 1); LuaAssert(L, ids[0] == 123); - ids = pm.scan_radius("bar", 1000.0, 1000.0, 100.0, 0); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 100.0, false, 0, false); LuaAssert(L, ids.size() == 2); LuaAssert(L, ids[0] == 123); LuaAssert(L, ids[1] == 456); diff --git a/luprex/core/cpp/planemap.hpp b/luprex/core/cpp/planemap.hpp index e361cbef..0ecd4b6f 100644 --- a/luprex/core/cpp/planemap.hpp +++ b/luprex/core/cpp/planemap.hpp @@ -123,8 +123,15 @@ public: PlaneMap(); ~PlaneMap(); - // Caution: scan_radius is not deterministically ordered. - IdVector scan_radius(const std::string &plane, float x, float y, float radius, int64_t prepend) const; + // Caution: scan_radius is not deterministically ordered unless sort=true. + // + // exclude_nowhere - if true, and plane="nowhere", nothing is scanned. + // special - an ID that is considered special. If zero, there is no special ID. + // omit - if true, remove the special ID from the list. + // if false, prepend the special ID to the head of the list. + // + IdVector scan_radius(const std::string &plane, float x, float y, float radius, bool exclude_nowhere, int64_t special, bool omit) const; + IdVector scan_radius_unsorted(const std::string &plane, float x, float y, float radius, bool exclude_nowhere, int64_t special, bool omit) const; private: // unit testing stuff. diff --git a/luprex/core/cpp/table.hpp b/luprex/core/cpp/table.hpp index 99d3e883..a572b43e 100644 --- a/luprex/core/cpp/table.hpp +++ b/luprex/core/cpp/table.hpp @@ -25,83 +25,4 @@ bool table_equal(LuaStack &LS0, LuaSlot tab1, LuaSlot tab2); // bool table_getpairs(LuaStack &LS0, LuaSlot tab, LuaSlot pairs, bool sort); -// table_findremove -// -// Given a vector and a value, remove the specified value from -// the vector, and shift elements downward to fill the gaps. -// -int lfn_table_findremove(lua_State *L); - -// table_push -// -// Given a vector and a value, push the value onto the end. -// -int lfn_table_push(lua_State *L); - -// table_find -// -// Given a vector and a value, search for the first occurrence -// of that value. Return the index. -// -int lfn_table_find(lua_State *L); - -// table_empty -// -// Return true if the table has no key/value pairs. -// -int lfn_table_empty(lua_State *L); - -// table_count -// -// Return the number of key/value pairs in the table. -// -int lfn_table_count(lua_State *L); - -// -// Create and return an empty deque. Queues are implemented -// as tables which are used as dynamically-expandable circular -// buffers. -// -int lfn_deque_create(lua_State *L); - -// -// Given a deque and a value, pushes the value onto the -// left or right end. -// -int lfn_deque_pushl(lua_State *L); -int lfn_deque_pushr(lua_State *L); - -// -// Given a deque, pop from the left or right end. Returns the -// value and removes it from the deque. If the deque is -// empty, returns nil. -// -int lfn_deque_popl(lua_State *L); -int lfn_deque_popr(lua_State *L); - -// -// Return the nth element from the left or right end of a deque. -// -int lfn_deque_nthl(lua_State *L); -int lfn_deque_nthr(lua_State *L); - -// Set (overwrite) the nth element in a deque. -// -int lfn_deque_setl(lua_State *L); -int lfn_deque_setr(lua_State *L); - -// -// Search a deque for a value. -// -// Search starts on the specified end and indices are relative -// to specified end. -// -int lfn_deque_findl(lua_State *L); -int lfn_deque_findr(lua_State *L); - -// -// Return the number of values in the deque. -// -int lfn_deque_size(lua_State *L); - #endif // TABLE_HPP diff --git a/luprex/core/cpp/world-accessor.cpp b/luprex/core/cpp/world-accessor.cpp index a64ad4cf..54b87795 100644 --- a/luprex/core/cpp/world-accessor.cpp +++ b/luprex/core/cpp/world-accessor.cpp @@ -51,6 +51,24 @@ LuaDefine(tangible_setclass, "c") { return LS.result(); } +LuaDefine(tangible_getclass, "c") { + LuaArg tanobj; + LuaVar mt, classtab; + LuaRet classname; + LuaStack LS(L, tanobj, mt, classtab, classname); + World *w = World::fetch_global_pointer(L); + w->tangible_get(LS, tanobj); + LS.getmetatable(mt, tanobj); + LS.rawget(classtab, mt, "__index"); + std::string name = LS.classname(classtab); + if (name == "") { + LS.set(classname, LuaNil); + } else { + LS.set(classname, name); + } + return LS.result(); +} + LuaDefine(tangible_delete, "c") { LuaArg tanobj; LuaStack LS(L, tanobj); @@ -179,6 +197,40 @@ LuaDefine(tangible_place, "c") { return LS.result(); } +LuaDefine(tangible_near, "c") { + LuaArg ltan, lradius, lomit_nowhere, lomit_self; + LuaRet list; + LuaStack LS(L, ltan, lradius, lomit_nowhere, lomit_self, list); + World *w = World::fetch_global_pointer(L); + Tangible *tan = w->tangible_get(LS, ltan); + double radius = LS.cknumber(lradius); + bool omit_nowhere = LS.ckboolean(lomit_nowhere); + bool omit_self = LS.ckboolean(lomit_self); + const AnimStep &aqback = tan->anim_queue_.back(); + util::IdVector idv = w->plane_map_.scan_radius(aqback.plane(), aqback.xyz().x, aqback.xyz().y, radius, omit_nowhere, tan->id(), omit_self); + LS.set(list, LuaNewTable); + int index = 1; + for (int64_t id : idv) LS.rawset(list, index++, id); + return LS.result(); +} + +LuaDefine(tangible_scan, "c") { + LuaArg lplane, lx, ly, lradius, lomit_nowhere; + LuaRet list; + LuaStack LS(L, lplane, lx, ly, lradius, lomit_nowhere, list); + World *w = World::fetch_global_pointer(L); + std::string plane = LS.ckstring(lplane); + double x = LS.cknumber(lx); + double y = LS.cknumber(ly); + double radius = LS.cknumber(lradius); + bool omit_nowhere = LS.ckboolean(lomit_nowhere); + util::IdVector idv = w->plane_map_.scan_radius(plane, x, y, radius, omit_nowhere, 0, false); + LS.set(list, LuaNewTable); + int index = 1; + for (int64_t id : idv) LS.rawset(list, index++, id); + return LS.result(); +} + LuaDefine(world_wait, "f") { if ((lua_gettop(L) != 1) || (lua_type(L, -1) != LUA_TNUMBER)) { luaL_error(L, "Argument to wait must be a number."); diff --git a/luprex/core/cpp/world-core.cpp b/luprex/core/cpp/world-core.cpp index b525350f..d5e7a5c5 100644 --- a/luprex/core/cpp/world-core.cpp +++ b/luprex/core/cpp/world-core.cpp @@ -228,7 +228,7 @@ void World::tangible_delete(int64_t id) { LS.result(); } -util::IdVector World::get_near_unsorted(int64_t player_id, float radius, bool exclude_nowhere) const { +util::IdVector World::get_near_unsorted(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player) const { const Tangible *player = tangible_get(player_id); if (player == nullptr) { return IdVector(); @@ -236,19 +236,18 @@ util::IdVector World::get_near_unsorted(int64_t player_id, float radius, bool ex // Find out where's the center of the world. const AnimStep &aqback = player->anim_queue_.back(); - if (exclude_nowhere && (aqback.plane() == "nowhere")) { - IdVector idv; - idv.push_back(player_id); - return idv; - } - - return plane_map_.scan_radius(aqback.plane(), aqback.xyz().x, aqback.xyz().y, radius, player_id); + return plane_map_.scan_radius_unsorted(aqback.plane(), aqback.xyz().x, aqback.xyz().y, radius, exclude_nowhere, player_id, omit_player); } -util::IdVector World::get_near(int64_t player_id, float radius, bool exclude_nowhere) const { - util::IdVector v = get_near_unsorted(player_id, radius, exclude_nowhere); - std::sort(v.begin(), v.end()); - return v; +util::IdVector World::get_near(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player) const { + const Tangible *player = tangible_get(player_id); + if (player == nullptr) { + return IdVector(); + } + + // Find out where's the center of the world. + const AnimStep &aqback = player->anim_queue_.back(); + return plane_map_.scan_radius(aqback.plane(), aqback.xyz().x, aqback.xyz().y, radius, exclude_nowhere, player_id, omit_player); } World::Redirects World::fetch_redirects() { diff --git a/luprex/core/cpp/world-diffxmit.cpp b/luprex/core/cpp/world-diffxmit.cpp index d36c29a9..fbfc3054 100644 --- a/luprex/core/cpp/world-diffxmit.cpp +++ b/luprex/core/cpp/world-diffxmit.cpp @@ -3,8 +3,8 @@ util::IdVector World::get_visible_union(int64_t actor_id, World *master) { return util::sort_union_id_vectors( - master->get_near_unsorted(actor_id, RadiusVisibility, true), - get_near_unsorted(actor_id, RadiusVisibility, true)); + master->get_near_unsorted(actor_id, RadiusVisibility, true, false), + get_near_unsorted(actor_id, RadiusVisibility, true, false)); } int64_t World::patch_actor(StreamBuffer *sb, DebugCollector *dbc) { @@ -168,7 +168,7 @@ void World::patch_luatabs(StreamBuffer *sb, DebugCollector *dbc) { int64_t actor_id = sb->read_int64(); util::HashValue closehash = sb->read_hashvalue(); int ncreate = sb->read_int32(); - util::IdVector closetans = get_near(actor_id, RadiusClose, true); + util::IdVector closetans = get_near(actor_id, RadiusClose, true, false); assert(closehash == util::hash_id_vector(closetans)); int nt = number_lua_tables(closetans); create_new_tables(ncreate); @@ -182,8 +182,8 @@ void World::diff_luatabs(int64_t actor_id, World *master, StreamBuffer *xsb) { StreamBuffer tsb; // Calculate the set of close tangibles. - util::IdVector closetans = master->get_near(actor_id, RadiusClose, true); - assert(get_near(actor_id, RadiusClose, true) == closetans); + util::IdVector closetans = master->get_near(actor_id, RadiusClose, true, false); + assert(get_near(actor_id, RadiusClose, true, false) == closetans); util::HashValue closehash = util::hash_id_vector(closetans); // Number and pair tables in the synchronous and master model. @@ -249,7 +249,7 @@ void World::diff_tanclass(int64_t actor_id, World *master, StreamBuffer *xsb) { // Calculate the set of close tangibles. // TODO: we've already calculated this in an earlier function. This is wasteful. - util::IdVector closetans = master->get_near(actor_id, RadiusClose, true); + util::IdVector closetans = master->get_near(actor_id, RadiusClose, true, false); tsb.write_int32(0); int write_count_after = tsb.total_writes(); diff --git a/luprex/core/cpp/world-testing.cpp b/luprex/core/cpp/world-testing.cpp index ee96b0dd..ac4440a3 100644 --- a/luprex/core/cpp/world-testing.cpp +++ b/luprex/core/cpp/world-testing.cpp @@ -32,7 +32,7 @@ std::string World::tangible_ids_debug_string() const { std::string World::tangibles_near_debug_string(int64_t actor, int64_t distance) { std::ostringstream result; - for (int64_t id : get_near(actor, distance, true)) { + for (int64_t id : get_near(actor, distance, true, false)) { const Tangible *tan = tangible_get(id); const AnimStep &aqback = tan->anim_queue_.back(); result << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz().debug_string() << std::endl; diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index 2851bdf1..41d56f65 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -119,8 +119,8 @@ public: // true, exclude any tangibles on the nowhere plane (but still include the player himself). // The unsorted version returns the tangibles in an unpredictable order. // - IdVector get_near(int64_t player_id, float radius, bool exclude_nowhere) const; - IdVector get_near_unsorted(int64_t player_id, float radius, bool exclude_nowhere) const; + IdVector get_near(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player) const; + IdVector get_near_unsorted(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player) const; // Make a tangible. // @@ -476,6 +476,8 @@ private: friend int lfn_tangible_actor(lua_State *L); friend int lfn_tangible_place(lua_State *L); friend int lfn_tangible_nopredict(lua_State *L); + friend int lfn_tangible_near(lua_State *L); + friend int lfn_tangible_scan(lua_State *L); }; using UniqueWorld = std::unique_ptr; diff --git a/luprex/core/lua/login.lua b/luprex/core/lua/login.lua index 7ce7c811..5c8df9c7 100644 --- a/luprex/core/lua/login.lua +++ b/luprex/core/lua/login.lua @@ -12,3 +12,8 @@ function setfoo(n) tangible.nopredict() tangible.actor().inventory.foo = n end + +function buildq() + return tangible.build{class="login", x=10, y=0, z=0, plane="nowhere", graphic="what"} +end + diff --git a/luprex/core/lua/player.lua b/luprex/core/lua/player.lua index e68a8ae1..7b1def2a 100644 --- a/luprex/core/lua/player.lua +++ b/luprex/core/lua/player.lua @@ -12,7 +12,7 @@ function player.interface(actor, place) end function player:printanimstate() - graphic,plane,x,y,z,facing = tangible.animstate(self) + local graphic,plane,x,y,z,facing = tangible.animstate(self) print("Resulting state: ", graphic, plane, x, y, z, facing) end