Redefine NodeResolver interface and replace with callback mechanism
authorkwolekr <kwolekr@minetest.net>
Wed, 17 Dec 2014 08:20:17 +0000 (03:20 -0500)
committerkwolekr <kwolekr@minetest.net>
Sat, 27 Dec 2014 07:12:21 +0000 (02:12 -0500)
16 files changed:
src/mapgen.cpp
src/mapgen.h
src/mg_biome.cpp
src/mg_biome.h
src/mg_decoration.cpp
src/mg_decoration.h
src/mg_ore.cpp
src/mg_ore.h
src/mg_schematic.cpp
src/mg_schematic.h
src/nodedef.cpp
src/nodedef.h
src/script/common/c_converter.cpp
src/script/lua_api/l_mapgen.cpp
src/script/lua_api/l_mapgen.h
src/server.cpp

index ceaabbb1ab9da4638b9cb1ffae37a6677c8bef53..24f9fc556be8f7a845bf39946d40e027d5634d2a 100644 (file)
@@ -384,7 +384,7 @@ void GenerateNotifier::getEvents(
 
 GenElementManager::GenElementManager(IGameDef *gamedef)
 {
-       m_resolver = gamedef->getNodeDefManager()->getResolver();
+       m_ndef = gamedef->getNodeDefManager();
 }
 
 
index 03850cd199a59978a08440cb681d21881565e7f1..07202f9a227cca2f7d2dd42d66e484383fe6656c 100644 (file)
@@ -192,7 +192,7 @@ public:
        virtual GenElement *getByName(const std::string &name);
 
 protected:
-       NodeResolver *m_resolver;
+       INodeDefManager *m_ndef;
        std::vector<GenElement *> m_elements;
 };
 
index a3a6d5128ec2ee571b8eb7aba96d4999d6f3ff8c..763bef1bc5df94cbb6e424896eb1c748011ec94f 100644 (file)
@@ -48,12 +48,14 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
        b->heat_point     = 0.0;
        b->humidity_point = 0.0;
 
-       m_resolver->addNode("air",                 "", CONTENT_AIR, &b->c_top);
-       m_resolver->addNode("air",                 "", CONTENT_AIR, &b->c_filler);
-       m_resolver->addNode("mapgen_stone",        "", CONTENT_AIR, &b->c_stone);
-       m_resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_water);
-       m_resolver->addNode("air",                 "", CONTENT_AIR, &b->c_dust);
-       m_resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water);
+       NodeResolveInfo *nri = new NodeResolveInfo(b);
+       nri->nodenames.push_back("air");
+       nri->nodenames.push_back("air");
+       nri->nodenames.push_back("mapgen_stone");
+       nri->nodenames.push_back("mapgen_water_source");
+       nri->nodenames.push_back("air");
+       nri->nodenames.push_back("mapgen_water_source");
+       m_ndef->pendNodeResolve(nri);
 
        add(b);
 }
@@ -102,18 +104,26 @@ Biome *BiomeManager::getBiome(float heat, float humidity, s16 y)
 
 void BiomeManager::clear()
 {
+
        for (size_t i = 1; i < m_elements.size(); i++) {
                Biome *b = (Biome *)m_elements[i];
-               if (!b)
-                       continue;
-
-               m_resolver->cancelNode(&b->c_top);
-               m_resolver->cancelNode(&b->c_filler);
-               m_resolver->cancelNode(&b->c_stone);
-               m_resolver->cancelNode(&b->c_water);
-               m_resolver->cancelNode(&b->c_dust);
-               m_resolver->cancelNode(&b->c_dust_water);
+               delete b;
        }
+
        m_elements.resize(1);
 }
 
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+void Biome::resolveNodeNames(NodeResolveInfo *nri)
+{
+       m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt_with_grass", CONTENT_AIR,    c_top);
+       m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt",            CONTENT_AIR,    c_filler);
+       m_ndef->getIdFromResolveInfo(nri, "mapgen_stone",           CONTENT_AIR,    c_stone);
+       m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source",    CONTENT_AIR,    c_water);
+       m_ndef->getIdFromResolveInfo(nri, "air",                    CONTENT_IGNORE, c_dust);
+       m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source",    CONTENT_IGNORE, c_dust_water);
+}
+
index f1539dacb9e0b44c93353437701aba39d9f6afd1..870c1196113acc64eafd8149e338e891d89cadf9 100644 (file)
@@ -33,7 +33,7 @@ enum BiomeType
        BIOME_TYPE_FLAT
 };
 
