Redefine NodeResolver interface and replace with callback mechanism

This commit is contained in:
kwolekr 2014-12-17 03:20:17 -05:00
parent 3ea5ed4ffe
commit b67f37f27e
16 changed files with 278 additions and 364 deletions

@ -384,7 +384,7 @@ void GenerateNotifier::getEvents(
GenElementManager::GenElementManager(IGameDef *gamedef)
{
m_resolver = gamedef->getNodeDefManager()->getResolver();
m_ndef = gamedef->getNodeDefManager();
}

@ -192,7 +192,7 @@ public:
virtual GenElement *getByName(const std::string &name);
protected:
NodeResolver *m_resolver;
INodeDefManager *m_ndef;
std::vector<GenElement *> m_elements;
};

@ -48,12 +48,14 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
b->heat_point = 0.0;
b->humidity_point = 0.0;
m_resolver->addNode("air", "", CONTENT_AIR, &b->c_top);
m_resolver->addNode("air", "", CONTENT_AIR, &b->c_filler);
m_resolver->addNode("mapgen_stone", "", CONTENT_AIR, &b->c_stone);
m_resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_water);
m_resolver->addNode("air", "", CONTENT_AIR, &b->c_dust);
m_resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water);
NodeResolveInfo *nri = new NodeResolveInfo(b);
nri->nodenames.push_back("air");
nri->nodenames.push_back("air");
nri->nodenames.push_back("mapgen_stone");
nri->nodenames.push_back("mapgen_water_source");
nri->nodenames.push_back("air");
nri->nodenames.push_back("mapgen_water_source");
m_ndef->pendNodeResolve(nri);
add(b);
}
@ -102,18 +104,26 @@ Biome *BiomeManager::getBiome(float heat, float humidity, s16 y)
void BiomeManager::clear()
{
for (size_t i = 1; i < m_elements.size(); i++) {
Biome *b = (Biome *)m_elements[i];
if (!b)
continue;
m_resolver->cancelNode(&b->c_top);
m_resolver->cancelNode(&b->c_filler);
m_resolver->cancelNode(&b->c_stone);
m_resolver->cancelNode(&b->c_water);
m_resolver->cancelNode(&b->c_dust);
m_resolver->cancelNode(&b->c_dust_water);
delete b;
}
m_elements.resize(1);
}
///////////////////////////////////////////////////////////////////////////////
void Biome::resolveNodeNames(NodeResolveInfo *nri)
{
m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt_with_grass", CONTENT_AIR, c_top);
m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt", CONTENT_AIR, c_filler);
m_ndef->getIdFromResolveInfo(nri, "mapgen_stone", CONTENT_AIR, c_stone);
m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water);
m_ndef->getIdFromResolveInfo(nri, "air", CONTENT_IGNORE, c_dust);
m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_IGNORE, c_dust_water);
}

