Skip to content

Commit

Permalink
Schematics: Refactor NodeResolver and add NodeResolveMethod
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kwolekr committed Apr 16, 2015
1 parent 0c634a9 commit 479f389
Show file tree
Hide file tree
Showing 17 changed files with 470 additions and 435 deletions.
17 changes: 13 additions & 4 deletions doc/lua_api.txt
Expand Up @@ -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`
Expand Down
4 changes: 2 additions & 2 deletions src/client.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
29 changes: 14 additions & 15 deletions src/mg_biome.cpp
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}

2 changes: 1 addition & 1 deletion src/mg_biome.h
Expand Up @@ -53,7 +53,7 @@ class Biome : public ObjDef, public NodeResolver {
float heat_point;
float humidity_point;

virtual void resolveNodeNames(NodeResolveInfo *nri);
virtual void resolveNodeNames();
};

class BiomeManager : public ObjDefManager {
Expand Down
12 changes: 6 additions & 6 deletions src/mg_decoration.cpp
Expand Up @@ -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);
}


Expand Down Expand Up @@ -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);
}


Expand Down
4 changes: 2 additions & 2 deletions src/mg_decoration.h
Expand Up @@ -79,7 +79,7 @@ class Decoration : public ObjDef, public NodeResolver {
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);
Expand All @@ -96,7 +96,7 @@ class DecoSimple : public Decoration {
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);
Expand Down
6 changes: 3 additions & 3 deletions src/mg_ore.cpp
Expand Up @@ -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);
}


Expand Down
2 changes: 1 addition & 1 deletion src/mg_ore.h
Expand Up @@ -67,7 +67,7 @@ class Ore : public ObjDef, public NodeResolver {
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,
Expand Down
64 changes: 28 additions & 36 deletions src/mg_schematic.cpp
Expand Up @@ -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);
}
}


Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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,
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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()) {
Expand All @@ -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());
}

Expand Down
18 changes: 7 additions & 11 deletions src/mg_schematic.h
Expand Up @@ -94,32 +94,28 @@ class Schematic : public ObjDef, public NodeResolver {
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,
Rotation rot, bool force_placement, INodeDefManager *nef);
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 {
Expand Down

0 comments on commit 479f389

Please sign in to comment.