-class Biome : public GenElement {
+class Biome : public GenElement, public NodeResolver {
 public:
        u32 flags;
 
@@ -51,6 +51,8 @@ public:
        s16 height_max;
        float heat_point;
        float humidity_point;
+
+       virtual void resolveNodeNames(NodeResolveInfo *nri);
 };
 
 class BiomeManager : public GenElementManager {
index 761b231edf10c94374809626ba4c2d9731b28391..50e8fb05a65f31eec9a71f203445e84d55d33040 100644 (file)
@@ -65,10 +65,7 @@ void DecorationManager::clear()
 {
        for (size_t i = 0; i < m_elements.size(); i++) {
                Decoration *deco = (Decoration *)m_elements[i];
-               if (!deco)
-                       continue;
-
-               deco->dropResolverEntries(m_resolver);
+               delete deco;
        }
        m_elements.clear();
 }
@@ -91,6 +88,12 @@ Decoration::~Decoration()
 }
 
 
+void Decoration::resolveNodeNames(NodeResolveInfo *nri)
+{
+       m_ndef->getIdsFromResolveInfo(nri, c_place_on);
+}
+
+
 size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
 {
        PseudoRandom ps(blockseed + 53);
@@ -229,6 +232,14 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
 ///////////////////////////////////////////////////////////////////////////////
 
 
+void DecoSimple::resolveNodeNames(NodeResolveInfo *nri)
+{
+       Decoration::resolveNodeNames(nri);
+       m_ndef->getIdsFromResolveInfo(nri, c_decos);
+       m_ndef->getIdsFromResolveInfo(nri, c_spawnby);
+}
+
+
 bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p)
 {
        // Don't bother if there aren't any decorations to place
@@ -310,13 +321,6 @@ int DecoSimple::getHeight()
 }
 
 
-void DecoSimple::dropResolverEntries(NodeResolver *resolver)
-{
-       resolver->cancelNodeList(&c_decos);
-       resolver->cancelNodeList(&c_spawnby);
-}
-
-
 ///////////////////////////////////////////////////////////////////////////////
 
 
index dffb524f39f95ea43b7caff7e96d5f256083f428..910f1a581fc8ee620fc1a050284c4243a5994bc8 100644 (file)
@@ -58,7 +58,7 @@ struct CutoffData {
 };
 #endif
 
-class Decoration : public GenElement {
+class Decoration : public GenElement, public NodeResolver {
 public:
        INodeDefManager *ndef;
 
@@ -76,12 +76,13 @@ public:
        Decoration();
        virtual ~Decoration();
 
+       virtual void resolveNodeNames(NodeResolveInfo *nri);
+
        size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
        size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
 
        virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0;
        virtual int getHeight() = 0;
-       virtual void dropResolverEntries(NodeResolver *resolver) {}
 };
 
 class DecoSimple : public Decoration {
@@ -92,12 +93,11 @@ public:
        s16 deco_height_max;
        s16 nspawnby;
 
-       ~DecoSimple() {}
+       virtual void resolveNodeNames(NodeResolveInfo *nri);
 
        bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p);
        virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
        virtual int getHeight();
-       virtual void dropResolverEntries(NodeResolver *resolver);
 };
 
 class DecoSchematic : public Decoration {
@@ -106,8 +106,6 @@ public:
        Schematic *schematic;
        std::string filename;
 
-       ~DecoSchematic() {}
-
        virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
        virtual int getHeight();
 };
index de3f6b0e5dcb1a3bc601a782f908199e5706fbf0..8681b5782cca4359cc05a5d93661aa1608604cb6 100644 (file)
@@ -64,11 +64,7 @@ void OreManager::clear()
 {
        for (size_t i = 0; i < m_elements.size(); i++) {
                Ore *ore = (Ore *)m_elements[i];
-               if (!ore)
-                       continue;
-
-               m_resolver->cancelNodeList(&ore->c_wherein);
-               m_resolver->cancelNode(&ore->c_ore);
+               delete ore;
        }
        m_elements.clear();
 }
@@ -84,6 +80,19 @@ Ore::Ore()
 }
 
 
+Ore::~Ore()
+{
+       delete noise;
+}
+
+
+void Ore::resolveNodeNames(NodeResolveInfo *nri)
+{
+       m_ndef->getIdFromResolveInfo(nri, "", CONTENT_AIR, c_ore);
+       m_ndef->getIdsFromResolveInfo(nri, c_wherein);
+}
+
+
 size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
 {
        int in_range = 0;
@@ -113,6 +122,9 @@ size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
 }
 
 
+///////////////////////////////////////////////////////////////////////////////
+
+
 void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
        u32 blockseed, v3s16 nmin, v3s16 nmax)
 {
@@ -151,6 +163,9 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
 }
 
 
