Fix unit test if there isn't a localhost address (for example FreeBSD jails), second...
[oweals/minetest.git] / src / nodedef.cpp
index e7bf9091f12898b43b9dbfd90e4e82e7a76271d3..bcf51a072e1429e9f75d8c93b6e1e1786564fa6b 100644 (file)
@@ -227,7 +227,6 @@ void ContentFeatures::reset()
        liquid_alternative_source = "";
        liquid_viscosity = 0;
        liquid_renewable = true;
-       freezemelt = "";
        liquid_range = LIQUID_LEVEL_MAX+1;
        drowning = 0;
        light_source = 0;
@@ -402,7 +401,18 @@ public:
        virtual void updateTextures(IGameDef *gamedef);
        void serialize(std::ostream &os, u16 protocol_version);
        void deSerialize(std::istream &is);
-       virtual NodeResolver *getResolver();
+
+       inline virtual bool getNodeRegistrationStatus() const;
+       inline virtual void setNodeRegistrationStatus(bool completed);
+
+       virtual void pendNodeResolve(NodeResolveInfo *nri);
+       virtual void cancelNodeResolve(NodeResolver *resolver);
+       virtual void runNodeResolverCallbacks();
+
+       virtual bool getIdFromResolveInfo(NodeResolveInfo *nri,
+               const std::string &node_alt, content_t c_fallback, content_t &result);
+       virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri,
+               std::vector<content_t> &result);
 
 private:
        void addNameIdMapping(content_t i, std::string name);
@@ -432,13 +442,15 @@ private:
        // Next possibly free id
        content_t m_next_id;
 
-       // NodeResolver to queue pending node resolutions
-       NodeResolver m_resolver;
+       // List of node strings and node resolver callbacks to perform
+       std::list<NodeResolveInfo *> m_pending_node_lookups;
+
+       // True when all nodes have been registered
+       bool m_node_registration_complete;
 };
 
 
-CNodeDefManager::CNodeDefManager() :
-       m_resolver(this)
+CNodeDefManager::CNodeDefManager()
 {
        clear();
 }
@@ -466,6 +478,14 @@ void CNodeDefManager::clear()
        m_group_to_items.clear();
        m_next_id = 0;
 
+       m_node_registration_complete = false;
+       for (std::list<NodeResolveInfo *>::iterator
+                       it = m_pending_node_lookups.begin();
+                       it != m_pending_node_lookups.end();
+                       ++it)
+               delete *it;
+       m_pending_node_lookups.clear();
+
        u32 initial_length = 0;
        initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1);
        initial_length = MYMAX(initial_length, CONTENT_AIR + 1);
@@ -1035,12 +1055,6 @@ void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
 }
 
 
-NodeResolver *CNodeDefManager::getResolver()
-{
-       return &m_resolver;
-}
-
-
 IWritableNodeDefManager *createNodeDefManager()
 {
        return new CNodeDefManager();
@@ -1267,166 +1281,129 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
        }
 }
 
-/*
-       NodeResolver
-*/
-
-NodeResolver::NodeResolver(INodeDefManager *ndef)
-{
-       m_ndef = ndef;
-       m_is_node_registration_complete = false;
-}
-
 
-NodeResolver::~NodeResolver()
+inline bool CNodeDefManager::getNodeRegistrationStatus() const
 {
-       while (!m_pending_contents.empty()) {
-               NodeResolveInfo *nri = m_pending_contents.front();
-               m_pending_contents.pop_front();
-               delete nri;
-       }
+       return m_node_registration_complete;
 }
 
 
-int NodeResolver::addNode(const std::string &n_wanted, const std::string &n_alt,
-       content_t c_fallback, content_t *content)
+inline void CNodeDefManager::setNodeRegistrationStatus(bool completed)
 {
-       if (m_is_node_registration_complete) {
-               if (m_ndef->getId(n_wanted, *content))
-                       return NR_STATUS_SUCCESS;
-
-               if (n_alt == "" || !m_ndef->getId(n_alt, *content)) {
-                       *content = c_fallback;
-                       return NR_STATUS_FAILURE;
-               }
-
-               return NR_STATUS_SUCCESS;
-       } else {
-               NodeResolveInfo *nfi = new NodeResolveInfo;
-               nfi->n_wanted   = n_wanted;
-               nfi->n_alt      = n_alt;
-               nfi->c_fallback = c_fallback;
-               nfi->output     = content;
-
-               m_pending_contents.push_back(nfi);
-
-               return NR_STATUS_PENDING;
-       }
+       m_node_registration_complete = completed;
 }
 
 