@ -33,7 +33,7 @@ enum BiomeType
BIOME_TYPE_FLAT
};
class Biome : public GenElement {
class Biome : public GenElement, public NodeResolver {
public:
u32 flags;
@ -51,6 +51,8 @@ public:
s16 height_max;
float heat_point;
float humidity_point;
virtual void resolveNodeNames(NodeResolveInfo *nri);
};
class BiomeManager : public GenElementManager {

@ -65,10 +65,7 @@ void DecorationManager::clear()
{
for (size_t i = 0; i < m_elements.size(); i++) {
Decoration *deco = (Decoration *)m_elements[i];
if (!deco)
continue;
deco->dropResolverEntries(m_resolver);
delete deco;
}
m_elements.clear();
}
@ -91,6 +88,12 @@ Decoration::~Decoration()
}
void Decoration::resolveNodeNames(NodeResolveInfo *nri)
{
m_ndef->getIdsFromResolveInfo(nri, c_place_on);
}
size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
{
PseudoRandom ps(blockseed + 53);
@ -229,6 +232,14 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
///////////////////////////////////////////////////////////////////////////////
void DecoSimple::resolveNodeNames(NodeResolveInfo *nri)
{
Decoration::resolveNodeNames(nri);
m_ndef->getIdsFromResolveInfo(nri, c_decos);
m_ndef->getIdsFromResolveInfo(nri, c_spawnby);
}
bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p)
{
// Don't bother if there aren't any decorations to place
@ -310,13 +321,6 @@ int DecoSimple::getHeight()
}
void DecoSimple::dropResolverEntries(NodeResolver *resolver)
{
resolver->cancelNodeList(&c_decos);
resolver->cancelNodeList(&c_spawnby);
}
///////////////////////////////////////////////////////////////////////////////

@ -58,7 +58,7 @@ struct CutoffData {
};
#endif
class Decoration : public GenElement {
class Decoration : public GenElement, public NodeResolver {
public:
INodeDefManager *ndef;
@ -76,12 +76,13 @@ public:
Decoration();
virtual ~Decoration();
virtual void resolveNodeNames(NodeResolveInfo *nri);
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0;
virtual int getHeight() = 0;
virtual void dropResolverEntries(NodeResolver *resolver) {}
};
class DecoSimple : public Decoration {
@ -92,12 +93,11 @@ public:
s16 deco_height_max;
s16 nspawnby;
~DecoSimple() {}
virtual void resolveNodeNames(NodeResolveInfo *nri);
bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p);
virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
virtual int getHeight();
virtual void dropResolverEntries(NodeResolver *resolver);
};
class DecoSchematic : public Decoration {
@ -106,8 +106,6 @@ public:
Schematic *schematic;
std::string filename;
~DecoSchematic() {}
virtual size_t generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
virtual int getHeight();
};

@ -64,11 +64,7 @@ void OreManager::clear()
{
for (size_t i = 0; i < m_elements.size(); i++) {
Ore *ore = (Ore *)m_elements[i];
if (!ore)
continue;
m_resolver->cancelNodeList(&ore->c_wherein);
m_resolver->cancelNode(&ore->c_ore);
delete ore;
}
m_elements.clear();
}
@ -84,6 +80,19 @@ Ore::Ore()
}
Ore::~Ore()
{
delete noise;
}
void Ore::resolveNodeNames(NodeResolveInfo *nri)
{
m_ndef->getIdFromResolveInfo(nri, "", CONTENT_AIR, c_ore);
m_ndef->getIdsFromResolveInfo(nri, c_wherein);
}
size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
{
int in_range = 0;
@ -113,6 +122,9 @@ size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
}
///////////////////////////////////////////////////////////////////////////////
void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
u32 blockseed, v3s16 nmin, v3s16 nmax)
{
@ -151,6 +163,9 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
}
///////////////////////////////////////////////////////////////////////////////
void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
u32 blockseed, v3s16 nmin, v3s16 nmax)
{

@ -54,7 +54,7 @@ enum OreType {
extern FlagDesc flagdesc_ore[];
class Ore : public GenElement {
class Ore : public GenElement, public NodeResolver {
public:
static const bool NEEDS_NOISE = false;
@ -72,6 +72,9 @@ public:
Noise *noise;
Ore();
virtual ~Ore();
virtual void resolveNodeNames(NodeResolveInfo *nri);
size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
virtual void generate(ManualMapVoxelManipulator *vm, int seed,

@ -58,6 +58,12 @@ Schematic::~Schematic()
}
void Schematic::resolveNodeNames(NodeResolveInfo *nri)
{
m_ndef->getIdsFromResolveInfo(nri, c_nodes);
}
void Schematic::updateContentIds()
{
if (flags & SCHEM_CIDS_UPDATED)
@ -195,8 +201,7 @@ void Schematic::placeStructure(Map *map, v3s16 p, u32 flags,
bool Schematic::loadSchematicFromFile(const char *filename,
NodeResolver *resolver,
std::map<std::string, std::string> &replace_names)
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
{
content_t cignore = CONTENT_IGNORE;
bool have_cignore = false;
@ -224,10 +229,9 @@ bool Schematic::loadSchematicFromFile(const char *filename,
for (int y = 0; y != size.Y; y++)
slice_probs[y] = (version >= 3) ? readU8(is) : MTSCHEM_PROB_ALWAYS;
int nodecount = size.X * size.Y * size.Z;
NodeResolveInfo *nri = new NodeResolveInfo(this);
u16 nidmapcount = readU16(is);
for (int i = 0; i != nidmapcount; i++) {
std::string name = deSerializeString(is);
if (name == "ignore") {
@ -241,16 +245,22 @@ bool Schematic::loadSchematicFromFile(const char *filename,
if (it != replace_names.end())
name = it->second;
resolver->addNodeList(name.c_str(), &c_nodes);
nri->nodenames.push_back(name);
}
nri->nodename_sizes.push_back(nidmapcount);
ndef->pendNodeResolve(nri);
size_t nodecount = size.X * size.Y * size.Z;
delete []schemdata;
schemdata = new MapNode[nodecount];
MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schemdata,
nodecount, 2, 2, true);
nodecount, 2, 2, true);
if (version == 1) { // fix up the probability values
for (int i = 0; i != nodecount; i++) {
for (size_t i = 0; i != nodecount; i++) {
if (schemdata[i].param1 == 0)
schemdata[i].param1 = MTSCHEM_PROB_ALWAYS;
if (have_cignore && schemdata[i].getContent() == cignore)

@ -42,7 +42,7 @@ class NodeResolver;
#define MTSCHEM_PROB_ALWAYS 0xFF
class Schematic : public GenElement {
class Schematic : public GenElement, public NodeResolver {
public:
std::vector<content_t> c_nodes;
@ -52,14 +52,16 @@ public:
u8 *slice_probs;
Schematic();
~Schematic();
virtual ~Schematic();
virtual void resolveNodeNames(NodeResolveInfo *nri);
void updateContentIds();
void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
Rotation rot, bool force_placement, INodeDefManager *ndef);
bool loadSchematicFromFile(const char *filename, NodeResolver *resolver,
bool loadSchematicFromFile(const char *filename, INodeDefManager *ndef,
std::map<std::string, std::string> &replace_names);
void saveSchematicToFile(const char *filename, INodeDefManager *ndef);
bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
@ -86,7 +88,7 @@ public:
};
void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
std::vector<content_t> *usednodes);
std::vector<content_t> *usednodes);
#endif

@ -402,7 +402,15 @@ public:
virtual void updateTextures(IGameDef *gamedef);
void serialize(std::ostream &os, u16 protocol_version);
void deSerialize(std::istream &is);
virtual NodeResolver *getResolver();
virtual void pendNodeResolve(NodeResolveInfo *nri);
virtual void cancelNodeResolve(NodeResolver *resolver);
virtual void runNodeResolverCallbacks();
virtual bool getIdFromResolveInfo(NodeResolveInfo *nri,
const std::string &node_alt, content_t c_fallback, content_t &result);
virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri,
std::vector<content_t> &result);
private:
void addNameIdMapping(content_t i, std::string name);
@ -432,13 +440,12 @@ private:
// Next possibly free id
content_t m_next_id;
// NodeResolver to queue pending node resolutions
NodeResolver m_resolver;
// List of node strings and node resolver callbacks to perform
std::list<NodeResolveInfo *> m_pending_node_lookups;
};
CNodeDefManager::CNodeDefManager() :
m_resolver(this)
CNodeDefManager::CNodeDefManager()
{
clear();
}
@ -1035,12 +1042,6 @@ void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
}
NodeResolver *CNodeDefManager::getResolver()
{
return &m_resolver;
}
IWritableNodeDefManager *createNodeDefManager()
{
return new CNodeDefManager();
@ -1267,166 +1268,100 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
}
}
/*
NodeResolver
*/
NodeResolver::NodeResolver(INodeDefManager *ndef)
void CNodeDefManager::pendNodeResolve(NodeResolveInfo *nri)
{
m_ndef = ndef;
m_is_node_registration_complete = false;
nri->resolver->m_ndef = this;
m_pending_node_lookups.push_back(nri);
}
NodeResolver::~NodeResolver()
void CNodeDefManager::cancelNodeResolve(NodeResolver *resolver)
{
while (!m_pending_contents.empty()) {
NodeResolveInfo *nri = m_pending_contents.front();
m_pending_contents.pop_front();
delete nri;
}
}
int NodeResolver::addNode(const std::string &n_wanted, const std::string &n_alt,
content_t c_fallback, content_t *content)
{
if (m_is_node_registration_complete) {
if (m_ndef->getId(n_wanted, *content))
return NR_STATUS_SUCCESS;
if (n_alt == "" || !m_ndef->getId(n_alt, *content)) {
*content = c_fallback;
return NR_STATUS_FAILURE;
}
return NR_STATUS_SUCCESS;
} else {
NodeResolveInfo *nfi = new NodeResolveInfo;
nfi->n_wanted = n_wanted;
nfi->n_alt = n_alt;
nfi->c_fallback = c_fallback;
nfi->output = content;
m_pending_contents.push_back(nfi);
return NR_STATUS_PENDING;
}
}
int NodeResolver::addNodeList(const std::string &nodename,
std::vector<content_t> *content_vec)
{
if (m_is_node_registration_complete) {
std::set<content_t> idset;
std::set<content_t>::iterator it;
m_ndef->getIds(nodename, idset);
for (it = idset.begin(); it != idset.end(); ++it)
content_vec->push_back(*it);
return idset.size() ? NR_STATUS_SUCCESS : NR_STATUS_FAILURE;
} else {
m_pending_content_vecs.push_back(
std::make_pair(nodename, content_vec));
return NR_STATUS_PENDING;
}
}
bool NodeResolver::cancelNode(content_t *content)
{
bool found = false;
for (std::list<NodeResolveInfo *>::iterator
it = m_pending_contents.begin();
it != m_pending_contents.end();
it = m_pending_node_lookups.begin();
it != m_pending_node_lookups.end();
++it) {
NodeResolveInfo *nfi = *it;
if (nfi->output == content) {
it = m_pending_contents.erase(it);
delete nfi;
found = true;
NodeResolveInfo *nri = *it;
if (resolver == nri->resolver) {
it = m_pending_node_lookups.erase(it);
delete nri;
}
}
return found;
}
int NodeResolver::cancelNodeList(std::vector<content_t> *content_vec)
void CNodeDefManager::runNodeResolverCallbacks()
{
int num_canceled = 0;
for (ContentVectorResolveList::iterator
it = m_pending_content_vecs.begin();
it != m_pending_content_vecs.end();
++it) {
if (it->second == content_vec) {
it = m_pending_content_vecs.erase(it);
num_canceled++;
}
}
return num_canceled;
}
int NodeResolver::resolveNodes()
{
int num_failed = 0;
//// Resolve pending single node name -> content ID mappings
while (!m_pending_contents.empty()) {
NodeResolveInfo *nri = m_pending_contents.front();
m_pending_contents.pop_front();
bool success = true;
if (!m_ndef->getId(nri->n_wanted, *nri->output)) {
success = (nri->n_alt != "") ?
m_ndef->getId(nri->n_alt, *nri->output) : false;
}
if (!success) {
*nri->output = nri->c_fallback;
num_failed++;
errorstream << "NodeResolver::resolveNodes(): Failed to "
"resolve '" << nri->n_wanted;
if (nri->n_alt != "")
errorstream << "' and '" << nri->n_alt;
errorstream << "'" << std::endl;
}
while (!m_pending_node_lookups.empty()) {
NodeResolveInfo *nri = m_pending_node_lookups.front();
m_pending_node_lookups.pop_front();
nri->resolver->resolveNodeNames(nri);
nri->resolver->m_lookup_done = true;
delete nri;
}
}
//// Resolve pending node names and add to content_t vector
while (!m_pending_content_vecs.empty()) {
std::pair<std::string, std::vector<content_t> *> item =
m_pending_content_vecs.front();
m_pending_content_vecs.pop_front();
std::string &name = item.first;
std::vector<content_t> *output = item.second;
std::set<content_t> idset;
std::set<content_t>::iterator it;
m_ndef->getIds(name, idset);
for (it = idset.begin(); it != idset.end(); ++it)
output->push_back(*it);
if (idset.empty()) {
num_failed++;
errorstream << "NodeResolver::resolveNodes(): Failed to "
"resolve '" << name << "'" << std::endl;
}
bool CNodeDefManager::getIdFromResolveInfo(NodeResolveInfo *nri,
const std::string &node_alt, content_t c_fallback, content_t &result)
{
if (nri->nodenames.empty()) {
result = c_fallback;
errorstream << "CNodeDefManager::getIdFromResolveInfo: empty "
"nodenames list" << std::endl;
return false;
}
//// Mark node registration as complete so future resolve
//// requests are satisfied immediately
m_is_node_registration_complete = true;
content_t c;
std::string name = nri->nodenames.front();
nri->nodenames.pop_front();
return num_failed;
bool success = getId(name, c);
if (!success && node_alt != "") {
name = node_alt;
success = getId(name, c);
}
if (!success) {
errorstream << "CNodeDefManager::getIdFromResolveInfo: Failed to "
"resolve node name '" << name << "'." << std::endl;
c = c_fallback;
}
result = c;
return success;
}
bool CNodeDefManager::getIdsFromResolveInfo(NodeResolveInfo *nri,
std::vector<content_t> &result)
{
if (nri->nodename_sizes.empty()) {
errorstream << "CNodeDefManager::getIdsFromResolveInfo: empty "
"nodename_sizes list" << std::endl;
return false;
}
size_t nitems = nri->nodename_sizes.front();
nri->nodename_sizes.pop_front();
while (nitems--) {
if (nri->nodenames.empty()) {
errorstream << "" << std::endl;
return false;
}
content_t c;
if (getId(nri->nodenames.front(), c)) {
result.push_back(c);
} else {
errorstream << "CNodeDefManager::getIdsFromResolveInfo: empty "
"nodenames list" << std::endl;
}
nri->nodenames.pop_front();
}
return true;
}

@ -40,8 +40,6 @@ class IShaderSource;
class IGameDef;
typedef std::list<std::pair<content_t, int> > GroupItems;
typedef std::list<std::pair<std::string, std::vector<content_t> *> >
ContentVectorResolveList;
enum ContentParamType
{
@ -284,125 +282,18 @@ struct ContentFeatures
}
};
class NodeResolver;
class INodeDefManager;
struct NodeResolveInfo {
std::string n_wanted;
std::string n_alt;
content_t c_fallback;
content_t *output;
};
NodeResolveInfo(NodeResolver *nr)
{
resolver = nr;
}
#define NR_STATUS_FAILURE 0
#define NR_STATUS_PENDING 1
#define NR_STATUS_SUCCESS 2
/**
NodeResolver
NodeResolver attempts to resolve node names to content ID integers. If the
node registration phase has not yet finished at the time the resolution
request is placed, the request is marked as pending and added to an internal
queue. The name resolution request is later satisfied by writing directly
to the output location when the node registration phase has been completed.
This is primarily intended to be used for objects registered during script
initialization (i.e. while nodes are being registered) that reference
particular nodes.
*/
class NodeResolver {
public:
NodeResolver(INodeDefManager *ndef);
~NodeResolver();
/**
Add a request to resolve the node n_wanted and set *content to the
result, or alternatively, n_alt if n_wanted is not found. If n_alt
cannot be found either, or has not been specified, *content is set
to c_fallback.
If node registration is complete, the request is finished immediately
and NR_STATUS_SUCCESS is returned (or NR_STATUS_FAILURE if no node can
be found). Otherwise, NR_STATUS_PENDING is returned and the resolution
request is queued.
N.B. If the memory in which content is located has been deallocated
before the pending request had been satisfied, cancelNode() must be
called.
@param n_wanted Name of node that is wanted.
@param n_alt Name of node in case n_wanted could not be found. Blank
if no alternative node is desired.
@param c_fallback Content ID that content is set to in case of node
resolution failure (should be CONTENT_AIR, CONTENT_IGNORE, etc.)
@param content Pointer to content_t that receives the result of the
node name resolution.
@return Status of node resolution request.
*/
int addNode(const std::string &n_wanted, const std::string &n_alt,
content_t c_fallback, content_t *content);
/**
Add a request to resolve the node(s) specified by nodename.
If node registration is complete, the request is finished immediately
and NR_STATUS_SUCCESS is returned if at least one node is resolved; if
zero were resolved, NR_STATUS_FAILURE. Otherwise, NR_STATUS_PENDING is
returned and the resolution request is queued.
N.B. If the memory in which content_vec is located has been deallocated
before the pending request had been satisfied, cancelNodeList() must be
called.
@param nodename Name of node (or node group) to be resolved.
@param content_vec Pointer to content_t vector onto which the results
are added.
@return Status of node resolution request.
*/
int addNodeList(const std::string &nodename,
std::vector<content_t> *content_vec);
/**
Removes all pending requests from the resolution queue with the output
address of 'content'.
@param content Location of the content ID for the request being
cancelled.
@return Number of pending requests cancelled.
*/
bool cancelNode(content_t *content);
/**
Removes all pending requests from the resolution queue with the output
address of 'content_vec'.
@param content_vec Location of the content ID vector for requests being
cancelled.
@return Number of pending requests cancelled.
*/
int cancelNodeList(std::vector<content_t> *content_vec);
/**
Carries out all pending node resolution requests. Call this when the
node registration phase has completed.
Internally marks node registration as complete.
@return Number of failed pending requests.
*/
int resolveNodes();
/**
Returns the status of the node registration phase.
@return Boolean of whether the registration phase is complete.
*/
bool isNodeRegFinished() { return m_is_node_registration_complete; }
private:
INodeDefManager *m_ndef;
bool m_is_node_registration_complete;
std::list<NodeResolveInfo *> m_pending_contents;
ContentVectorResolveList m_pending_content_vecs;
std::list<std::string> nodenames;
std::list<size_t> nodename_sizes;
NodeResolver *resolver;
};
class INodeDefManager
@ -422,7 +313,14 @@ public:
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
virtual NodeResolver *getResolver()=0;
virtual void pendNodeResolve(NodeResolveInfo *nri)=0;
virtual void cancelNodeResolve(NodeResolver *resolver)=0;
virtual void runNodeResolverCallbacks()=0;
virtual bool getIdFromResolveInfo(NodeResolveInfo *nri,
const std::string &node_alt, content_t c_fallback, content_t &result)=0;
virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri,
std::vector<content_t> &result)=0;
};
class IWritableNodeDefManager : public INodeDefManager
@ -464,10 +362,38 @@ public:
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
virtual void deSerialize(std::istream &is)=0;
virtual NodeResolver *getResolver()=0;
virtual void pendNodeResolve(NodeResolveInfo *nri)=0;
virtual void cancelNodeResolve(NodeResolver *resolver)=0;
virtual void runNodeResolverCallbacks()=0;
virtual bool getIdFromResolveInfo(NodeResolveInfo *nri,
const std::string &node_alt, content_t c_fallback, content_t &result)=0;
virtual bool getIdsFromResolveInfo(NodeResolveInfo *nri,
std::vector<content_t> &result)=0;
};
IWritableNodeDefManager *createNodeDefManager();
class NodeResolver {
public:
NodeResolver()
{
m_lookup_done = false;
m_ndef = NULL;
}
~NodeResolver()
{
if (!m_lookup_done)
m_ndef->cancelNodeResolve(this);
}
virtual void resolveNodeNames(NodeResolveInfo *nri) = 0;
bool m_lookup_done;
INodeDefManager *m_ndef;
};
#endif

@ -235,7 +235,8 @@ bool read_stringlist(lua_State *L, int index, std::vector<const char *> &result)
if (lua_istable(L, index)) {
lua_pushnil(L);
while (lua_next(L, index)) {
result.push_back(lua_tostring(L, -1));
if (lua_isstring(L, -1))
result.push_back(lua_tostring(L, -1));
lua_pop(L, 1);
}
} else if (lua_isstring(L, index)) {

@ -183,9 +183,8 @@ bool get_schematic(lua_State *L, int index, Schematic *schem,
if (lua_istable(L, index)) {
return read_schematic(L, index, schem, ndef, replace_names);
} else if (lua_isstring(L, index)) {
NodeResolver *resolver = ndef->getResolver();
const char *filename = lua_tostring(L, index);
return schem->loadSchematicFromFile(filename, resolver, replace_names);
return schem->loadSchematicFromFile(filename, ndef, replace_names);
} else {
return false;
}
@ -415,8 +414,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
int index = 1;
luaL_checktype(L, index, LUA_TTABLE);
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
enum BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
es_BiomeTerrainType, BIOME_TYPE_NORMAL);
@ -437,19 +436,15 @@ int ModApiMapgen::l_register_biome(lua_State *L)
return 0;
}
// Pend node resolutions only if insertion succeeded
resolver->addNode(getstringfield_default(L, index, "node_top", ""),
"mapgen_dirt_with_grass", CONTENT_AIR, &b->c_top);
resolver->addNode(getstringfield_default(L, index, "node_filler", ""),
"mapgen_dirt", CONTENT_AIR, &b->c_filler);
resolver->addNode(getstringfield_default(L, index, "node_stone", ""),
"mapgen_stone", CONTENT_AIR, &b->c_stone);
resolver->addNode(getstringfield_default(L, index, "node_water", ""),
"mapgen_water_source", CONTENT_AIR, &b->c_water);
resolver->addNode(getstringfield_default(L, index, "node_dust", ""),
"air", CONTENT_IGNORE, &b->c_dust);
resolver->addNode(getstringfield_default(L, index, "node_dust_water", ""),
"mapgen_water_source", CONTENT_IGNORE, &b->c_dust_water);
NodeResolveInfo *nri = new NodeResolveInfo(b);
std::list<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", ""));
nnames.push_back(getstringfield_default(L, index, "node_dust", ""));
nnames.push_back(getstringfield_default(L, index, "node_dust_water", ""));
ndef->pendNodeResolve(nri);
verbosestream << "register_biome: " << b->name << std::endl;
@ -485,7 +480,6 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
luaL_checktype(L, index, LUA_TTABLE);
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr;
@ -509,11 +503,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
return 0;
}
NodeResolveInfo *nri = new NodeResolveInfo(deco);
//// Get node name(s) to place decoration on
std::vector<const char *> place_on_names;
getstringlistfield(L, index, "place_on", place_on_names);
nri->nodename_sizes.push_back(place_on_names.size());
for (size_t i = 0; i != place_on_names.size(); i++)
resolver->addNodeList(place_on_names[i], &deco->c_place_on);
nri->nodenames.push_back(place_on_names[i]);
getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL);
@ -538,7 +535,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
bool success = false;
switch (decotype) {
case DECO_SIMPLE:
success = regDecoSimple(L, resolver, (DecoSimple *)deco);
success = regDecoSimple(L, nri, (DecoSimple *)deco);
break;
case DECO_SCHEMATIC:
success = regDecoSchematic(L, ndef, (DecoSchematic *)deco);
@ -547,6 +544,8 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
break;
}
ndef->pendNodeResolve(nri);
if (!success) {
delete deco;
return 0;
@ -558,12 +557,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
return 0;
}
verbosestream << "register_decoration: " << deco->name << std::endl;
lua_pushinteger(L, id);
return 1;
}
bool ModApiMapgen::regDecoSimple(lua_State *L,
NodeResolver *resolver, DecoSimple *deco)
NodeResolveInfo *nri, DecoSimple *deco)
{
int index = 1;
@ -584,6 +585,9 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
"defined" << std::endl;
return false;
}
nri->nodename_sizes.push_back(deco_names.size());
for (size_t i = 0; i != deco_names.size(); i++)
nri->nodenames.push_back(deco_names[i]);
std::vector<const char *> spawnby_names;
getstringlistfield(L, index, "spawn_by", spawnby_names);
@ -592,11 +596,9 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
" but num_spawn_by specified" << std::endl;
return false;
}
for (size_t i = 0; i != deco_names.size(); i++)
resolver->addNodeList(deco_names[i], &deco->c_decos);
nri->nodename_sizes.push_back(spawnby_names.size());
for (size_t i = 0; i != spawnby_names.size(); i++)
resolver->addNodeList(spawnby_names[i], &deco->c_spawnby);
nri->nodenames.push_back(spawnby_names[i]);
return true;
}
@ -615,6 +617,7 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
read_schematic_replacements(L, replace_names, lua_gettop(L));
lua_pop(L, 1);
// TODO(hmmmm): get a ref from registered schematics
Schematic *schem = new Schematic;
lua_getfield(L, index, "schematic");
if (!get_schematic(L, -1, schem, ndef, replace_names)) {
@ -635,8 +638,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
int index = 1;
luaL_checktype(L, index, LUA_TTABLE);
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr;
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr;
enum OreType oretype = (OreType)getenumfield(L, index,
"ore_type", es_OreType, ORE_SCATTER);
@ -683,13 +686,18 @@ int ModApiMapgen::l_register_ore(lua_State *L)
return 0;
}
NodeResolveInfo *nri = new NodeResolveInfo(ore);
nri->nodenames.push_back(getstringfield_default(L, index, "ore", ""));
std::vector<const char *> wherein_names;
getstringlistfield(L, index, "wherein", wherein_names);
nri->nodename_sizes.push_back(wherein_names.size());
for (size_t i = 0; i != wherein_names.size(); i++)
resolver->addNodeList(wherein_names[i], &ore->c_wherein);
nri->nodenames.push_back(wherein_names[i]);
resolver->addNode(getstringfield_default(L, index, "ore", ""),
"", CONTENT_AIR, &ore->c_ore);
ndef->pendNodeResolve(nri);
verbosestream << "register_ore: " << ore->name << std::endl;
lua_pushinteger(L, id);
return 1;