+///////////////////////////////////////////////////////////////////////////////
+
+
 void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
        u32 blockseed, v3s16 nmin, v3s16 nmax)
 {
index 585d58f37a304be6acb9d364a95fedcf15e990a8..3b413674e926495d4e46fa96ed4e29df2a5797bf 100644 (file)
@@ -54,7 +54,7 @@ enum OreType {
 
 extern FlagDesc flagdesc_ore[];
 
-class Ore : public GenElement {
+class Ore : public GenElement, public NodeResolver {
 public:
        static const bool NEEDS_NOISE = false;
 
@@ -72,6 +72,9 @@ public:
        Noise *noise;
 
        Ore();
+       virtual ~Ore();
+
+       virtual void resolveNodeNames(NodeResolveInfo *nri);
 
        size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
        virtual void generate(ManualMapVoxelManipulator *vm, int seed,
index a7882464723d589a9b82711b2ab052b47796b231..299a328c918667c37fe2c87a8c2f6feb48a4b3a2 100644 (file)
@@ -58,6 +58,12 @@ Schematic::~Schematic()
 }
 
 
+void Schematic::resolveNodeNames(NodeResolveInfo *nri)
+{
+       m_ndef->getIdsFromResolveInfo(nri, c_nodes);
+}
+
+
 void Schematic::updateContentIds()
 {
        if (flags & SCHEM_CIDS_UPDATED)
@@ -195,8 +201,7 @@ void Schematic::placeStructure(Map *map, v3s16 p, u32 flags,
 
 
 bool Schematic::loadSchematicFromFile(const char *filename,
-       NodeResolver *resolver,
-       std::map<std::string, std::string> &replace_names)
+       INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
 {
        content_t cignore = CONTENT_IGNORE;
        bool have_cignore = false;
@@ -224,10 +229,9 @@ bool Schematic::loadSchematicFromFile(const char *filename,
        for (int y = 0; y != size.Y; y++)
                slice_probs[y] = (version >= 3) ? readU8(is) : MTSCHEM_PROB_ALWAYS;
 
-       int nodecount = size.X * size.Y * size.Z;
+       NodeResolveInfo *nri = new NodeResolveInfo(this);
 
        u16 nidmapcount = readU16(is);
-
        for (int i = 0; i != nidmapcount; i++) {
                std::string name = deSerializeString(is);
                if (name == "ignore") {
@@ -241,16 +245,22 @@ bool Schematic::loadSchematicFromFile(const char *filename,
                if (it != replace_names.end())
                        name = it->second;
 
-               resolver->addNodeList(name.c_str(), &c_nodes);
+               nri->nodenames.push_back(name);
        }
 
+       nri->nodename_sizes.push_back(nidmapcount);
+       ndef->pendNodeResolve(nri);
+
+       size_t nodecount = size.X * size.Y * size.Z;
+
        delete []schemdata;
        schemdata = new MapNode[nodecount];
+
        MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schemdata,
-                               nodecount, 2, 2, true);
+               nodecount, 2, 2, true);
 
        if (version == 1) { // fix up the probability values
-               for (int i = 0; i != nodecount; i++) {
+               for (size_t i = 0; i != nodecount; i++) {
                        if (schemdata[i].param1 == 0)
                                schemdata[i].param1 = MTSCHEM_PROB_ALWAYS;
                        if (have_cignore && schemdata[i].getContent() == cignore)
index df54d79bae0e008686f6c37c01a9c5bbf522130a..8d0b18148761b84a171597a7b6286502aa2cd638 100644 (file)
@@ -42,7 +42,7 @@ class NodeResolver;
 #define MTSCHEM_PROB_ALWAYS 0xFF
 
 
-class Schematic : public GenElement {
+class Schematic : public GenElement, public NodeResolver {
 public:
        std::vector<content_t> c_nodes;
 
@@ -52,14 +52,16 @@ public:
        u8 *slice_probs;
 
        Schematic();
-       ~Schematic();
+       virtual ~Schematic();
+
+       virtual void resolveNodeNames(NodeResolveInfo *nri);
 
        void updateContentIds();
 
        void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
                Rotation rot, bool force_placement, INodeDefManager *ndef);
 
-       bool loadSchematicFromFile(const char *filename, NodeResolver *resolver,
+       bool loadSchematicFromFile(const char *filename, INodeDefManager *ndef,
                std::map<std::string, std::string> &replace_names);
        void saveSchematicToFile(const char *filename, INodeDefManager *ndef);
        bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
@@ -86,7 +88,7 @@ public:
 };
 
 void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
-                                       std::vector<content_t> *usednodes);
+       std::vector<content_t> *usednodes);
 
 
 #endif
index e7bf9091f12898b43b9dbfd90e4e82e7a76271d3..bf97ff6d89b6ef0d24eddf21fc22b9957eb13a0c 100644 (file)
@@ -402,7 +402,15 @@ public:
        virtual void updateTextures(IGameDef *gamedef);
        void serialize(std::ostream &os, u16 protocol_version);
        void deSerialize(std::istream &is);
-       virtual NodeResolver *getResolver();
+
+       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 +440,12 @@ 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;
 };
 
 
-CNodeDefManager::CNodeDefManager() :
-       m_resolver(this)
+CNodeDefManager::CNodeDefManager()
 {
        clear();
 }
@@ -1035,12 +1042,6 @@ void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
 }
 
 
-NodeResolver *CNodeDefManager::getResolver()
-{
-       return &m_resolver;
-}
-
-
 IWritableNodeDefManager *createNodeDefManager()
 {
        return new CNodeDefManager();
@@ -1267,166 +1268,100 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
        }
 }
 
-/*
-       NodeResolver
-*/
 
-NodeResolver::NodeResolver(INodeDefManager *ndef)
+void CNodeDefManager::pendNodeResolve(NodeResolveInfo *nri)
 {
-       m_ndef = ndef;
-       m_is_node_registration_complete = false;
+       nri->resolver->m_ndef = this;
+       m_pending_node_lookups.push_back(nri);
 }
 
 
-NodeResolver::~NodeResolver()
+void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver)
 {
-       while (!m_pending_contents.empty()) {
-               NodeResolveInfo *nri = m_pending_contents.front();
-               m_pending_contents.pop_front();
-               delete nri;
-       }
-}
-
-
-int NodeResolver::addNode(const std::string &n_wanted, const std::string &n_alt,
-       content_t c_fallback, content_t *content)
-{
-       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;
+       for (std::list<NodeResolveInfo *>::iterator
+                       it = m_pending_node_lookups.begin();
+                       it != m_pending_node_lookups.end();
+                       ++it) {
+               NodeResolveInfo *nri = *it;
+               if (resolver == nri->resolver) {
+                       it = m_pending_node_lookups.erase(it);
+                       delete nri;
                }
-
-               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;
        }
 }
 
 
-int NodeResolver::addNodeList(const std::string &nodename,
-       std::vector<content_t> *content_vec)
+void CNodeDefManager::runNodeResolverCallbacks()
 {
-       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;
-       } else {
-               m_pending_content_vecs.push_back(
-                       std::make_pair(nodename, content_vec));
-               return NR_STATUS_PENDING;
+       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;
        }
 }
 
 
-bool NodeResolver::cancelNode(content_t *content)
+bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri,
+       const std::string &node_alt, content_t c_fallback, content_t &result)
 {
-       bool found = false;
-
-       for (std::list<NodeResolveInfo *>::iterator
-                       it = m_pending_contents.begin();
-                       it != m_pending_contents.end();
-                       ++it) {
-               NodeResolveInfo *nfi = *it;
-               if (nfi->output == content) {
-                       it = m_pending_contents.erase(it);
-                       delete nfi;
-                       found = true;
-               }
+       if (nri->nodenames.empty()) {
+               result = c_fallback;
+               errorstream << "CNodeDefManager::getIdFromResolveInfo: empty "
+                       "nodenames list" << std::endl;
+               return false;
        }
 
-       return found;
-}
-
+       content_t c;
+       std::string name = nri->nodenames.front();
+       nri->nodenames.pop_front();
 
-int NodeResolver::cancelNodeList(std::vector<content_t> *content_vec)
-{
-       int num_canceled = 0;
+       bool success = getId(name, c);
+       if (!success && node_alt != "") {
+               name = node_alt;
+               success = getId(name, c);
+       }
 
-       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++;
-               }
+       if (!success) {
+               errorstream << "CNodeDefManager::getIdFromResolveInfo: Failed to "
+                       "resolve node name '" << name << "'." << std::endl;
+               c = c_fallback;
        }
 
-       return num_canceled;
+       result = c;
+       return success;
 }
 
 
-int NodeResolver::resolveNodes()
+bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri,
+       std::vector<content_t> &result)
 {
-       int num_failed = 0;
+       if (nri->nodename_sizes.empty()) {
+               errorstream << "CNodeDefManager::getIdsFromResolveInfo: empty "
+                       "nodename_sizes list" << std::endl;
+               return false;
+       }
 
-       //// Resolve pending single node name -> content ID mappings
-       while (!m_pending_contents.empty()) {
-               NodeResolveInfo *nri = m_pending_contents.front();
-               m_pending_contents.pop_front();
+       size_t nitems = nri->nodename_sizes.front();
+       nri->nodename_sizes.pop_front();
 
-               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;
+       while (nitems--) {
+               if (nri->nodenames.empty()) {
+                       errorstream << "" << std::endl;
+                       return false;
                }
 
-               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;
+               content_t c;
+               if (getId(nri->nodenames.front(), c)) {
+                       result.push_back(c);
+               } else {
+                       errorstream << "CNodeDefManager::getIdsFromResolveInfo: empty "
+                               "nodenames list" << std::endl;
                }
 
-               delete nri;
-       }
-
-       //// 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();
-
-               std::string &name = item.first;
-               std::vector<content_t> *output = item.second;
-
-               std::set<content_t> idset;
-               std::set<content_t>::iterator it;
-
-               m_ndef->getIds(name, idset);
-               for (it = idset.begin(); it != idset.end(); ++it)
-                       output->push_back(*it);
-
-               if (idset.empty()) {
-                       num_failed++;
-                       errorstream << "NodeResolver::resolveNodes():  Failed to "
-                               "resolve '" << name << "'" << std::endl;
-               }
+               nri->nodenames.pop_front();
        }
 
-       //// Mark node registration as complete so future resolve
-       //// requests are satisfied immediately
-       m_is_node_registration_complete = true;
-
-       return num_failed;
+       return true;
 }
index dd76717e1b15ffd68be0a9dc4be36c5822b35d79..0c779ddccf04f513245838250705a8fc084a6451 100644 (file)
@@ -40,8 +40,6 @@ class IShaderSource;
 class IGameDef;
 
 typedef std::list<std::pair<content_t, int> > GroupItems;
-typedef std::list<std::pair<std::string, std::vector<content_t> *> >
-       ContentVectorResolveList;
 
 enum ContentParamType
 {
@@ -284,125 +282,18 @@ struct ContentFeatures
        }
 };
 
-struct NodeResolveInfo {
-       std::string n_wanted;
-       std::string n_alt;
-       content_t c_fallback;
-       content_t *output;
-};
-
-#define NR_STATUS_FAILURE 0
-#define NR_STATUS_PENDING 1
-#define NR_STATUS_SUCCESS 2
-
-/**
-       NodeResolver
-
-       NodeResolver attempts to resolve node names to content ID integers. If the
-       node registration phase has not yet finished at the time the resolution
-       request is placed, the request is marked as pending and added to an internal
-       queue.  The name resolution request is later satisfied by writing directly
-       to the output location when the node registration phase has been completed.
-
-       This is primarily intended to be used for objects registered during script
-       initialization (i.e. while nodes are being registered) that reference
-       particular nodes.
-*/
-class NodeResolver {
-public:
-       NodeResolver(INodeDefManager *ndef);
-       ~NodeResolver();
-
-       /**
-               Add a request to resolve the node n_wanted and set *content to the
-               result, or alternatively, n_alt if n_wanted is not found.  If n_alt
-               cannot be found either, or has not been specified, *content is set
-               to c_fallback.
-
-               If node registration is complete, the request is finished immediately
-               and NR_STATUS_SUCCESS is returned (or NR_STATUS_FAILURE if no node can
-               be found).  Otherwise, NR_STATUS_PENDING is returned and the resolution
-               request is queued.
-
-               N.B.  If the memory in which content is located has been deallocated
-               before the pending request had been satisfied, cancelNode() must be
-               called.
-
-               @param n_wanted Name of node that is wanted.
-               @param n_alt Name of node in case n_wanted could not be found.  Blank
-                       if no alternative node is desired.
-               @param c_fallback Content ID that content is set to in case of node
-                       resolution failure (should be CONTENT_AIR, CONTENT_IGNORE, etc.)
-               @param content Pointer to content_t that receives the result of the
-                       node name resolution.
-               @return Status of node resolution request.
-       */
-       int addNode(const std::string &n_wanted, const std::string &n_alt,
-               content_t c_fallback, content_t *content);
-
-       /**
-               Add a request to resolve the node(s) specified by nodename.
-
-               If node registration is complete, the request is finished immediately
-               and NR_STATUS_SUCCESS is returned if at least one node is resolved; if
-               zero were resolved, NR_STATUS_FAILURE.  Otherwise, NR_STATUS_PENDING is
-               returned and the resolution request is queued.
-
-               N.B.  If the memory in which content_vec is located has been deallocated
-               before the pending request had been satisfied, cancelNodeList() must be
-               called.
-
-               @param nodename Name of node (or node group) to be resolved.
-               @param content_vec Pointer to content_t vector onto which the results
-                       are added.
-
-               @return Status of node resolution request.
-       */
-       int addNodeList(const std::string &nodename,
-               std::vector<content_t> *content_vec);
-
-       /**
-               Removes all pending requests from the resolution queue with the output
-               address of 'content'.
-
-               @param content Location of the content ID for the request being
-                       cancelled.
-               @return Number of pending requests cancelled.
-       */
-       bool cancelNode(content_t *content);
-
-       /**
-               Removes all pending requests from the resolution queue with the output
-               address of 'content_vec'.
-
-               @param content_vec Location of the content ID vector for requests being
-                       cancelled.
-               @return Number of pending requests cancelled.
-       */
-       int cancelNodeList(std::vector<content_t> *content_vec);
-
-       /**
-               Carries out all pending node resolution requests.  Call this when the
-               node registration phase has completed.
-
-               Internally marks node registration as complete.
+class NodeResolver;
+class INodeDefManager;
 
-               @return Number of failed pending requests.
-       */
-       int resolveNodes();
-
-       /**
-               Returns the status of the node registration phase.
-
-               @return Boolean of whether the registration phase is complete.
-       */
-       bool isNodeRegFinished() { return m_is_node_registration_complete; }
+struct NodeResolveInfo {
+       NodeResolveInfo(NodeResolver *nr)
+       {
+               resolver = nr;
+       }
 
-private:
-       INodeDefManager *m_ndef;
-       bool m_is_node_registration_complete;
-       std::list<NodeResolveInfo *> m_pending_contents;
-       ContentVectorResolveList m_pending_content_vecs;
+       std::list<std::string> nodenames;
+       std::list<size_t> nodename_sizes;
+       NodeResolver *resolver;
 };
 
 class INodeDefManager
@@ -422,7 +313,14 @@ public:
 
        virtual void serialize(std::ostream &os, u16 protocol_version)=0;
 
-       virtual NodeResolver *getResolver()=0;
+       virtual void pendNodeResolve(NodeResolveInfo *nri)=0;
+       virtual void cancelNodeResolve(NodeResolver *resolver)=0;
+       virtual void runNodeResolverCallbacks()=0;
+
+       virtual bool getIdFromResolveInfo(NodeResolveInfo *nri,
+               const std::string &node_alt, content_t c_fallback, content_t &result)=0;
+       virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri,
+               std::vector<content_t> &result)=0;
 };
 
 class IWritableNodeDefManager : public INodeDefManager
@@ -464,10 +362,38 @@ public:
        virtual void serialize(std::ostream &os, u16 protocol_version)=0;
        virtual void deSerialize(std::istream &is)=0;
 
-       virtual NodeResolver *getResolver()=0;
+       virtual void pendNodeResolve(NodeResolveInfo *nri)=0;
+       virtual void cancelNodeResolve(NodeResolver *resolver)=0;
+       virtual void runNodeResolverCallbacks()=0;
+
+       virtual bool getIdFromResolveInfo(NodeResolveInfo *nri,
+               const std::string &node_alt, content_t c_fallback, content_t &result)=0;
+       virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri,
+               std::vector<content_t> &result)=0;
 };
 
 IWritableNodeDefManager *createNodeDefManager();
 
