mirror of
https://github.com/minetest/minetest.git
synced 2024-08-18 20:44:16 +02:00
Schematics: Refactor NodeResolver and add NodeResolveMethod
NodeResolver name lists now belong to the NodeResolver object instead of the associated NodeDefManager. In addition to minimizing unnecessary abstraction and overhead, this move permits NodeResolvers to look up nodes that they had previously set pending for resolution. So far, this functionality has been used in the case of schematics for serialization/deserialization.
This commit is contained in:
parent
0c634a9719
commit
479f38973e
@ -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`
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
float heat_point;
|
||||
float humidity_point;
|
||||
|
||||
virtual void resolveNodeNames(NodeResolveInfo *nri);
|
||||
virtual void resolveNodeNames();
|
||||
};
|
||||
|
||||
class BiomeManager : public ObjDefManager {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
203
src/nodedef.cpp
203
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;
|
||||
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<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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<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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
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<content_t> *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<std::string> m_nodenames;
|
||||
std::vector<size_t> m_nnlistsizes;
|
||||
INodeDefManager *m_ndef;
|
||||
bool m_resolve_done;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
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, 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<std::string> *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<std::string, content_t> 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<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);
|
||||
}
|
||||
|
||||
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<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);
|
||||
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;
|
||||
}
|
||||
@ -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<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;
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user