@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
class INodeDefManager;
class NodeResolver;
class NodeResolveInfo;
class DecoSimple;
class DecoSchematic;
@ -68,7 +68,7 @@ private:
static int l_place_schematic(lua_State *L);
static bool regDecoSimple(lua_State *L,
NodeResolver *resolver, DecoSimple *deco);
NodeResolveInfo *nri, DecoSimple *deco);
static bool regDecoSchematic(lua_State *L,
INodeDefManager *ndef, DecoSchematic *deco);

@ -337,7 +337,7 @@ Server::Server(
m_nodedef->updateAliases(m_itemdef);
// Perform pending node name resolutions
m_nodedef->getResolver()->resolveNodes();
m_nodedef->runNodeResolverCallbacks();
// Load the mapgen params from global settings now after any
// initial overrides have been set by the mods
@ -2650,7 +2650,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
} // action == 4
/*
Catch invalid actions
@ -4570,7 +4570,7 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c
u32 Server::hudAdd(Player *player, HudElement *form) {
if (!player)
return -1;
u32 id = player->addHud(form);
SendHUDAdd(player->peer_id, id, form);
@ -4586,7 +4586,7 @@ bool Server::hudRemove(Player *player, u32 id) {
if (!todel)
return false;
delete todel;
SendHUDRemove(player->peer_id, id);
@ -4607,9 +4607,9 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
SendHUDSetFlags(player->peer_id, flags, mask);
player->hud_flags = flags;
PlayerSAO* playersao = player->getPlayerSAO();
if (playersao == NULL)
return false;