+class NodeResolver {
+public:
+       NodeResolver()
+       {
+               m_lookup_done = false;
+               m_ndef = NULL;
+       }
+
+       ~NodeResolver()
+       {
+               if (!m_lookup_done)
+                       m_ndef->cancelNodeResolve(this);
+       }
+
+       virtual void resolveNodeNames(NodeResolveInfo *nri) = 0;
+
+       bool m_lookup_done;
+       INodeDefManager *m_ndef;
+};
+
+
 #endif
 
index a906171d3665fa6e1be92f27f3d32f7967a21e66..66eeec68ebd0fc87fa072c48da5f8eb1610cc46a 100644 (file)
@@ -235,7 +235,8 @@ bool read_stringlist(lua_State *L, int index, std::vector<const char *> &result)
        if (lua_istable(L, index)) {
                lua_pushnil(L);
                while (lua_next(L, index)) {
-                       result.push_back(lua_tostring(L, -1));
+                       if (lua_isstring(L, -1))
+                               result.push_back(lua_tostring(L, -1));
                        lua_pop(L, 1);
                }
        } else if (lua_isstring(L, index)) {
index 177e0d85bd9a8ab00ba2085911462040dc90bba8..a90c2c6c54349682ec7a33f3d1a547289cf2bd4c 100644 (file)
@@ -183,9 +183,8 @@ bool get_schematic(lua_State *L, int index, Schematic *schem,
        if (lua_istable(L, index)) {
                return read_schematic(L, index, schem, ndef, replace_names);
        } else if (lua_isstring(L, index)) {
-               NodeResolver *resolver = ndef->getResolver();
                const char *filename = lua_tostring(L, index);
-               return schem->loadSchematicFromFile(filename, resolver, replace_names);
+               return schem->loadSchematicFromFile(filename, ndef, replace_names);
        } else {
                return false;
        }
@@ -415,8 +414,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
        int index = 1;
        luaL_checktype(L, index, LUA_TTABLE);
 
-       NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
-       BiomeManager *bmgr     = getServer(L)->getEmergeManager()->biomemgr;
+       INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+       BiomeManager *bmgr    = getServer(L)->getEmergeManager()->biomemgr;
 
        enum BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
                es_BiomeTerrainType, BIOME_TYPE_NORMAL);
@@ -437,19 +436,15 @@ int ModApiMapgen::l_register_biome(lua_State *L)
                return 0;
        }
 
