Rationalizing the use of scan_radius and making it accessible

This commit is contained in:
2021-11-23 16:10:48 -05:00
parent c75ba3b3a8
commit 8c871a9f40
10 changed files with 109 additions and 110 deletions

View File

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

View File

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

View File

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

View File

@@ -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.");

View File

@@ -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() {

View File

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

View File

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

View File

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