aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt17
-rw-r--r--src/client.cpp4
-rw-r--r--src/mg_biome.cpp29
-rw-r--r--src/mg_biome.h2
-rw-r--r--src/mg_decoration.cpp12
-rw-r--r--src/mg_decoration.h4
-rw-r--r--src/mg_ore.cpp6
-rw-r--r--src/mg_ore.h2
-rw-r--r--src/mg_schematic.cpp64
-rw-r--r--src/mg_schematic.h18
-rw-r--r--src/nodedef.cpp185
-rw-r--r--src/nodedef.h93
-rw-r--r--src/script/common/c_converter.cpp26
-rw-r--r--src/script/common/c_converter.h8
-rw-r--r--src/script/lua_api/l_mapgen.cpp424
-rw-r--r--src/script/lua_api/l_mapgen.h9
-rw-r--r--src/server.cpp2
17 files changed, 470 insertions, 435 deletions
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<std::string> *names)
+bool Schematic::deserializeFromMts(std::istream *is, std::vector<std::string> *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<std::string> 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<std::string> *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<std::string> *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<std::pair<v3s16, u8> > *plist,
std::vector<std::pair<s16, u8> > *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<content_t> &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<NodeResolveInfo *> m_pending_node_lookups;
+ // NodeResolvers to callback once node registration has ended
+ std::vector<NodeResolver *> 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<NodeResolveInfo *>::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;
- } else {
- m_pending_node_lookups.push_back(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;
}
}
-void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver)
+bool CNodeDefManager::cancelNodeResolveCallback(NodeResolver *nr)
{
- 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;
- }
+ 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 CNodeDefManager::runNodeResolverCallbacks()
+void NodeResolver::nodeResolveInternal()
{
- 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;
+ 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 {
+ if (c < m_nodenames.size())
+ return m_nodenames[c];
+ else
+ return m_ndef->get(CONTENT_UNKNOWN).name;
}
}
-bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri,
- const std::string &node_alt, content_t c_fallback, content_t &result)
+bool NodeResolver::getIdFromNrBacklog(content_t *result_out,
+ const std::string &node_alt, content_t c_fallback)
{
- 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<content_t> &result)
+bool NodeResolver::getIdsFromNrBacklog(std::vector<content_t> *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<content_t> cids;
std::set<content_t>::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<std::pair<content_t, int> > 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<std::string> nodenames;
- std::list<NodeListInfo> 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<content_t> &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<content_t> &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;
- }
-
- virtual ~NodeResolver()
- {
- if (!m_lookup_done && m_ndef)
- m_ndef->cancelNodeResolve(this);
- }
-
- virtual void resolveNodeNames(NodeResolveInfo *nri) = 0;
-
- bool m_lookup_done;
+ NodeResolver();
+ virtual ~NodeResolver();
+ virtual void resolveNodeNames() = 0;
+
+ bool getIdFromNrBacklog(content_t *result_out,
+ const std::string &node_alt, content_t c_fallback);
+ bool getIdsFromNrBacklog(std::vector<content_t> *result_out,
+ bool all_required=false, content_t c_fallback=CONTENT_IGNORE);
+ const std::string &getNodeName(content_t c) const;
+
+ void nodeResolveInternal();
+
+ u32 m_nodenames_idx;
+ u32 m_nnlistsizes_idx;
+ std::vector<std::string> m_nodenames;
+ std::vector<size_t> 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<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
return boxes;
}
-bool read_stringlist(lua_State *L, int index, std::vector<const char *> &result)
+size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *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<const char *> &result)
+size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
+ std::vector<std::string> *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<const char *> &result);
+ std::vector<std::string> *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<aabb3f> read_aabb3f_vector (lua_State *L, int index, f32 scale);
-bool read_stringlist (lua_State *L, int index,
- std::vector<const char *> &result);
+size_t read_stringlist (lua_State *L, int index,
+ std::vector<std::string> *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<u8> *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);
-
-bool read_deco_simple(lua_State *L, NodeResolveInfo *nri, DecoSimple *deco);
+ 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<std::string> *names);
+
+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,164 +197,69 @@ 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;
}
-Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr)
+Schematic *load_schematic_from_def(lua_State *L, int index, INodeDefManager *ndef,
+ StringMap *replace_names, NodeResolveMethod resolve_method)
{
- if (index < 0)
- index = lua_gettop(L) + 1 + index;
-
- Biome *biome = (Biome *)get_objdef(L, index, biomemgr);
- if (biome)
- return biome;
-
- biome = read_biome_def(L, index, biomemgr->getNodeDef());
- if (!biome)
- return NULL;
-
- if (biomemgr->add(biome) == OBJDEF_INVALID_HANDLE) {
- delete biome;
- return NULL;
- }
-
- return biome;
-}
-
+ Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL);
-Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
-{
- if (!lua_istable(L, index))
+ if (!read_schematic_def(L, index, schem, &schem->m_nodenames)) {
+ delete schem;
return NULL;
-
- BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
- ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL);
- Biome *b = BiomeManager::create(biometype);
-
- b->name = getstringfield_default(L, index, "name", "");
- b->depth_top = getintfield_default(L, index, "depth_top", 1);
- b->depth_filler = getintfield_default(L, index, "depth_filler", 2);
- b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0);
- b->y_min = getintfield_default(L, index, "y_min", -31000);
- b->y_max = getintfield_default(L, index, "y_max", 31000);
- b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
- b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
- b->flags = 0; //reserved
-
- 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_top", ""));
- nnames.push_back(getstringfield_default(L, index, "node_water", ""));
- nnames.push_back(getstringfield_default(L, index, "node_dust", ""));
- ndef->pendNodeResolve(nri);
-
- return b;
-}
-
-
-size_t get_biome_list(lua_State *L, int index,
- BiomeManager *biomemgr, std::set<u8> *biome_id_list)
-{
- if (index < 0)
- index = lua_gettop(L) + 1 + index;
-
- if (lua_isnil(L, index))
- return 0;
-
- bool is_single = true;
- if (lua_istable(L, index)) {
- lua_getfield(L, index, "name");
- is_single = !lua_isnil(L, -1);
- lua_pop(L, 1);
}
- if (is_single) {
- Biome *biome = get_or_load_biome(L, index, biomemgr);
- if (!biome) {
- errorstream << "get_biome_list: failed to get biome" << std::endl;
- return 1;
- }
-
- biome_id_list->insert(biome->index);
- return 0;
- }
+ size_t num_nodes = schem->m_nodenames.size();
- // returns number of failed resolutions
- size_t fail_count = 0;
- size_t count = 0;
+ schem->m_nnlistsizes.push_back(num_nodes);
- for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) {
- count++;
- Biome *biome = get_or_load_biome(L, -1, biomemgr);
- if (!biome) {
- fail_count++;
- errorstream << "get_biome_list: failed to load biome (index "
- << count << ")" << std::endl;
- continue;
+ 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;
}
-
- biome_id_list->insert(biome->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;
- }
+ ndef->pendNodeResolve(schem, resolve_method);
return schem;
}
-Schematic *read_schematic_def(lua_State *L, int index,
- INodeDefManager *ndef, StringMap *replace_names)
+bool read_schematic_def(lua_State *L, int index,
+ Schematic *schem, std::vector<std::string> *names)
{
if (!lua_istable(L, index))
- return NULL;
+ 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;
- MapNode *schemdata = new MapNode[numnodes];
+ schem->schemdata = new MapNode[numnodes];
int i = 0;
+ size_t names_base = names->size();
+ std::map<std::string, content_t> name_id_map;
+
lua_pushnil(L);
while (lua_next(L, -2)) {
if (i >= numnodes) {
@@ -335,53 +283,47 @@ Schematic *read_schematic_def(lua_State *L, int index,
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;
+ std::map<std::string, content_t>::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);
}
- schemdata[i] = MapNode(ndef, name, param1, param2);
+ schem->schemdata[i] = MapNode(name_index, param1, param2);
i++;
lua_pop(L, 1);
}
if (i != numnodes) {
- errorstream << "read_schematic: incorrect number of "
+ errorstream << "read_schematic_def: incorrect number of "
"nodes provided in raw schematic data (got " << i <<
", expected " << numnodes << ")." << std::endl;
- delete schemdata;
- return NULL;
+ return false;
}
//// Get Y-slice probability values (if present)
- u8 *slice_probs = new u8[size.Y];
+ schem->slice_probs = new u8[size.Y];
for (i = 0; i != size.Y; i++)
- slice_probs[i] = MTSCHEM_PROB_ALWAYS;
+ 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) {
- slice_probs[i] = getintfield_default(L, -1,
+ schem->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;
+ return true;
}
@@ -413,9 +355,110 @@ void read_schematic_replacements(lua_State *L, int index, StringMap *replace_nam
}
}
-
///////////////////////////////////////////////////////////////////////////////
+Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ Biome *biome = (Biome *)get_objdef(L, index, biomemgr);
+ if (biome)
+ return biome;
+
+ biome = read_biome_def(L, index, biomemgr->getNodeDef());
+ if (!biome)
+ return NULL;
+
+ if (biomemgr->add(biome) == OBJDEF_INVALID_HANDLE) {
+ delete biome;
+ return NULL;
+ }
+
+ return biome;
+}
+
+
+Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
+{
+ if (!lua_istable(L, index))
+ return NULL;
+
+ BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
+ ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL);
+ Biome *b = BiomeManager::create(biometype);
+
+ b->name = getstringfield_default(L, index, "name", "");
+ b->depth_top = getintfield_default(L, index, "depth_top", 1);
+ b->depth_filler = getintfield_default(L, index, "depth_filler", 2);
+ b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0);
+ b->y_min = getintfield_default(L, index, "y_min", -31000);
+ b->y_max = getintfield_default(L, index, "y_max", 31000);
+ b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
+ b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
+ b->flags = 0; //reserved
+
+ std::vector<std::string> &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;
+}
+
+
+size_t get_biome_list(lua_State *L, int index,
+ BiomeManager *biomemgr, std::set<u8> *biome_id_list)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ if (lua_isnil(L, index))
+ return 0;
+
+ bool is_single = true;
+ if (lua_istable(L, index)) {
+ lua_getfield(L, index, "name");
+ is_single = !lua_isnil(L, -1);
+ lua_pop(L, 1);
+ }
+
+ if (is_single) {
+ Biome *biome = get_or_load_biome(L, index, biomemgr);
+ if (!biome) {
+ errorstream << "get_biome_list: failed to get biome" << std::endl;
+ return 1;
+ }
+
+ biome_id_list->insert(biome->index);
+ return 0;
+ }
+
+ // returns number of failed resolutions
+ size_t fail_count = 0;
+ size_t count = 0;
+
+ for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) {
+ count++;
+ Biome *biome = get_or_load_biome(L, -1, biomemgr);
+ if (!biome) {
+ fail_count++;
+ errorstream << "get_biome_list: failed to load biome (index "
+ << count << ")" << std::endl;
+ continue;
+ }
+
+ biome_id_list->insert(biome->index);
+ }
+
+ return fail_count;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// get_mapgen_object(objectname)
// returns the requested object used during map generation
@@ -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<const char *> 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<const char *> 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<const char *> 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<const char *> 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);