-       // Pend node resolutions only if insertion succeeded
-       resolver->addNode(getstringfield_default(L, index, "node_top", ""),
-                "mapgen_dirt_with_grass", CONTENT_AIR, &b->c_top);
-       resolver->addNode(getstringfield_default(L, index, "node_filler", ""),
-               "mapgen_dirt", CONTENT_AIR, &b->c_filler);
-       resolver->addNode(getstringfield_default(L, index, "node_stone", ""),
-               "mapgen_stone", CONTENT_AIR, &b->c_stone);
-       resolver->addNode(getstringfield_default(L, index, "node_water", ""),
-               "mapgen_water_source", CONTENT_AIR, &b->c_water);
-       resolver->addNode(getstringfield_default(L, index, "node_dust", ""),
-               "air", CONTENT_IGNORE, &b->c_dust);
-       resolver->addNode(getstringfield_default(L, index, "node_dust_water", ""),
-               "mapgen_water_source", CONTENT_IGNORE, &b->c_dust_water);
+       NodeResolveInfo *nri = new NodeResolveInfo(b);
+       std::list<std::string> &nnames = nri->nodenames;
+       nnames.push_back(getstringfield_default(L, index, "node_top",        ""));
+       nnames.push_back(getstringfield_default(L, index, "node_filler",     ""));
+       nnames.push_back(getstringfield_default(L, index, "node_stone",      ""));
+       nnames.push_back(getstringfield_default(L, index, "node_water",      ""));
+       nnames.push_back(getstringfield_default(L, index, "node_dust",       ""));
+       nnames.push_back(getstringfield_default(L, index, "node_dust_water", ""));
+       ndef->pendNodeResolve(nri);
 
        verbosestream << "register_biome: " << b->name << std::endl;
 
