Add core.find_nodes_with_meta() script API
authorkwolekr <kwolekr@minetest.net>
Tue, 5 May 2015 18:30:46 +0000 (14:30 -0400)
committerkwolekr <kwolekr@minetest.net>
Tue, 5 May 2015 20:21:59 +0000 (16:21 -0400)
doc/lua_api.txt
src/map.cpp
src/map.h
src/nodemetadata.cpp
src/nodemetadata.h
src/script/lua_api/l_env.cpp
src/script/lua_api/l_env.h

index 6325ed35dd4771393bf09cf030396e4ca3ddccb5..c01ef208c5da7d7466f0e4aa6dd8403f55124583 100644 (file)
@@ -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)`
index 9fead00c6d40436b107f0249b6acb51721046517..7f8059cc480e6f7825f9b25a8d1e9da7a1994418 100644 (file)
@@ -1890,6 +1890,40 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
        }
 }
 
+std::vector<v3s16> Map::findNodesWithMetadata(v3s16 p1, v3s16 p2)
+{
+       std::vector<v3s16> 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<v3s16> 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);
index 325a02e6044af5d1463e063f1b6a493573ecfe78..5500ccf91bece71a3ac21274073c1ad2b8a47e53 100644 (file)
--- 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<v3s16> findNodesWithMetadata(v3s16 p1, v3s16 p2);
+       NodeMetadata *getNodeMetadata(v3s16 p);
 
        /**
         * Sets metadata for a node.
index 1e40a1630ea7c03c5c152546174cb0c42d31897c..bd54d225688d1c99755d3db07c7b38ca5e9a9bf0 100644 (file)
@@ -157,10 +157,21 @@ NodeMetadataList::~NodeMetadataList()
        clear();
 }
 
-NodeMetadata* NodeMetadataList::get(v3s16 p)
+std::vector<v3s16> NodeMetadataList::getAllKeys()
 {
-       std::map<v3s16, NodeMetadata*>::const_iterator n = m_data.find(p);
-       if(n == m_data.end())
+       std::vector<v3s16> keys;
+
+       std::map<v3s16, NodeMetadata *>::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<v3s16, NodeMetadata *>::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<v3s16, NodeMetadata*>::iterator
-                       i = m_data.begin();
-                       i != m_data.end(); i++)
-       {
-               delete i->second;
+       std::map<v3s16, NodeMetadata*>::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<std::string, std::string>::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;
index 6baf3b3d37bf3808bedab05e768c6472ccaaed13..acd45bdf9bde4f3b7c85a6029a84bb536bfe7c01 100644 (file)
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irr_v3d.h"
 #include <string>
 #include <iostream>
+#include <vector>
 #include <map>
 
 /*
@@ -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<v3s16> getAllKeys();
        // Get pointer to data
-       NodeMetadataget(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<v3s16, NodeMetadata*> m_data;
+       std::map<v3s16, NodeMetadata *> m_data;
 };
 
 #endif
index 0fe1ddec38592bf0a6991c9f7a8367145b7be0eb..9581d1ef39f6286cda5a2c12ffe88f6662b9bf2d 100644 (file)
@@ -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<v3s16> 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);
index 5c9afd2f1e2644b767c6c57bf29f33cd6b12340e..0d4ca788ed0cc75b82f4fcea4ab05e8a9019c0d2 100644 (file)
@@ -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);