diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 25f9d53ca..a7fcaeab1 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2170,14 +2170,23 @@ These functions return the leftover itemstack. * `force_placement` is a boolean indicating whether nodes other than `air` and `ignore` are replaced by the schematic -* `minetest.serialize_schematic(schematic, format, use_comments)` +* `minetest.serialize_schematic(schematic, format, options)` * Return the serialized schematic specified by schematic (see: Schematic specifier) * in the `format` of either "mts" or "lua". * "mts" - a string containing the binary MTS data used in the MTS file format * "lua" - a string containing Lua code representing the schematic in table format - * If `use_comments` is true, the Lua code generated will have (X, Z) position comments - * for every X row generated in the schematic data for easier reading. This parameter - * is ignored if `format` is not "lua". + * `options` is a table containing the following optional parameters: + * If `use_comments` is true and `format` is "lua", the Lua code generated will have (X, Z) + * position comments for every X row generated in the schematic data for easier reading. + * If `register_after_load` is true, then `schematic`, if not yet loaded, will be registered + * after loading and persist in memory. + * node_resolve_method can be one of either "none", "direct", or "deferred" (default: "none") + * This sets the way method by with node names are mapped to their content IDs, if loaded: + * "none" performs no node resolution and preserves all node names from the schematic definition + * "direct" performs an immediate lookup of content ID, given all the nodes that have been + * registered up to this point in script execution + * "deferred" pends node resolution until after the script registration phase has ended + * In practice, it is recommended to use "none" in nearly all use cases. ### Misc. * `minetest.get_connected_players()`: returns list of `ObjectRefs` diff --git a/src/client.cpp b/src/client.cpp index 8a018de28..99ef3c7e1 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -388,7 +388,7 @@ void Client::step(float dtime) if(counter <= 0.0) { counter = 2.0; - Player *myplayer = m_env.getLocalPlayer(); + Player *myplayer = m_env.getLocalPlayer(); FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment."); // Send TOSERVER_INIT_LEGACY @@ -1631,7 +1631,7 @@ void Client::afterContentReceived(IrrlichtDevice *device) draw_load_screen(text, device, guienv, 0, 72); m_nodedef->updateAliases(m_itemdef); m_nodedef->setNodeRegistrationStatus(true); - m_nodedef->runNodeResolverCallbacks(); + m_nodedef->runNodeResolveCallbacks(); delete[] text; // Update node textures and assign shaders to each tile diff --git a/src/mg_biome.cpp b/src/mg_biome.cpp index 75334544a..c2040f542 100644 --- a/src/mg_biome.cpp +++ b/src/mg_biome.cpp @@ -46,14 +46,13 @@ BiomeManager::BiomeManager(IGameDef *gamedef) : b->heat_point = 0.0; b->humidity_point = 0.0; - 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("mapgen_water_source"); - nri->nodenames.push_back("air"); - m_ndef->pendNodeResolve(nri); + b->m_nodenames.push_back("air"); + b->m_nodenames.push_back("air"); + b->m_nodenames.push_back("mapgen_stone"); + b->m_nodenames.push_back("mapgen_water_source"); + b->m_nodenames.push_back("mapgen_water_source"); + b->m_nodenames.push_back("air"); + m_ndef->pendNodeResolve(b, NODE_RESOLVE_DEFERRED); add(b); } @@ -117,13 +116,13 @@ void BiomeManager::clear() /////////////////////////////////////////////////////////////////////////////// -void Biome::resolveNodeNames(NodeResolveInfo *nri) +void Biome::resolveNodeNames() { - 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_top); - m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water); - m_ndef->getIdFromResolveInfo(nri, "air", CONTENT_IGNORE, c_dust); + getIdFromNrBacklog(&c_top, "mapgen_dirt_with_grass", CONTENT_AIR); + getIdFromNrBacklog(&c_filler, "mapgen_dirt", CONTENT_AIR); + getIdFromNrBacklog(&c_stone, "mapgen_stone", CONTENT_AIR); + getIdFromNrBacklog(&c_water_top, "mapgen_water_source", CONTENT_AIR); + getIdFromNrBacklog(&c_water, "mapgen_water_source", CONTENT_AIR); + getIdFromNrBacklog(&c_dust, "air", CONTENT_IGNORE); } diff --git a/src/mg_biome.h b/src/mg_biome.h index 7e789d3b1..a0ed30d6e 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -53,7 +53,7 @@ public: float heat_point; float humidity_point; - virtual void resolveNodeNames(NodeResolveInfo *nri); + virtual void resolveNodeNames(); }; class BiomeManager : public ObjDefManager { diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index 1858e346a..8f81b0d11 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -88,9 +88,9 @@ Decoration::~Decoration() } -void Decoration::resolveNodeNames(NodeResolveInfo *nri) +void Decoration::resolveNodeNames() { - m_ndef->getIdsFromResolveInfo(nri, c_place_on); + getIdsFromNrBacklog(&c_place_on); } @@ -232,11 +232,11 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) /////////////////////////////////////////////////////////////////////////////// -void DecoSimple::resolveNodeNames(NodeResolveInfo *nri) +void DecoSimple::resolveNodeNames() { - Decoration::resolveNodeNames(nri); - m_ndef->getIdsFromResolveInfo(nri, c_decos); - m_ndef->getIdsFromResolveInfo(nri, c_spawnby); + Decoration::resolveNodeNames(); + getIdsFromNrBacklog(&c_decos); + getIdsFromNrBacklog(&c_spawnby); } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index c92cfe4dc..180c248be 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -79,7 +79,7 @@ public: Decoration(); virtual ~Decoration(); - virtual void resolveNodeNames(NodeResolveInfo *nri); + virtual void resolveNodeNames(); size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); //size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); @@ -96,7 +96,7 @@ public: s16 deco_height_max; s16 nspawnby; - virtual void resolveNodeNames(NodeResolveInfo *nri); + virtual void resolveNodeNames(); bool canPlaceDecoration(MMVManip *vm, v3s16 p); virtual size_t generate(MMVManip *vm, PseudoRandom *pr, v3s16 p); diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index e7e062c69..dd113e6ce 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -82,10 +82,10 @@ Ore::~Ore() } -void Ore::resolveNodeNames(NodeResolveInfo *nri) +void Ore::resolveNodeNames() { - m_ndef->getIdFromResolveInfo(nri, "", CONTENT_AIR, c_ore); - m_ndef->getIdsFromResolveInfo(nri, c_wherein); + getIdFromNrBacklog(&c_ore, "", CONTENT_AIR); + getIdsFromNrBacklog(&c_wherein); } diff --git a/src/mg_ore.h b/src/mg_ore.h index 59a1341b7..b6cf176e7 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -67,7 +67,7 @@ public: Ore(); virtual ~Ore(); - virtual void resolveNodeNames(NodeResolveInfo *nri); + virtual void resolveNodeNames(); size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, diff --git a/src/mg_schematic.cpp b/src/mg_schematic.cpp index 71884c3d8..2b9c7faeb 100644 --- a/src/mg_schematic.cpp +++ b/src/mg_schematic.cpp @@ -56,22 +56,16 @@ Schematic::~Schematic() } -void Schematic::resolveNodeNames(NodeResolveInfo *nri) +void Schematic::resolveNodeNames() { - m_ndef->getIdsFromResolveInfo(nri, c_nodes); -} - - -void Schematic::updateContentIds() -{ - if (flags & SCHEM_CIDS_UPDATED) - return; - - flags |= SCHEM_CIDS_UPDATED; + getIdsFromNrBacklog(&c_nodes, true, CONTENT_AIR); size_t bufsize = size.X * size.Y * size.Z; - for (size_t i = 0; i != bufsize; i++) - schemdata[i].setContent(c_nodes[schemdata[i].getContent()]); + for (size_t i = 0; i != bufsize; i++) { + content_t c_original = schemdata[i].getContent(); + content_t c_new = c_nodes[c_original]; + schemdata[i].setContent(c_new); + } } @@ -82,8 +76,6 @@ void Schematic::blitToVManip(v3s16 p, MMVManip *vm, Rotation rot, int ystride = size.X; int zstride = size.X * size.Y; - updateContentIds(); - s16 sx = size.X; s16 sy = size.Y; s16 sz = size.Z; @@ -198,8 +190,7 @@ void Schematic::placeStructure(Map *map, v3s16 p, u32 flags, Rotation rot, } -bool Schematic::deserializeFromMts(std::istream *is, - INodeDefManager *ndef, std::vector *names) +bool Schematic::deserializeFromMts(std::istream *is, std::vector *names) { std::istream &ss = *is; content_t cignore = CONTENT_IGNORE; @@ -263,7 +254,7 @@ bool Schematic::deserializeFromMts(std::istream *is, } -bool Schematic::serializeToMts(std::ostream *os, INodeDefManager *ndef) +bool Schematic::serializeToMts(std::ostream *os) { std::ostream &ss = *os; @@ -281,7 +272,7 @@ bool Schematic::serializeToMts(std::ostream *os, INodeDefManager *ndef) u16 numids = usednodes.size(); writeU16(ss, numids); // name count for (int i = 0; i != numids; i++) - ss << serializeString(ndef->get(usednodes[i]).name); // node names + ss << serializeString(getNodeName(usednodes[i])); // node names // compressed bulk node data MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, @@ -291,8 +282,7 @@ bool Schematic::serializeToMts(std::ostream *os, INodeDefManager *ndef) } -bool Schematic::serializeToLua(std::ostream *os, - INodeDefManager *ndef, bool use_comments) +bool Schematic::serializeToLua(std::ostream *os, bool use_comments) { std::ostream &ss = *os; @@ -335,7 +325,7 @@ bool Schematic::serializeToLua(std::ostream *os, for (u16 x = 0; x != size.X; x++, i++) { ss << "\t\t{" - << "name=\"" << ndef->get(schemdata[i]).name + << "name=\"" << getNodeName(schemdata[i].getContent()) << "\", param1=" << (u16)schemdata[i].param1 << ", param2=" << (u16)schemdata[i].param2 << "}," << std::endl; @@ -351,8 +341,9 @@ bool Schematic::serializeToLua(std::ostream *os, } -bool Schematic::loadSchematicFromFile(const char *filename, - INodeDefManager *ndef, StringMap *replace_names) +bool Schematic::loadSchematicFromFile(const std::string &filename, + INodeDefManager *ndef, StringMap *replace_names, + NodeResolveMethod resolve_method) { std::ifstream is(filename, std::ios_base::binary); if (!is.good()) { @@ -361,30 +352,31 @@ bool Schematic::loadSchematicFromFile(const char *filename, return false; } - std::vector names; - if (!deserializeFromMts(&is, ndef, &names)) + size_t origsize = m_nodenames.size(); + if (!deserializeFromMts(&is, &m_nodenames)) return false; - NodeResolveInfo *nri = new NodeResolveInfo(this); - for (size_t i = 0; i != names.size(); i++) { - if (replace_names) { - StringMap::iterator it = replace_names->find(names[i]); + if (replace_names) { + for (size_t i = origsize; i != m_nodenames.size(); i++) { + std::string &name = m_nodenames[i]; + StringMap::iterator it = replace_names->find(name); if (it != replace_names->end()) - names[i] = it->second; + name = it->second; } - nri->nodenames.push_back(names[i]); } - nri->nodelistinfo.push_back(NodeListInfo(names.size(), CONTENT_AIR)); - ndef->pendNodeResolve(nri); + + m_nnlistsizes.push_back(m_nodenames.size() - origsize); + + ndef->pendNodeResolve(this, resolve_method); return true; } -bool Schematic::saveSchematicToFile(const char *filename, INodeDefManager *ndef) +bool Schematic::saveSchematicToFile(const std::string &filename) { std::ostringstream os(std::ios_base::binary); - serializeToMts(&os, ndef); + serializeToMts(&os); return fs::safeWriteToFile(filename, os.str()); } diff --git a/src/mg_schematic.h b/src/mg_schematic.h index 50d48b1f1..63cea21f6 100644 --- a/src/mg_schematic.h +++ b/src/mg_schematic.h @@ -94,23 +94,21 @@ public: Schematic(); virtual ~Schematic(); - virtual void resolveNodeNames(NodeResolveInfo *nri); + virtual void resolveNodeNames(); void updateContentIds(); void blitToVManip(v3s16 p, MMVManip *vm, Rotation rot, bool force_placement, INodeDefManager *ndef); - bool loadSchematicFromFile(const char *filename, INodeDefManager *ndef, - StringMap *replace_names); - bool saveSchematicToFile(const char *filename, INodeDefManager *ndef); + bool loadSchematicFromFile(const std::string &filename, INodeDefManager *ndef, + StringMap *replace_names, NodeResolveMethod resolve_method); + bool saveSchematicToFile(const std::string &filename); bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2); - bool deserializeFromMts(std::istream *is, INodeDefManager *ndef, - std::vector *names); - bool serializeToMts(std::ostream *os, INodeDefManager *ndef); - bool serializeToLua(std::ostream *os, - INodeDefManager *ndef, bool use_comments); + bool deserializeFromMts(std::istream *is, std::vector *names_out); + bool serializeToMts(std::ostream *os); + bool serializeToLua(std::ostream *os, bool use_comments); void placeStructure(Map *map, v3s16 p, u32 flags, @@ -118,8 +116,6 @@ public: void applyProbabilities(v3s16 p0, std::vector > *plist, std::vector > *splist); - - std::string getAsLuaTable(INodeDefManager *ndef, bool use_comments); }; class SchematicManager : public ObjDefManager { diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 486a99350..58566200e 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -406,14 +406,9 @@ public: 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 &result); + virtual void pendNodeResolve(NodeResolver *nr, NodeResolveMethod how); + virtual bool cancelNodeResolveCallback(NodeResolver *nr); + virtual void runNodeResolveCallbacks(); private: void addNameIdMapping(content_t i, std::string name); @@ -443,8 +438,8 @@ private: // Next possibly free id content_t m_next_id; - // List of node strings and node resolver callbacks to perform - std::list m_pending_node_lookups; + // NodeResolvers to callback once node registration has ended + std::vector m_pending_resolve_callbacks; // True when all nodes have been registered bool m_node_registration_complete; @@ -480,12 +475,7 @@ void CNodeDefManager::clear() m_next_id = 0; m_node_registration_complete = false; - for (std::list::iterator - it = m_pending_node_lookups.begin(); - it != m_pending_node_lookups.end(); - ++it) - delete *it; - m_pending_node_lookups.clear(); + m_pending_resolve_callbacks.clear(); u32 initial_length = 0; initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1); @@ -1304,114 +1294,167 @@ inline void CNodeDefManager::setNodeRegistrationStatus(bool completed) } -void CNodeDefManager::pendNodeResolve(NodeResolveInfo *nri) +void CNodeDefManager::pendNodeResolve(NodeResolver *nr, NodeResolveMethod how) { - nri->resolver->m_ndef = this; - if (m_node_registration_complete) { - nri->resolver->resolveNodeNames(nri); - nri->resolver->m_lookup_done = true; - delete nri; + nr->m_ndef = this; + + switch (how) { + case NODE_RESOLVE_NONE: + break; + case NODE_RESOLVE_DIRECT: + nr->nodeResolveInternal(); + break; + case NODE_RESOLVE_DEFERRED: + if (m_node_registration_complete) + nr->nodeResolveInternal(); + else + m_pending_resolve_callbacks.push_back(nr); + break; + } +} + + +bool CNodeDefManager::cancelNodeResolveCallback(NodeResolver *nr) +{ + size_t len = m_pending_resolve_callbacks.size(); + for (size_t i = 0; i != len; i++) { + if (nr != m_pending_resolve_callbacks[i]) + continue; + + len--; + m_pending_resolve_callbacks[i] = m_pending_resolve_callbacks[len]; + m_pending_resolve_callbacks.resize(len); + return true; + } + + return false; +} + + +void CNodeDefManager::runNodeResolveCallbacks() +{ + for (size_t i = 0; i != m_pending_resolve_callbacks.size(); i++) { + NodeResolver *nr = m_pending_resolve_callbacks[i]; + nr->nodeResolveInternal(); + } + + m_pending_resolve_callbacks.clear(); +} + + +//// +//// NodeResolver +//// + +NodeResolver::NodeResolver() { + m_ndef = NULL; + m_nodenames_idx = 0; + m_nnlistsizes_idx = 0; + m_resolve_done = false; + + m_nodenames.reserve(16); + m_nnlistsizes.reserve(4); +} + + +NodeResolver::~NodeResolver() +{ + if (!m_resolve_done && m_ndef) + m_ndef->cancelNodeResolveCallback(this); +} + + +void NodeResolver::nodeResolveInternal() +{ + m_nodenames_idx = 0; + m_nnlistsizes_idx = 0; + + resolveNodeNames(); + m_resolve_done = true; + + m_nodenames.clear(); + m_nnlistsizes.clear(); +} + + +const std::string &NodeResolver::getNodeName(content_t c) const +{ + if (m_nodenames.size() == 0) { + return m_ndef->get(c).name; } else { - m_pending_node_lookups.push_back(nri); + if (c < m_nodenames.size()) + return m_nodenames[c]; + else + return m_ndef->get(CONTENT_UNKNOWN).name; } } -void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver) +bool NodeResolver::getIdFromNrBacklog(content_t *result_out, + const std::string &node_alt, content_t c_fallback) { - for (std::list::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; - } - } -} - - -void CNodeDefManager::runNodeResolverCallbacks() -{ - 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 CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri, - const std::string &node_alt, content_t c_fallback, content_t &result) -{ - if (nri->nodenames.empty()) { - result = c_fallback; - errorstream << "Resolver empty nodename list" << std::endl; + if (m_nodenames_idx == m_nodenames.size()) { + *result_out = c_fallback; + errorstream << "Resolver: no more nodes in list" << std::endl; return false; } content_t c; - std::string name = nri->nodenames.front(); - nri->nodenames.pop_front(); + std::string name = m_nodenames[m_nodenames_idx++]; - bool success = getId(name, c); + bool success = m_ndef->getId(name, c); if (!success && node_alt != "") { name = node_alt; - success = getId(name, c); + success = m_ndef->getId(name, c); } if (!success) { - errorstream << "Resolver: Failed to resolve node name '" << name + errorstream << "NodeResolver: failed to resolve node name '" << name << "'." << std::endl; c = c_fallback; } - result = c; + *result_out = c; return success; } -bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri, - std::vector &result) +bool NodeResolver::getIdsFromNrBacklog(std::vector *result_out, + bool all_required, content_t c_fallback) { bool success = true; - if (nri->nodelistinfo.empty()) { - errorstream << "Resolver: Empty nodelistinfo list" << std::endl; + if (m_nnlistsizes_idx == m_nnlistsizes.size()) { + errorstream << "NodeResolver: no more node lists" << std::endl; return false; } - NodeListInfo listinfo = nri->nodelistinfo.front(); - nri->nodelistinfo.pop_front(); + size_t length = m_nnlistsizes[m_nnlistsizes_idx++]; - while (listinfo.length--) { - if (nri->nodenames.empty()) { - errorstream << "Resolver: Empty nodename list" << std::endl; + while (length--) { + if (m_nodenames_idx == m_nodenames.size()) { + errorstream << "NodeResolver: no more nodes in list" << std::endl; return false; } content_t c; - std::string name = nri->nodenames.front(); - nri->nodenames.pop_front(); + std::string &name = m_nodenames[m_nodenames_idx++]; 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); + if (m_ndef->getId(name, c)) { + result_out->push_back(c); + } else if (all_required) { + errorstream << "NodeResolver: failed to resolve node name '" + << name << "'." << std::endl; + result_out->push_back(c_fallback); success = false; } } else { std::set cids; std::set::iterator it; - getIds(name, cids); + m_ndef->getIds(name, cids); for (it = cids.begin(); it != cids.end(); ++it) - result.push_back(*it); + result_out->push_back(*it); } } diff --git a/src/nodedef.h b/src/nodedef.h index dfd0f4f99..d9829c495 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -34,10 +34,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "sound.h" // SimpleSoundSpec #include "constants.h" // BS +class INodeDefManager; class IItemDefManager; class ITextureSource; class IShaderSource; class IGameDef; +class NodeResolver; typedef std::list > GroupItems; @@ -280,38 +282,10 @@ struct ContentFeatures } }; -class NodeResolver; -class INodeDefManager; - -struct NodeListInfo { - NodeListInfo(u32 len) - { - length = len; - all_required = false; - c_fallback = CONTENT_IGNORE; - } - - NodeListInfo(u32 len, content_t fallback) - { - length = len; - all_required = true; - c_fallback = fallback; - } - - u32 length; - bool all_required; - content_t c_fallback; -}; - -struct NodeResolveInfo { - NodeResolveInfo(NodeResolver *nr) - { - resolver = nr; - } - - std::list nodenames; - std::list nodelistinfo; - NodeResolver *resolver; +enum NodeResolveMethod { + NODE_RESOLVE_NONE, + NODE_RESOLVE_DIRECT, + NODE_RESOLVE_DEFERRED, }; class INodeDefManager @@ -334,14 +308,9 @@ public: virtual bool getNodeRegistrationStatus() const=0; virtual void setNodeRegistrationStatus(bool completed)=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; + virtual void pendNodeResolve(NodeResolver *nr, NodeResolveMethod how)=0; + virtual bool cancelNodeResolveCallback(NodeResolver *nr)=0; + virtual void runNodeResolveCallbacks()=0; }; class IWritableNodeDefManager : public INodeDefManager @@ -388,38 +357,34 @@ public: virtual bool getNodeRegistrationStatus() const=0; virtual void setNodeRegistrationStatus(bool completed)=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; + virtual void pendNodeResolve(NodeResolver *nr, NodeResolveMethod how)=0; + virtual bool cancelNodeResolveCallback(NodeResolver *nr)=0; + virtual void runNodeResolveCallbacks()=0; }; IWritableNodeDefManager *createNodeDefManager(); class NodeResolver { public: - NodeResolver() - { - m_lookup_done = false; - m_ndef = NULL; - } + NodeResolver(); + virtual ~NodeResolver(); + virtual void resolveNodeNames() = 0; - virtual ~NodeResolver() - { - if (!m_lookup_done && m_ndef) - m_ndef->cancelNodeResolve(this); - } + bool getIdFromNrBacklog(content_t *result_out, + const std::string &node_alt, content_t c_fallback); + bool getIdsFromNrBacklog(std::vector *result_out, + bool all_required=false, content_t c_fallback=CONTENT_IGNORE); + const std::string &getNodeName(content_t c) const; - virtual void resolveNodeNames(NodeResolveInfo *nri) = 0; + void nodeResolveInternal(); - bool m_lookup_done; + u32 m_nodenames_idx; + u32 m_nnlistsizes_idx; + std::vector m_nodenames; + std::vector m_nnlistsizes; INodeDefManager *m_ndef; + bool m_resolve_done; }; - #endif diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index 66eeec68e..5070dca2d 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -227,24 +227,28 @@ std::vector read_aabb3f_vector(lua_State *L, int index, f32 scale) return boxes; } -bool read_stringlist(lua_State *L, int index, std::vector &result) +size_t read_stringlist(lua_State *L, int index, std::vector *result) { if (index < 0) index = lua_gettop(L) + 1 + index; + size_t num_strings = 0; + if (lua_istable(L, index)) { lua_pushnil(L); while (lua_next(L, index)) { - if (lua_isstring(L, -1)) - result.push_back(lua_tostring(L, -1)); + if (lua_isstring(L, -1)) { + result->push_back(lua_tostring(L, -1)); + num_strings++; + } lua_pop(L, 1); } } else if (lua_isstring(L, index)) { - result.push_back(lua_tostring(L, index)); - } else { - return false; + result->push_back(lua_tostring(L, index)); + num_strings++; } - return true; + + return num_strings; } /* @@ -307,15 +311,15 @@ bool getboolfield(lua_State *L, int table, return got; } -bool getstringlistfield(lua_State *L, int table, const char *fieldname, - std::vector &result) +size_t getstringlistfield(lua_State *L, int table, const char *fieldname, + std::vector *result) { lua_getfield(L, table, fieldname); - bool got = read_stringlist(L, -1, result); + size_t num_strings_read = read_stringlist(L, -1, result); lua_pop(L, 1); - return got; + return num_strings_read; } std::string checkstringfield(lua_State *L, int table, diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index 3b7eb6f7d..fdcd0c8fc 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -48,9 +48,9 @@ int getintfield_default (lua_State *L, int table, bool getstringfield(lua_State *L, int table, const char *fieldname, std::string &result); -bool getstringlistfield(lua_State *L, int table, +size_t getstringlistfield(lua_State *L, int table, const char *fieldname, - std::vector &result); + std::vector *result); bool getintfield(lua_State *L, int table, const char *fieldname, int &result); void read_groups(lua_State *L, int index, @@ -83,8 +83,8 @@ video::SColor readARGB8 (lua_State *L, int index); aabb3f read_aabb3f (lua_State *L, int index, f32 scale); v3s16 read_v3s16 (lua_State *L, int index); std::vector read_aabb3f_vector (lua_State *L, int index, f32 scale); -bool read_stringlist (lua_State *L, int index, - std::vector &result); +size_t read_stringlist (lua_State *L, int index, + std::vector *result); void push_v3s16 (lua_State *L, v3s16 p); void pushFloatPos (lua_State *L, v3f p); diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index a34281fd2..953d80538 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -92,6 +92,14 @@ struct EnumString ModApiMapgen::es_SchematicFormatType[] = {0, NULL}, }; +struct EnumString ModApiMapgen::es_NodeResolveMethod[] = +{ + {NODE_RESOLVE_NONE, "none"}, + {NODE_RESOLVE_DIRECT, "direct"}, + {NODE_RESOLVE_DEFERRED, "deferred"}, + {0, NULL}, +}; + ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr); Biome *get_or_load_biome(lua_State *L, int index, @@ -101,19 +109,23 @@ size_t get_biome_list(lua_State *L, int index, BiomeManager *biomemgr, std::set *biome_id_list); Schematic *get_or_load_schematic(lua_State *L, int index, - SchematicManager *schemmgr, StringMap *replace_names); -Schematic *read_schematic_def(lua_State *L, int index, - INodeDefManager *ndef, StringMap *replace_names); -Schematic *load_schematic(lua_State *L, int index, - SchematicManager *schemmgr, StringMap *replace_names); + SchematicManager *schemmgr, StringMap *replace_names, + bool register_on_load=true, + NodeResolveMethod resolve_method=NODE_RESOLVE_DEFERRED); +Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef, + StringMap *replace_names, NodeResolveMethod resolve_method); +Schematic *load_schematic_from_def(lua_State *L, int index, + INodeDefManager *ndef, StringMap *replace_names, + NodeResolveMethod resolve_method); +bool read_schematic_def(lua_State *L, int index, + Schematic *schem, std::vector *names); -bool read_deco_simple(lua_State *L, NodeResolveInfo *nri, DecoSimple *deco); +bool read_deco_simple(lua_State *L, DecoSimple *deco); bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco); /////////////////////////////////////////////////////////////////////////////// - ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr) { if (index < 0) @@ -130,17 +142,48 @@ ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr) return NULL; } +/////////////////////////////////////////////////////////////////////////////// -Schematic *load_schematic(lua_State *L, int index, - SchematicManager *schemmgr, StringMap *replace_names) +Schematic *get_or_load_schematic(lua_State *L, int index, + SchematicManager *schemmgr, StringMap *replace_names, + bool register_on_load, + NodeResolveMethod resolve_method) { if (index < 0) index = lua_gettop(L) + 1 + index; - Schematic *schem; + Schematic *schem = (Schematic *)get_objdef(L, index, schemmgr); + if (schem) + return schem; + + schem = load_schematic(L, index, schemmgr->getNodeDef(), + replace_names, resolve_method); + if (!schem) + return NULL; + + if (!register_on_load) + return schem; + + if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) { + delete schem; + return NULL; + } + + return schem; +} + + +Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef, + StringMap *replace_names, NodeResolveMethod resolve_method) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + Schematic *schem = NULL; if (lua_istable(L, index)) { - schem = read_schematic_def(L, index, schemmgr->getNodeDef(), replace_names); + schem = load_schematic_from_def(L, index, ndef, + replace_names, resolve_method); if (!schem) { delete schem; return NULL; @@ -154,19 +197,166 @@ Schematic *load_schematic(lua_State *L, int index, if (!fs::IsPathAbsolute(filepath)) filepath = ModApiBase::getCurrentModPath(L) + DIR_DELIM + filepath; - if (!schem->loadSchematicFromFile(filepath.c_str(), - schemmgr->getNodeDef(), replace_names)) { + if (!schem->loadSchematicFromFile(filepath, ndef, + replace_names, resolve_method)) { delete schem; return NULL; } - } else { - return NULL; } return schem; } +Schematic *load_schematic_from_def(lua_State *L, int index, INodeDefManager *ndef, + StringMap *replace_names, NodeResolveMethod resolve_method) +{ + Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL); + + if (!read_schematic_def(L, index, schem, &schem->m_nodenames)) { + delete schem; + return NULL; + } + + size_t num_nodes = schem->m_nodenames.size(); + + schem->m_nnlistsizes.push_back(num_nodes); + + if (replace_names) { + for (size_t i = 0; i != num_nodes; i++) { + StringMap::iterator it = replace_names->find(schem->m_nodenames[i]); + if (it != replace_names->end()) + schem->m_nodenames[i] = it->second; + } + } + + ndef->pendNodeResolve(schem, resolve_method); + + return schem; +} + + +bool read_schematic_def(lua_State *L, int index, + Schematic *schem, std::vector *names) +{ + if (!lua_istable(L, index)) + return false; + + //// Get schematic size + lua_getfield(L, index, "size"); + v3s16 size = read_v3s16(L, -1); + lua_pop(L, 1); + + schem->size = size; + + //// Get schematic data + lua_getfield(L, index, "data"); + luaL_checktype(L, -1, LUA_TTABLE); + + int numnodes = size.X * size.Y * size.Z; + schem->schemdata = new MapNode[numnodes]; + int i = 0; + + size_t names_base = names->size(); + std::map name_id_map; + + lua_pushnil(L); + while (lua_next(L, -2)) { + if (i >= numnodes) { + i++; + lua_pop(L, 1); + continue; + } + + // same as readnode, except param1 default is MTSCHEM_PROB_CONST + lua_getfield(L, -1, "name"); + std::string name = luaL_checkstring(L, -1); + lua_pop(L, 1); + + u8 param1; + lua_getfield(L, -1, "param1"); + param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS; + lua_pop(L, 1); + + u8 param2; + lua_getfield(L, -1, "param2"); + param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; + lua_pop(L, 1); + + std::map::iterator it = name_id_map.find(name); + content_t name_index; + if (it != name_id_map.end()) { + name_index = it->second; + } else { + name_index = names->size() - names_base; + name_id_map[name] = name_index; + names->push_back(name); + } + + schem->schemdata[i] = MapNode(name_index, param1, param2); + + i++; + lua_pop(L, 1); + } + + if (i != numnodes) { + errorstream << "read_schematic_def: incorrect number of " + "nodes provided in raw schematic data (got " << i << + ", expected " << numnodes << ")." << std::endl; + return false; + } + + //// Get Y-slice probability values (if present) + schem->slice_probs = new u8[size.Y]; + for (i = 0; i != size.Y; i++) + schem->slice_probs[i] = MTSCHEM_PROB_ALWAYS; + + lua_getfield(L, index, "yslice_prob"); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2)) { + if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) { + schem->slice_probs[i] = getintfield_default(L, -1, + "prob", MTSCHEM_PROB_ALWAYS); + } + lua_pop(L, 1); + } + } + + return true; +} + + +void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + lua_pushnil(L); + while (lua_next(L, index)) { + std::string replace_from; + std::string replace_to; + + if (lua_istable(L, -1)) { // Old {{"x", "y"}, ...} format + lua_rawgeti(L, -1, 1); + replace_from = lua_tostring(L, -1); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 2); + replace_to = lua_tostring(L, -1); + lua_pop(L, 1); + } else { // New {x = "y", ...} format + replace_from = lua_tostring(L, -2); + replace_to = lua_tostring(L, -1); + } + + replace_names->insert(std::make_pair(replace_from, replace_to)); + lua_pop(L, 1); + } +} + +/////////////////////////////////////////////////////////////////////////////// + Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr) { if (index < 0) @@ -208,15 +398,14 @@ Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef) b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f); b->flags = 0; //reserved - 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_top", "")); - nnames.push_back(getstringfield_default(L, index, "node_water", "")); - nnames.push_back(getstringfield_default(L, index, "node_dust", "")); - ndef->pendNodeResolve(nri); + std::vector &nn = b->m_nodenames; + nn.push_back(getstringfield_default(L, index, "node_top", "")); + nn.push_back(getstringfield_default(L, index, "node_filler", "")); + nn.push_back(getstringfield_default(L, index, "node_stone", "")); + nn.push_back(getstringfield_default(L, index, "node_water_top", "")); + nn.push_back(getstringfield_default(L, index, "node_water", "")); + nn.push_back(getstringfield_default(L, index, "node_dust", "")); + ndef->pendNodeResolve(b, NODE_RESOLVE_DEFERRED); return b; } @@ -269,154 +458,8 @@ size_t get_biome_list(lua_State *L, int index, return fail_count; } - -Schematic *get_or_load_schematic(lua_State *L, int index, - SchematicManager *schemmgr, StringMap *replace_names) -{ - if (index < 0) - index = lua_gettop(L) + 1 + index; - - Schematic *schem = (Schematic *)get_objdef(L, index, schemmgr); - if (schem) - return schem; - - schem = load_schematic(L, index, schemmgr, replace_names); - if (!schem) - return NULL; - - if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) { - delete schem; - return NULL; - } - - return schem; -} - - -Schematic *read_schematic_def(lua_State *L, int index, - INodeDefManager *ndef, StringMap *replace_names) -{ - if (!lua_istable(L, index)) - return NULL; - - //// Get schematic size - lua_getfield(L, index, "size"); - v3s16 size = read_v3s16(L, -1); - lua_pop(L, 1); - - //// Get schematic data - lua_getfield(L, index, "data"); - luaL_checktype(L, -1, LUA_TTABLE); - - int numnodes = size.X * size.Y * size.Z; - MapNode *schemdata = new MapNode[numnodes]; - int i = 0; - - lua_pushnil(L); - while (lua_next(L, -2)) { - if (i >= numnodes) { - i++; - lua_pop(L, 1); - continue; - } - - // same as readnode, except param1 default is MTSCHEM_PROB_CONST - lua_getfield(L, -1, "name"); - std::string name = luaL_checkstring(L, -1); - lua_pop(L, 1); - - u8 param1; - lua_getfield(L, -1, "param1"); - param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS; - lua_pop(L, 1); - - u8 param2; - lua_getfield(L, -1, "param2"); - param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; - lua_pop(L, 1); - - if (replace_names) { - StringMap::iterator it = replace_names->find(name); - if (it != replace_names->end()) - name = it->second; - } - - schemdata[i] = MapNode(ndef, name, param1, param2); - - i++; - lua_pop(L, 1); - } - - if (i != numnodes) { - errorstream << "read_schematic: incorrect number of " - "nodes provided in raw schematic data (got " << i << - ", expected " << numnodes << ")." << std::endl; - delete schemdata; - return NULL; - } - - //// Get Y-slice probability values (if present) - u8 *slice_probs = new u8[size.Y]; - for (i = 0; i != size.Y; i++) - slice_probs[i] = MTSCHEM_PROB_ALWAYS; - - lua_getfield(L, index, "yslice_prob"); - if (lua_istable(L, -1)) { - lua_pushnil(L); - while (lua_next(L, -2)) { - if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) { - slice_probs[i] = getintfield_default(L, -1, - "prob", MTSCHEM_PROB_ALWAYS); - } - lua_pop(L, 1); - } - } - - Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL); - - // Here, we read the nodes directly from the INodeDefManager - there is no - // need for pending node resolutions so we'll mark this schematic as updated - schem->flags = SCHEM_CIDS_UPDATED; - - schem->size = size; - schem->schemdata = schemdata; - schem->slice_probs = slice_probs; - return schem; -} - - -void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names) -{ - if (index < 0) - index = lua_gettop(L) + 1 + index; - - lua_pushnil(L); - while (lua_next(L, index)) { - std::string replace_from; - std::string replace_to; - - if (lua_istable(L, -1)) { // Old {{"x", "y"}, ...} format - lua_rawgeti(L, -1, 1); - replace_from = lua_tostring(L, -1); - lua_pop(L, 1); - - lua_rawgeti(L, -1, 2); - replace_to = lua_tostring(L, -1); - lua_pop(L, 1); - } else { // New {x = "y", ...} format - replace_from = lua_tostring(L, -2); - replace_to = lua_tostring(L, -1); - } - - replace_names->insert(std::make_pair(replace_from, replace_to)); - lua_pop(L, 1); - } -} - - /////////////////////////////////////////////////////////////////////////////// - // get_mapgen_object(objectname) // returns the requested object used during map generation int ModApiMapgen::l_get_mapgen_object(lua_State *L) @@ -689,15 +732,11 @@ 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->nodelistinfo.push_back(NodeListInfo(place_on_names.size())); - for (size_t i = 0; i != place_on_names.size(); i++) - nri->nodenames.push_back(place_on_names[i]); + size_t nread = getstringlistfield(L, index, "place_on", &deco->m_nodenames); + deco->m_nnlistsizes.push_back(nread); + //// Get decoration flags getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL); //// Get NoiseParams to define how decoration is placed @@ -716,7 +755,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) bool success = false; switch (decotype) { case DECO_SIMPLE: - success = read_deco_simple(L, nri, (DecoSimple *)deco); + success = read_deco_simple(L, (DecoSimple *)deco); break; case DECO_SCHEMATIC: success = read_deco_schematic(L, schemmgr, (DecoSchematic *)deco); @@ -725,13 +764,13 @@ int ModApiMapgen::l_register_decoration(lua_State *L) break; } - ndef->pendNodeResolve(nri); - if (!success) { delete deco; return 0; } + ndef->pendNodeResolve(deco, NODE_RESOLVE_DEFERRED); + ObjDefHandle handle = decomgr->add(deco); if (handle == OBJDEF_INVALID_HANDLE) { delete deco; @@ -743,8 +782,9 @@ int ModApiMapgen::l_register_decoration(lua_State *L) } -bool read_deco_simple(lua_State *L, NodeResolveInfo *nri, DecoSimple *deco) +bool read_deco_simple(lua_State *L, DecoSimple *deco) { + size_t nnames; int index = 1; deco->deco_height = getintfield_default(L, index, "height", 1); @@ -757,27 +797,21 @@ bool read_deco_simple(lua_State *L, NodeResolveInfo *nri, DecoSimple *deco) return false; } - std::vector deco_names; - getstringlistfield(L, index, "decoration", deco_names); - if (deco_names.size() == 0) { + nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames); + deco->m_nnlistsizes.push_back(nnames); + if (nnames == 0) { errorstream << "register_decoration: no decoration nodes " "defined" << std::endl; return false; } - nri->nodelistinfo.push_back(NodeListInfo(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); - if (deco->nspawnby != -1 && spawnby_names.size() == 0) { + nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames); + deco->m_nnlistsizes.push_back(nnames); + if (nnames == 0 && deco->nspawnby != -1) { errorstream << "register_decoration: no spawn_by nodes defined," " but num_spawn_by specified" << std::endl; return false; } - nri->nodelistinfo.push_back(NodeListInfo(spawnby_names.size())); - for (size_t i = 0; i != spawnby_names.size(); i++) - nri->nodenames.push_back(spawnby_names[i]); return true; } @@ -878,16 +912,12 @@ int ModApiMapgen::l_register_ore(lua_State *L) return 0; } - NodeResolveInfo *nri = new NodeResolveInfo(ore); - nri->nodenames.push_back(getstringfield_default(L, index, "ore", "")); + ore->m_nodenames.push_back(getstringfield_default(L, index, "ore", "")); - std::vector wherein_names; - getstringlistfield(L, index, "wherein", wherein_names); - nri->nodelistinfo.push_back(NodeListInfo(wherein_names.size())); - for (size_t i = 0; i != wherein_names.size(); i++) - nri->nodenames.push_back(wherein_names[i]); + size_t nnames = getstringlistfield(L, index, "wherein", &ore->m_nodenames); + ore->m_nnlistsizes.push_back(nnames); - ndef->pendNodeResolve(nri); + ndef->pendNodeResolve(ore, NODE_RESOLVE_DEFERRED); lua_pushinteger(L, handle); return 1; @@ -903,7 +933,8 @@ int ModApiMapgen::l_register_schematic(lua_State *L) if (lua_istable(L, 2)) read_schematic_replacements(L, 2, &replace_names); - Schematic *schem = load_schematic(L, 1, schemmgr, &replace_names); + Schematic *schem = load_schematic(L, 1, schemmgr->getNodeDef(), + &replace_names, NODE_RESOLVE_DEFERRED); if (!schem) return 0; @@ -1055,7 +1086,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L) schem.applyProbabilities(p1, &prob_list, &slice_prob_list); - schem.saveSchematicToFile(filename, ndef); + schem.saveSchematicToFile(filename); actionstream << "create_schematic: saved schematic file '" << filename << "'." << std::endl; @@ -1103,14 +1134,20 @@ int ModApiMapgen::l_place_schematic(lua_State *L) return 1; } -// serialize_schematic(schematic, format, use_comments) +// serialize_schematic(schematic, format, options={...}) int ModApiMapgen::l_serialize_schematic(lua_State *L) { SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + + //// Read options + NodeResolveMethod resolve_method = (NodeResolveMethod)getenumfield(L, 3, + "node_resolve_method", es_NodeResolveMethod, NODE_RESOLVE_NONE); + bool register_on_load = getboolfield_default(L, 3, "register_on_load", false); + bool use_comments = getboolfield_default(L, 3, "use_lua_comments", false); //// Read schematic - Schematic *schem = get_or_load_schematic(L, 1, schemmgr, NULL); + Schematic *schem = get_or_load_schematic(L, 1, schemmgr, NULL, + register_on_load, resolve_method); if (!schem) { errorstream << "serialize_schematic: failed to get schematic" << std::endl; return 0; @@ -1122,19 +1159,14 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L) if (enumstr) string_to_enum(es_SchematicFormatType, schem_format, std::string(enumstr)); - //// Read use_comments - bool use_comments = false; - if (lua_isboolean(L, 3)) - use_comments = lua_toboolean(L, 3); - //// Serialize to binary string std::ostringstream os(std::ios_base::binary); switch (schem_format) { case SCHEM_FMT_MTS: - schem->serializeToMts(&os, ndef); + schem->serializeToMts(&os); break; case SCHEM_FMT_LUA: - schem->serializeToLua(&os, ndef, use_comments); + schem->serializeToLua(&os, use_comments); break; default: return 0; diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index a54fcd7a8..84e556f63 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -22,12 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" -class INodeDefManager; -struct NodeResolveInfo; -class DecoSimple; -class DecoSchematic; -class SchematicManager; - class ModApiMapgen : public ModApiBase { private: // get_mapgen_object(objectname) @@ -84,7 +78,7 @@ private: // place_schematic(p, schematic, rotation, replacement) static int l_place_schematic(lua_State *L); - // serialize_schematic(schematic, format, use_comments) + // serialize_schematic(schematic, format, options={...}) static int l_serialize_schematic(lua_State *L); public: @@ -96,6 +90,7 @@ public: static struct EnumString es_OreType[]; static struct EnumString es_Rotation[]; static struct EnumString es_SchematicFormatType[]; + static struct EnumString es_NodeResolveMethod[]; }; #endif /* L_MAPGEN_H_ */ diff --git a/src/server.cpp b/src/server.cpp index 4d5938205..e8fdea7d1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -332,7 +332,7 @@ Server::Server( m_nodedef->setNodeRegistrationStatus(true); // Perform pending node name resolutions - m_nodedef->runNodeResolverCallbacks(); + m_nodedef->runNodeResolveCallbacks(); // init the recipe hashes to speed up crafting m_craftdef->initHashes(this);