@@ -485,7 +480,6 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
        luaL_checktype(L, index, LUA_TTABLE);
 
        INodeDefManager *ndef      = getServer(L)->getNodeDefManager();
-       NodeResolver *resolver     = getServer(L)->getNodeDefManager()->getResolver();
        DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
        BiomeManager *biomemgr     = getServer(L)->getEmergeManager()->biomemgr;
 
@@ -509,11 +503,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
                return 0;
        }
 
+       NodeResolveInfo *nri = new NodeResolveInfo(deco);
+
        //// Get node name(s) to place decoration on
        std::vector<const char *> place_on_names;
        getstringlistfield(L, index, "place_on", place_on_names);
+       nri->nodename_sizes.push_back(place_on_names.size());
        for (size_t i = 0; i != place_on_names.size(); i++)
-               resolver->addNodeList(place_on_names[i], &deco->c_place_on);
+               nri->nodenames.push_back(place_on_names[i]);
 
        getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL);
 
@@ -538,7 +535,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
        bool success = false;
        switch (decotype) {
                case DECO_SIMPLE:
-                       success = regDecoSimple(L, resolver, (DecoSimple *)deco);
+                       success = regDecoSimple(L, nri, (DecoSimple *)deco);
                        break;
                case DECO_SCHEMATIC:
                        success = regDecoSchematic(L, ndef, (DecoSchematic *)deco);
@@ -547,6 +544,8 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
                        break;
        }
 
