mirror of
https://github.com/minetest/minetest.git
synced 2024-12-28 08:57:30 +01:00
Redefine NodeResolver interface and replace with callback mechanism
This commit is contained in:
parent
3ea5ed4ffe
commit
b67f37f27e
@ -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
|
||||
|
239
src/nodedef.cpp
239
src/nodedef.cpp
@ -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;
|
||||
}
|
||||
|
168
src/nodedef.h
168
src/nodedef.h
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user