-int NodeResolver::addNodeList(const std::string &nodename,
-       std::vector<content_t> *content_vec)
+void CNodeDefManager::pendNodeResolve(NodeResolveInfo *nri)
 {
-       if (m_is_node_registration_complete) {
-               std::set<content_t> idset;
-               std::set<content_t>::iterator it;
-
-               m_ndef->getIds(nodename, idset);
-               for (it = idset.begin(); it != idset.end(); ++it)
-                       content_vec->push_back(*it);
-
-               return idset.size() ? NR_STATUS_SUCCESS : NR_STATUS_FAILURE;
+       nri->resolver->m_ndef = this;
+       if (m_node_registration_complete) {
+               nri->resolver->resolveNodeNames(nri);
+               nri->resolver->m_lookup_done = true;
+               delete nri;
        } else {
-               m_pending_content_vecs.push_back(
-                       std::make_pair(nodename, content_vec));
-               return NR_STATUS_PENDING;
+               m_pending_node_lookups.push_back(nri);
        }
 }
 
 
-bool NodeResolver::cancelNode(content_t *content)
+void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver)
 {
-       bool found = false;
-
        for (std::list<NodeResolveInfo *>::iterator
-                       it = m_pending_contents.begin();
-                       it != m_pending_contents.end();
+                       it = m_pending_node_lookups.begin();
+                       it != m_pending_node_lookups.end();
                        ++it) {
-               NodeResolveInfo *nfi = *it;
-               if (nfi->output == content) {
-                       it = m_pending_contents.erase(it);
-                       delete nfi;
-                       found = true;
+               NodeResolveInfo *nri = *it;
+               if (resolver == nri->resolver) {
+                       it = m_pending_node_lookups.erase(it);
+                       delete nri;
                }
        }
-
-       return found;
 }
 
 
-int NodeResolver::cancelNodeList(std::vector<content_t> *content_vec)
+void CNodeDefManager::runNodeResolverCallbacks()
 {
-       int num_canceled = 0;
-
-       for (ContentVectorResolveList::iterator
-                       it = m_pending_content_vecs.begin();
-                       it != m_pending_content_vecs.end();
-                       ++it) {
-               if (it->second == content_vec) {
-                       it = m_pending_content_vecs.erase(it);
-                       num_canceled++;
-               }
+       while (!m_pending_node_lookups.empty()) {
+               NodeResolveInfo *nri = m_pending_node_lookups.front();
+               m_pending_node_lookups.pop_front();
+               nri->resolver->resolveNodeNames(nri);
+               nri->resolver->m_lookup_done = true;
+               delete nri;
        }
-
-       return num_canceled;
 }
 
 
-int NodeResolver::resolveNodes()
+bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri,
+       const std::string &node_alt, content_t c_fallback, content_t &result)
 {
-       int num_failed = 0;
-
-       //// Resolve pending single node name -> content ID mappings
-       while (!m_pending_contents.empty()) {
-               NodeResolveInfo *nri = m_pending_contents.front();
-               m_pending_contents.pop_front();
+       if (nri->nodenames.empty()) {
+               result = c_fallback;
+               errorstream << "Resolver empty nodename list" << std::endl;
+               return false;
+       }
 
-               bool success = true;
-               if (!m_ndef->getId(nri->n_wanted, *nri->output)) {
-                       success = (nri->n_alt != "") ?
-                               m_ndef->getId(nri->n_alt, *nri->output) : false;
-               }
+       content_t c;
+       std::string name = nri->nodenames.front();
+       nri->nodenames.pop_front();
 
-               if (!success) {
-                       *nri->output = nri->c_fallback;
-                       num_failed++;
-                       errorstream << "NodeResolver::resolveNodes():  Failed to "
-                               "resolve '" << nri->n_wanted;
-                       if (nri->n_alt != "")
-                               errorstream << "' and '" << nri->n_alt;
-                       errorstream << "'" << std::endl;
-               }
+       bool success = getId(name, c);
+       if (!success && node_alt != "") {
+               name = node_alt;
+               success = getId(name, c);
+       }
 
-               delete nri;
+       if (!success) {
+               errorstream << "Resolver: Failed to resolve node name '" << name
+                       << "'." << std::endl;
+               c = c_fallback;
        }
 
-       //// Resolve pending node names and add to content_t vector
-       while (!m_pending_content_vecs.empty()) {
-               std::pair<std::string, std::vector<content_t> *> item =
-                       m_pending_content_vecs.front();
-               m_pending_content_vecs.pop_front();
+       result = c;
+       return success;
+}
 
-               std::string &name = item.first;
-               std::vector<content_t> *output = item.second;
 
-               std::set<content_t> idset;
-               std::set<content_t>::iterator it;
+bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri,
+       std::vector<content_t> &result)
+{
+       bool success = true;
 
-               m_ndef->getIds(name, idset);
-               for (it = idset.begin(); it != idset.end(); ++it)
-                       output->push_back(*it);
+       if (nri->nodelistinfo.empty()) {
+               errorstream << "Resolver: Empty nodelistinfo list" << std::endl;
+               return false;
+       }
 
-               if (idset.empty()) {
-                       num_failed++;
-                       errorstream << "NodeResolver::resolveNodes():  Failed to "
-                               "resolve '" << name << "'" << std::endl;
+       NodeListInfo listinfo = nri->nodelistinfo.front();
+       nri->nodelistinfo.pop_front();
+
+       while (listinfo.length--) {
+               if (nri->nodenames.empty()) {
+                       errorstream << "Resolver: Empty nodename list" << std::endl;
+                       return false;
                }
-       }
 
-       //// Mark node registration as complete so future resolve
-       //// requests are satisfied immediately
-       m_is_node_registration_complete = true;
+               content_t c;
+               std::string name = nri->nodenames.front();
+               nri->nodenames.pop_front();
+
+               if (name.substr(0,6) != "group:") {
+                       if (getId(name, c)) {
+                               result.push_back(c);
+                       } else if (listinfo.all_required) {
+                               errorstream << "Resolver: Failed to resolve node name '" << name
+                                       << "'." << std::endl;
+                               result.push_back(listinfo.c_fallback);
+                               success = false;
+                       }
+               } else {
+                       std::set<content_t> cids;
+                       std::set<content_t>::iterator it;
+                       getIds(name, cids);
+                       for (it = cids.begin(); it != cids.end(); ++it)
+                               result.push_back(*it);
+               }
+       }
 
-       return num_failed;
+       return success;
 }