+       ndef->pendNodeResolve(nri);
+
        if (!success) {
                delete deco;
                return 0;
@@ -558,12 +557,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
                return 0;
        }
 
+       verbosestream << "register_decoration: " << deco->name << std::endl;
+
        lua_pushinteger(L, id);
        return 1;
 }
 
 bool ModApiMapgen::regDecoSimple(lua_State *L,
-               NodeResolver *resolver, DecoSimple *deco)
+               NodeResolveInfo *nri, DecoSimple *deco)
 {
        int index = 1;
 
@@ -584,6 +585,9 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
                        "defined" << std::endl;
                return false;
        }
+       nri->nodename_sizes.push_back(deco_names.size());
+       for (size_t i = 0; i != deco_names.size(); i++)
+               nri->nodenames.push_back(deco_names[i]);
 
        std::vector<const char *> spawnby_names;
        getstringlistfield(L, index, "spawn_by", spawnby_names);
@@ -592,11 +596,9 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
                        " but num_spawn_by specified" << std::endl;
                return false;
        }
-
-       for (size_t i = 0; i != deco_names.size(); i++)
-               resolver->addNodeList(deco_names[i], &deco->c_decos);
+       nri->nodename_sizes.push_back(spawnby_names.size());
        for (size_t i = 0; i != spawnby_names.size(); i++)
