diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6325ed35d..c01ef208c 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1871,6 +1871,8 @@ and `minetest.auth_reload` call the authetification handler. * `minetest.punch_node(pos)` * Punch node with the same effects that a player would cause +* `minetest.find_nodes_with_meta(pos1, pos2)` + * Get a table of positions of nodes that have metadata within a region {pos1, pos2} * `minetest.get_meta(pos)` * Get a `NodeMetaRef` at that position * `minetest.get_node_timer(pos)` diff --git a/src/map.cpp b/src/map.cpp index 9fead00c6..7f8059cc4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1890,6 +1890,40 @@ void Map::transformLiquids(std::map & modified_blocks) } } +std::vector Map::findNodesWithMetadata(v3s16 p1, v3s16 p2) +{ + std::vector positions_with_meta; + + sortBoxVerticies(p1, p2); + v3s16 bpmin = getNodeBlockPos(p1); + v3s16 bpmax = getNodeBlockPos(p2); + + for (s16 z = bpmin.Z; z <= bpmax.Z; z++) + for (s16 y = bpmin.Y; y <= bpmax.Y; y++) + for (s16 x = bpmin.X; x <= bpmax.X; x++) { + v3s16 blockpos(x, y, z); + + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if (!block) { + verbosestream << "Map::getNodeMetadata(): Need to emerge " + << PP(blockpos) << std::endl; + block = emergeBlock(blockpos, false); + } + if (!block) { + infostream << "WARNING: Map::getNodeMetadata(): Block not found" + << std::endl; + continue; + } + + v3s16 p_base = blockpos * MAP_BLOCKSIZE; + std::vector keys = block->m_node_metadata.getAllKeys(); + for (size_t i = 0; i != keys.size(); i++) + positions_with_meta.push_back(keys[i] + p_base); + } + + return positions_with_meta; +} + NodeMetadata *Map::getNodeMetadata(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); diff --git a/src/map.h b/src/map.h index 325a02e60..5500ccf91 100644 --- a/src/map.h +++ b/src/map.h @@ -301,7 +301,8 @@ public: These are basically coordinate wrappers to MapBlock */ - NodeMetadata* getNodeMetadata(v3s16 p); + std::vector findNodesWithMetadata(v3s16 p1, v3s16 p2); + NodeMetadata *getNodeMetadata(v3s16 p); /** * Sets metadata for a node. diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index 1e40a1630..bd54d2256 100644 --- a/src/nodemetadata.cpp +++ b/src/nodemetadata.cpp @@ -157,10 +157,21 @@ NodeMetadataList::~NodeMetadataList() clear(); } -NodeMetadata* NodeMetadataList::get(v3s16 p) +std::vector NodeMetadataList::getAllKeys() { - std::map::const_iterator n = m_data.find(p); - if(n == m_data.end()) + std::vector keys; + + std::map::const_iterator it; + for (it = m_data.begin(); it != m_data.end(); ++it) + keys.push_back(it->first); + + return keys; +} + +NodeMetadata *NodeMetadataList::get(v3s16 p) +{ + std::map::const_iterator n = m_data.find(p); + if (n == m_data.end()) return NULL; return n->second; } @@ -168,8 +179,7 @@ NodeMetadata* NodeMetadataList::get(v3s16 p) void NodeMetadataList::remove(v3s16 p) { NodeMetadata *olddata = get(p); - if(olddata) - { + if (olddata) { delete olddata; m_data.erase(p); } @@ -183,16 +193,15 @@ void NodeMetadataList::set(v3s16 p, NodeMetadata *d) void NodeMetadataList::clear() { - for(std::map::iterator - i = m_data.begin(); - i != m_data.end(); i++) - { - delete i->second; + std::map::iterator it; + for (it = m_data.begin(); it != m_data.end(); ++it) { + delete it->second; } m_data.clear(); } -std::string NodeMetadata::getString(const std::string &name, unsigned short recursion) const +std::string NodeMetadata::getString(const std::string &name, + unsigned short recursion) const { std::map::const_iterator it; it = m_stringvars.find(name); @@ -211,7 +220,8 @@ void NodeMetadata::setString(const std::string &name, const std::string &var) } } -std::string NodeMetadata::resolveString(const std::string &str, unsigned short recursion) const +std::string NodeMetadata::resolveString(const std::string &str, + unsigned short recursion) const { if (recursion > 1) { return str; diff --git a/src/nodemetadata.h b/src/nodemetadata.h index 6baf3b3d3..acd45bdf9 100644 --- a/src/nodemetadata.h +++ b/src/nodemetadata.h @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_v3d.h" #include #include +#include #include /* @@ -42,10 +43,10 @@ class NodeMetadata public: NodeMetadata(IGameDef *gamedef); ~NodeMetadata(); - + void serialize(std::ostream &os) const; void deSerialize(std::istream &is); - + void clear(); // Generic key/value store @@ -81,18 +82,20 @@ public: void serialize(std::ostream &os) const; void deSerialize(std::istream &is, IGameDef *gamedef); - + + // Add all keys in this list to the vector keys + std::vector getAllKeys(); // Get pointer to data - NodeMetadata* get(v3s16 p); + NodeMetadata *get(v3s16 p); // Deletes data void remove(v3s16 p); // Deletes old data and sets a new one void set(v3s16 p, NodeMetadata *d); // Deletes all void clear(); - + private: - std::map m_data; + std::map m_data; }; #endif diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 0fe1ddec3..9581d1ef3 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -334,6 +334,22 @@ int ModApiEnvMod::l_add_node_level(lua_State *L) return 1; } +// find_nodes_with_meta(pos1, pos2) +int ModApiEnvMod::l_find_nodes_with_meta(lua_State *L) +{ + GET_ENV_PTR; + + std::vector positions = env->getMap().findNodesWithMetadata( + check_v3s16(L, 1), check_v3s16(L, 2)); + + lua_newtable(L); + for (size_t i = 0; i != positions.size(); i++) { + push_v3s16(L, positions[i]); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} // get_meta(pos) int ModApiEnvMod::l_get_meta(lua_State *L) @@ -912,6 +928,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(set_node_level); API_FCT(add_node_level); API_FCT(add_entity); + API_FCT(find_nodes_with_meta); API_FCT(get_meta); API_FCT(get_node_timer); API_FCT(get_player_by_name); diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 5c9afd2f1..0d4ca788e 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -64,7 +64,6 @@ private: // pos = {x=num, y=num, z=num} static int l_punch_node(lua_State *L); - // get_node_max_level(pos) // pos = {x=num, y=num, z=num} static int l_get_node_max_level(lua_State *L); @@ -81,6 +80,9 @@ private: // pos = {x=num, y=num, z=num} static int l_add_node_level(lua_State *L); + // find_nodes_with_meta(pos1, pos2) + static int l_find_nodes_with_meta(lua_State *L); + // get_meta(pos) static int l_get_meta(lua_State *L);