diff --git a/src/mapgen.cpp b/src/mapgen.cpp index ceaabbb1a..24f9fc556 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -384,7 +384,7 @@ void GenerateNotifier::getEvents( GenElementManager::GenElementManager(IGameDef *gamedef) { - m_resolver = gamedef->getNodeDefManager()->getResolver(); + m_ndef = gamedef->getNodeDefManager(); } diff --git a/src/mapgen.h b/src/mapgen.h index 03850cd19..07202f9a2 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -192,7 +192,7 @@ public: virtual GenElement *getByName(const std::string &name); protected: - NodeResolver *m_resolver; + INodeDefManager *m_ndef; std::vector m_elements; }; diff --git a/src/mg_biome.cpp b/src/mg_biome.cpp index a3a6d5128..763bef1bc 100644 --- a/src/mg_biome.cpp +++ b/src/mg_biome.cpp @@ -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); +} + diff --git a/src/mg_biome.h b/src/mg_biome.h index f1539dacb..870c11961 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -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 { diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index 761b231ed..50e8fb05a 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -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); -} - - /////////////////////////////////////////////////////////////////////////////// diff --git a/src/mg_decoration.h b/src/mg_decoration.h index dffb524f3..910f1a581 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -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(); }; diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index de3f6b0e5..8681b5782 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -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) { diff --git a/src/mg_ore.h b/src/mg_ore.h index 585d58f37..3b413674e 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -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, diff --git a/src/mg_schematic.cpp b/src/mg_schematic.cpp index a78824647..299a328c9 100644 --- a/src/mg_schematic.cpp +++ b/src/mg_schematic.cpp @@ -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 &replace_names) + INodeDefManager *ndef, std::map &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) diff --git a/src/mg_schematic.h b/src/mg_schematic.h index df54d79ba..8d0b18148 100644 --- a/src/mg_schematic.h +++ b/src/mg_schematic.h @@ -42,7 +42,7 @@ class NodeResolver; #define MTSCHEM_PROB_ALWAYS 0xFF -class Schematic : public GenElement { +class Schematic : public GenElement, public NodeResolver { public: std::vector 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 &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 *usednodes); + std::vector *usednodes); #endif diff --git a/src/nodedef.cpp b/src/nodedef.cpp index e7bf9091f..bf97ff6d8 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -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 &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 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; - } - - 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_vec) -{ - if (m_is_node_registration_complete) { - std::set idset; - std::set::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; - } -} - - -bool NodeResolver::cancelNode(content_t *content) -{ - bool found = false; - for (std::list::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_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++; - } - } - - return num_canceled; -} - - -int NodeResolver::resolveNodes() -{ - 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(); - - 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; - } - - 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; - } - + 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; } +} - //// Resolve pending node names and add to content_t vector - while (!m_pending_content_vecs.empty()) { - std::pair *> item = - m_pending_content_vecs.front(); - m_pending_content_vecs.pop_front(); - std::string &name = item.first; - std::vector *output = item.second; - - std::set idset; - std::set::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; - } +bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri, + const std::string &node_alt, content_t c_fallback, content_t &result) +{ + if (nri->nodenames.empty()) { + result = c_fallback; + errorstream << "CNodeDefManager::getIdFromResolveInfo: empty " + "nodenames 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(); - return num_failed; + bool success = getId(name, c); + if (!success && node_alt != "") { + name = node_alt; + success = getId(name, c); + } + + if (!success) { + errorstream << "CNodeDefManager::getIdFromResolveInfo: Failed to " + "resolve node name '" << name << "'." << std::endl; + c = c_fallback; + } + + result = c; + return success; +} + + +bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri, + std::vector &result) +{ + if (nri->nodename_sizes.empty()) { + errorstream << "CNodeDefManager::getIdsFromResolveInfo: empty " + "nodename_sizes list" << std::endl; + return false; + } + + size_t nitems = nri->nodename_sizes.front(); + nri->nodename_sizes.pop_front(); + + while (nitems--) { + if (nri->nodenames.empty()) { + errorstream << "" << std::endl; + return false; + } + + content_t c; + if (getId(nri->nodenames.front(), c)) { + result.push_back(c); + } else { + errorstream << "CNodeDefManager::getIdsFromResolveInfo: empty " + "nodenames list" << std::endl; + } + + nri->nodenames.pop_front(); + } + + return true; } diff --git a/src/nodedef.h b/src/nodedef.h index dd76717e1..0c779ddcc 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -40,8 +40,6 @@ class IShaderSource; class IGameDef; typedef std::list > GroupItems; -typedef std::list *> > - ContentVectorResolveList; enum ContentParamType { @@ -284,125 +282,18 @@ struct ContentFeatures } }; +class NodeResolver; +class INodeDefManager; + struct NodeResolveInfo { - std::string n_wanted; - std::string n_alt; - content_t c_fallback; - content_t *output; -}; + NodeResolveInfo(NodeResolver *nr) + { + resolver = nr; + } -#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_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_vec); - - /** - Carries out all pending node resolution requests. Call this when the - node registration phase has completed. - - Internally marks node registration as complete. - - @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; } - -private: - INodeDefManager *m_ndef; - bool m_is_node_registration_complete; - std::list m_pending_contents; - ContentVectorResolveList m_pending_content_vecs; + std::list nodenames; + std::list 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 &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 &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 diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index a906171d3..66eeec68e 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -235,7 +235,8 @@ bool read_stringlist(lua_State *L, int index, std::vector &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)) { diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 177e0d85b..a90c2c6c5 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -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 &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 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 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 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]); - resolver->addNode(getstringfield_default(L, index, "ore", ""), - "", CONTENT_AIR, &ore->c_ore); + ndef->pendNodeResolve(nri); + + verbosestream << "register_ore: " << ore->name << std::endl; lua_pushinteger(L, id); return 1; diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 87ae9fd81..247043a01 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -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); diff --git a/src/server.cpp b/src/server.cpp index d56c34c65..161aaafc7 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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;