-               resolver->addNodeList(spawnby_names[i], &deco->c_spawnby);
+               nri->nodenames.push_back(spawnby_names[i]);
 
        return true;
 }
@@ -615,6 +617,7 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
                read_schematic_replacements(L, replace_names, lua_gettop(L));
        lua_pop(L, 1);
 
+       // TODO(hmmmm): get a ref from registered schematics
        Schematic *schem = new Schematic;
        lua_getfield(L, index, "schematic");
        if (!get_schematic(L, -1, schem, ndef, replace_names)) {
@@ -635,8 +638,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
        int index = 1;
        luaL_checktype(L, index, LUA_TTABLE);
 
-       NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
-       OreManager *oremgr     = getServer(L)->getEmergeManager()->oremgr;
+       INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+       OreManager *oremgr    = getServer(L)->getEmergeManager()->oremgr;
 
        enum OreType oretype = (OreType)getenumfield(L, index,
                                "ore_type", es_OreType, ORE_SCATTER);
@@ -683,13 +686,18 @@ int ModApiMapgen::l_register_ore(lua_State *L)
                return 0;
        }
 
+       NodeResolveInfo *nri = new NodeResolveInfo(ore);
+       nri->nodenames.push_back(getstringfield_default(L, index, "ore", ""));
+
        std::vector<const char *> wherein_names;
        getstringlistfield(L, index, "wherein", wherein_names);
+       nri->nodename_sizes.push_back(wherein_names.size());
        for (size_t i = 0; i != wherein_names.size(); i++)
-               resolver->addNodeList(wherein_names[i], &ore->c_wherein);
+               nri->nodenames.push_back(wherein_names[i]);
+
+       ndef->pendNodeResolve(nri);
 
-       resolver->addNode(getstringfield_default(L, index, "ore", ""),
-               "", CONTENT_AIR, &ore->c_ore);
+       verbosestream << "register_ore: " << ore->name << std::endl;
 
        lua_pushinteger(L, id);
        return 1;
index 87ae9fd817aad909ee6881e1885f6f4480975a41..247043a019e6d992f7bd904505388b9d3a6c294c 100644 (file)
@@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "lua_api/l_base.h"
 
 class INodeDefManager;
-class NodeResolver;
+class NodeResolveInfo;
 class DecoSimple;
 class DecoSchematic;
 
@@ -68,7 +68,7 @@ private:
        static int l_place_schematic(lua_State *L);
 
        static bool regDecoSimple(lua_State *L,
-                       NodeResolver *resolver, DecoSimple *deco);
+                       NodeResolveInfo *nri, DecoSimple *deco);
        static bool regDecoSchematic(lua_State *L,
                        INodeDefManager *ndef, DecoSchematic *deco);
 
index d56c34c65e7d26b3ce02becde2918cec4efa0ee9..161aaafc71a96196290655c318e7ba06605b4e8b 100644 (file)
@@ -337,7 +337,7 @@ Server::Server(
        m_nodedef->updateAliases(m_itemdef);
 
        // Perform pending node name resolutions
-       m_nodedef->getResolver()->resolveNodes();
+       m_nodedef->runNodeResolverCallbacks();
 
        // Load the mapgen params from global settings now after any
        // initial overrides have been set by the mods
@@ -2650,7 +2650,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        }
 
                } // action == 4
-               
+
 
                /*
                        Catch invalid actions
@@ -4570,7 +4570,7 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c
 u32 Server::hudAdd(Player *player, HudElement *form) {
        if (!player)
                return -1;
-       
+
        u32 id = player->addHud(form);
 
        SendHUDAdd(player->peer_id, id, form);
@@ -4586,7 +4586,7 @@ bool Server::hudRemove(Player *player, u32 id) {
 
        if (!todel)
                return false;
-       
+
        delete todel;
 
        SendHUDRemove(player->peer_id, id);
@@ -4607,9 +4607,9 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
 
        SendHUDSetFlags(player->peer_id, flags, mask);
        player->hud_flags = flags;
-       
+
        PlayerSAO* playersao = player->getPlayerSAO();
-       
+
        if (playersao == NULL)
                return false;