Add NodeResolver and clean up node name -> content ID resolution system
parent
b49e5cfc70
commit
d274cbfce6
|
@ -30,7 +30,7 @@ NoiseParams nparams_biome_def_heat(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.
|
|||
NoiseParams nparams_biome_def_humidity(50, 50, v3f(500.0, 500.0, 500.0), 842, 3, 0.55);
|
||||
|
||||
|
||||
BiomeDefManager::BiomeDefManager() {
|
||||
BiomeDefManager::BiomeDefManager(NodeResolver *resolver) {
|
||||
biome_registration_finished = false;
|
||||
np_heat = &nparams_biome_def_heat;
|
||||
np_humidity = &nparams_biome_def_humidity;
|
||||
|
@ -38,30 +38,22 @@ BiomeDefManager::BiomeDefManager() {
|
|||
// Create default biome to be used in case none exist
|
||||
Biome *b = new Biome;
|
||||
|
||||
b->id = 0;
|
||||
b->name = "Default";
|
||||
b->flags = 0;
|
||||
|
||||
b->depth_top = 0;
|
||||
b->depth_filler = 0;
|
||||
|
||||
b->nname_top = "air";
|
||||
b->nname_filler = "air";
|
||||
b->nname_water = "mapgen_water_source";
|
||||
b->nname_dust = "air";
|
||||
b->nname_dust_water = "mapgen_water_source";
|
||||
|
||||
b->c_top = CONTENT_IGNORE;
|
||||
b->c_filler = CONTENT_IGNORE;
|
||||
b->c_water = CONTENT_IGNORE;
|
||||
b->c_dust = CONTENT_IGNORE;
|
||||
b->c_dust_water = CONTENT_IGNORE;
|
||||
|
||||
b->id = 0;
|
||||
b->name = "Default";
|
||||
b->flags = 0;
|
||||
b->depth_top = 0;
|
||||
b->depth_filler = 0;
|
||||
b->height_min = -MAP_GENERATION_LIMIT;
|
||||
b->height_max = MAP_GENERATION_LIMIT;
|
||||
b->heat_point = 0.0;
|
||||
b->humidity_point = 0.0;
|
||||
|
||||
resolver->addNode("air", "", CONTENT_AIR, &b->c_top);
|
||||
resolver->addNode("air", "", CONTENT_AIR, &b->c_filler);
|
||||
resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_water);
|
||||
resolver->addNode("air", "", CONTENT_AIR, &b->c_dust);
|
||||
resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water);
|
||||
|
||||
biomes.push_back(b);
|
||||
}
|
||||
|
||||
|
@ -106,62 +98,18 @@ void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) {
|
|||
}
|
||||
|
||||
|
||||
void BiomeDefManager::resolveNodeNames(INodeDefManager *ndef) {
|
||||
Biome *b;
|
||||
|
||||
biome_registration_finished = true;
|
||||
|
||||
for (size_t i = 0; i < biomes.size(); i++) {
|
||||
b = biomes[i];
|
||||
|
||||
b->c_top = ndef->getId(b->nname_top);
|
||||
if (b->c_top == CONTENT_IGNORE) {
|
||||
errorstream << "BiomeDefManager::resolveNodeNames: node '"
|
||||
<< b->nname_top << "' not defined" << std::endl;
|
||||
b->c_top = CONTENT_AIR;
|
||||
b->depth_top = 0;
|
||||
}
|
||||
|
||||
b->c_filler = ndef->getId(b->nname_filler);
|
||||
if (b->c_filler == CONTENT_IGNORE) {
|
||||
errorstream << "BiomeDefManager::resolveNodeNames: node '"
|
||||
<< b->nname_filler << "' not defined" << std::endl;
|
||||
b->c_filler = CONTENT_AIR;
|
||||
b->depth_filler = 0;
|
||||
}
|
||||
|
||||
b->c_water = ndef->getId(b->nname_water);
|
||||
if (b->c_water == CONTENT_IGNORE) {
|
||||
errorstream << "BiomeDefManager::resolveNodeNames: node '"
|
||||
<< b->nname_water << "' not defined" << std::endl;
|
||||
b->c_water = CONTENT_AIR;
|
||||
}
|
||||
|
||||
b->c_dust = ndef->getId(b->nname_dust);
|
||||
if (b->c_dust == CONTENT_IGNORE) {
|
||||
errorstream << "BiomeDefManager::resolveNodeNames: node '"
|
||||
<< b->nname_dust << "' not defined" << std::endl;
|
||||
}
|
||||
|
||||
b->c_dust_water = ndef->getId(b->nname_dust_water);
|
||||
if (b->c_dust_water == CONTENT_IGNORE) {
|
||||
errorstream << "BiomeDefManager::resolveNodeNames: node '"
|
||||
<< b->nname_dust_water << "' not defined" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BiomeDefManager::addBiome(Biome *b) {
|
||||
if (biome_registration_finished) {
|
||||
errorstream << "BIomeDefManager: biome registration already finished, dropping " << b->name <<std::endl;
|
||||
errorstream << "BIomeDefManager: biome registration already "
|
||||
"finished, dropping " << b->name << std::endl;
|
||||
delete b;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t nbiomes = biomes.size();
|
||||
if (nbiomes >= 0xFF) {
|
||||
errorstream << "BiomeDefManager: too many biomes, dropping " << b->name << std::endl;
|
||||
errorstream << "BiomeDefManager: too many biomes, dropping "
|
||||
<< b->name << std::endl;
|
||||
delete b;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -45,11 +45,13 @@ public:
|
|||
std::string name;
|
||||
u32 flags;
|
||||
|
||||
/*
|
||||
std::string nname_top;
|
||||
std::string nname_filler;
|
||||
std::string nname_water;
|
||||
std::string nname_dust;
|
||||
std::string nname_dust_water;
|
||||
*/
|
||||
|
||||
content_t c_top;
|
||||
content_t c_filler;
|
||||
|
@ -81,7 +83,7 @@ public:
|
|||
NoiseParams *np_heat;
|
||||
NoiseParams *np_humidity;
|
||||
|
||||
BiomeDefManager();
|
||||
BiomeDefManager(NodeResolver *resolver);
|
||||
~BiomeDefManager();
|
||||
|
||||
Biome *createBiome(BiomeTerrainType btt);
|
||||
|
|
|
@ -85,7 +85,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
|
|||
registerMapgen("singlenode", new MapgenFactorySinglenode());
|
||||
|
||||
this->ndef = gamedef->getNodeDefManager();
|
||||
this->biomedef = new BiomeDefManager();
|
||||
this->biomedef = new BiomeDefManager(gamedef->getNodeDefManager()->getResolver());
|
||||
this->gennotify = 0;
|
||||
|
||||
// Note that accesses to this variable are not synchronized.
|
||||
|
@ -145,9 +145,9 @@ EmergeManager::~EmergeManager() {
|
|||
delete decorations[i];
|
||||
decorations.clear();
|
||||
|
||||
for (std::map<std::string, MapgenFactory *>::iterator iter = mglist.begin();
|
||||
iter != mglist.end(); iter ++) {
|
||||
delete iter->second;
|
||||
for (std::map<std::string, MapgenFactory *>::iterator it = mglist.begin();
|
||||
it != mglist.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
mglist.clear();
|
||||
|
||||
|
@ -176,16 +176,6 @@ void EmergeManager::initMapgens() {
|
|||
if (mapgen.size())
|
||||
return;
|
||||
|
||||
// Resolve names of nodes for things that were registered
|
||||
// (at this point, the registration period is over)
|
||||
biomedef->resolveNodeNames(ndef);
|
||||
|
||||
for (size_t i = 0; i != ores.size(); i++)
|
||||
ores[i]->resolveNodeNames(ndef);
|
||||
|
||||
for (size_t i = 0; i != decorations.size(); i++)
|
||||
decorations[i]->resolveNodeNames(ndef);
|
||||
|
||||
if (!params.sparams) {
|
||||
params.sparams = createMapgenParams(params.mg_name);
|
||||
if (!params.sparams) {
|
||||
|
|
170
src/mapgen.cpp
170
src/mapgen.cpp
|
@ -96,28 +96,6 @@ Ore::~Ore() {
|
|||
}
|
||||
|
||||
|
||||
void Ore::resolveNodeNames(INodeDefManager *ndef) {
|
||||
if (ore == CONTENT_IGNORE) {
|
||||
ore = ndef->getId(ore_name);
|
||||
if (ore == CONTENT_IGNORE) {
|
||||
errorstream << "Ore::resolveNodeNames: ore node '"
|
||||
<< ore_name << "' not defined";
|
||||
ore = CONTENT_AIR;
|
||||
wherein.push_back(CONTENT_AIR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i=0; i != wherein_names.size(); i++) {
|
||||
std::string name = wherein_names[i];
|
||||
content_t c = ndef->getId(name);
|
||||
if (c != CONTENT_IGNORE) {
|
||||
wherein.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||
int in_range = 0;
|
||||
|
||||
|
@ -147,7 +125,7 @@ void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
|||
void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
|
||||
u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||
PseudoRandom pr(blockseed);
|
||||
MapNode n_ore(ore, 0, ore_param2);
|
||||
MapNode n_ore(c_ore, 0, ore_param2);
|
||||
|
||||
int volume = (nmax.X - nmin.X + 1) *
|
||||
(nmax.Y - nmin.Y + 1) *
|
||||
|
@ -171,8 +149,8 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
|
|||
continue;
|
||||
|
||||
u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
|
||||
for (size_t ii = 0; ii < wherein.size(); ii++)
|
||||
if (vm->m_data[i].getContent() == wherein[ii])
|
||||
for (size_t ii = 0; ii < c_wherein.size(); ii++)
|
||||
if (vm->m_data[i].getContent() == c_wherein[ii])
|
||||
vm->m_data[i] = n_ore;
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +160,7 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
|
|||
void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
|
||||
u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||
PseudoRandom pr(blockseed + 4234);
|
||||
MapNode n_ore(ore, 0, ore_param2);
|
||||
MapNode n_ore(c_ore, 0, ore_param2);
|
||||
|
||||
int max_height = clust_size;
|
||||
int y_start = pr.range(nmin.Y, nmax.Y - max_height);
|
||||
|
@ -210,9 +188,12 @@ void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
|
|||
if (!vm->m_area.contains(i))
|
||||
continue;
|
||||
|
||||
for (size_t ii = 0; ii < wherein.size(); ii++)
|
||||
if (vm->m_data[i].getContent() == wherein[ii])
|
||||
for (size_t ii = 0; ii < c_wherein.size(); ii++) {
|
||||
if (vm->m_data[i].getContent() == c_wherein[ii]) {
|
||||
vm->m_data[i] = n_ore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,14 +229,6 @@ Decoration::~Decoration() {
|
|||
}
|
||||
|
||||
|
||||
void Decoration::resolveNodeNames(INodeDefManager *ndef) {
|
||||
this->ndef = ndef;
|
||||
|
||||
if (c_place_on == CONTENT_IGNORE)
|
||||
c_place_on = ndef->getId(place_on_name);
|
||||
}
|
||||
|
||||
|
||||
void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||
PseudoRandom ps(blockseed + 53);
|
||||
int carea_size = nmax.X - nmin.X + 1;
|
||||
|
@ -388,48 +361,17 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void DecoSimple::resolveNodeNames(INodeDefManager *ndef) {
|
||||
Decoration::resolveNodeNames(ndef);
|
||||
|
||||
if (c_deco == CONTENT_IGNORE && !decolist_names.size()) {
|
||||
c_deco = ndef->getId(deco_name);
|
||||
if (c_deco == CONTENT_IGNORE) {
|
||||
errorstream << "DecoSimple::resolveNodeNames: decoration node '"
|
||||
<< deco_name << "' not defined" << std::endl;
|
||||
c_deco = CONTENT_AIR;
|
||||
}
|
||||
}
|
||||
if (c_spawnby == CONTENT_IGNORE) {
|
||||
c_spawnby = ndef->getId(spawnby_name);
|
||||
if (c_spawnby == CONTENT_IGNORE) {
|
||||
errorstream << "DecoSimple::resolveNodeNames: spawnby node '"
|
||||
<< spawnby_name << "' not defined" << std::endl;
|
||||
nspawnby = -1;
|
||||
c_spawnby = CONTENT_AIR;
|
||||
}
|
||||
}
|
||||
|
||||
if (c_decolist.size())
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i != decolist_names.size(); i++) {
|
||||
content_t c = ndef->getId(decolist_names[i]);
|
||||
if (c == CONTENT_IGNORE) {
|
||||
errorstream << "DecoSimple::resolveNodeNames: decolist node '"
|
||||
<< decolist_names[i] << "' not defined" << std::endl;
|
||||
c = CONTENT_AIR;
|
||||
}
|
||||
c_decolist.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) {
|
||||
ManualMapVoxelManipulator *vm = mg->vm;
|
||||
|
||||
u32 vi = vm->m_area.index(p);
|
||||
if (vm->m_data[vi].getContent() != c_place_on &&
|
||||
c_place_on != CONTENT_IGNORE)
|
||||
content_t c = vm->m_data[vi].getContent();
|
||||
size_t idx;
|
||||
for (idx = 0; idx != c_place_on.size(); idx++) {
|
||||
if (c == c_place_on[idx])
|
||||
break;
|
||||
}
|
||||
if ((idx != 0) && (idx == c_place_on.size()))
|
||||
return;
|
||||
|
||||
if (nspawnby != -1) {
|
||||
|
@ -447,17 +389,25 @@ void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) {
|
|||
|
||||
for (int i = 0; i != 8; i++) {
|
||||
u32 index = vm->m_area.index(p + dirs[i]);
|
||||
if (vm->m_area.contains(index) &&
|
||||
vm->m_data[index].getContent() == c_spawnby)
|
||||
nneighs++;
|
||||
if (!vm->m_area.contains(index))
|
||||
continue;
|
||||
|
||||
content_t c = vm->m_data[index].getContent();
|
||||
for (size_t j = 0; j != c_spawnby.size(); j++) {
|
||||
if (c == c_spawnby[j]) {
|
||||
nneighs++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nneighs < nspawnby)
|
||||
return;
|
||||
}
|
||||
|
||||
size_t ndecos = c_decolist.size();
|
||||
content_t c_place = ndecos ? c_decolist[pr->range(0, ndecos - 1)] : c_deco;
|
||||
if (c_decos.size() == 0)
|
||||
return;
|
||||
content_t c_place = c_decos[pr->range(0, c_decos.size() - 1)];
|
||||
|
||||
s16 height = (deco_height_max > 0) ?
|
||||
pr->range(deco_height, deco_height_max) : deco_height;
|
||||
|
@ -483,7 +433,7 @@ int DecoSimple::getHeight() {
|
|||
|
||||
|
||||
std::string DecoSimple::getName() {
|
||||
return deco_name;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
@ -491,7 +441,6 @@ std::string DecoSimple::getName() {
|
|||
|
||||
|
||||
DecoSchematic::DecoSchematic() {
|
||||
node_names = NULL;
|
||||
schematic = NULL;
|
||||
slice_probs = NULL;
|
||||
flags = 0;
|
||||
|
@ -500,47 +449,19 @@ DecoSchematic::DecoSchematic() {
|
|||
|
||||
|
||||
DecoSchematic::~DecoSchematic() {
|
||||
delete node_names;
|
||||
delete []schematic;
|
||||
delete []slice_probs;
|
||||
}
|
||||
|
||||
|
||||
void DecoSchematic::resolveNodeNames(INodeDefManager *ndef) {
|
||||
Decoration::resolveNodeNames(ndef);
|
||||
|
||||
if (filename.empty())
|
||||
void DecoSchematic::updateContentIds() {
|
||||
if (flags & DECO_SCHEM_CIDS_UPDATED)
|
||||
return;
|
||||
|
||||
if (!node_names) {
|
||||
errorstream << "DecoSchematic::resolveNodeNames: node name list was "
|
||||
"not created" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != node_names->size(); i++) {
|
||||
std::string name = node_names->at(i);
|
||||
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
it = replacements.find(name);
|
||||
if (it != replacements.end())
|
||||
name = it->second;
|
||||
|
||||
content_t c = ndef->getId(name);
|
||||
if (c == CONTENT_IGNORE) {
|
||||
errorstream << "DecoSchematic::resolveNodeNames: node '"
|
||||
<< name << "' not defined" << std::endl;
|
||||
c = CONTENT_AIR;
|
||||
}
|
||||
|
||||
c_nodes.push_back(c);
|
||||
}
|
||||
flags |= DECO_SCHEM_CIDS_UPDATED;
|
||||
|
||||
for (int i = 0; i != size.X * size.Y * size.Z; i++)
|
||||
schematic[i].setContent(c_nodes[schematic[i].getContent()]);
|
||||
|
||||
delete node_names;
|
||||
node_names = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -555,8 +476,13 @@ void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) {
|
|||
p.Z -= (size.Z + 1) / 2;
|
||||
|
||||
u32 vi = vm->m_area.index(p);
|
||||
if (vm->m_data[vi].getContent() != c_place_on &&
|
||||
c_place_on != CONTENT_IGNORE)
|
||||
content_t c = vm->m_data[vi].getContent();
|
||||
size_t idx;
|
||||
for (idx = 0; idx != c_place_on.size(); idx++) {
|
||||
if (c == c_place_on[idx])
|
||||
break;
|
||||
}
|
||||
if ((idx != 0) && (idx == c_place_on.size()))
|
||||
return;
|
||||
|
||||
Rotation rot = (rotation == ROTATE_RAND) ?
|
||||
|
@ -582,6 +508,8 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
|||
int ystride = size.X;
|
||||
int zstride = size.X * size.Y;
|
||||
|
||||
updateContentIds();
|
||||
|
||||
s16 sx = size.X;
|
||||
s16 sy = size.Y;
|
||||
s16 sz = size.Z;
|
||||
|
@ -694,7 +622,9 @@ void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement) {
|
|||
}
|
||||
|
||||
|
||||
bool DecoSchematic::loadSchematicFile() {
|
||||
bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
|
||||
std::map<std::string, std::string> &replace_names)
|
||||
{
|
||||
content_t cignore = CONTENT_IGNORE;
|
||||
bool have_cignore = false;
|
||||
|
||||
|
@ -730,7 +660,6 @@ bool DecoSchematic::loadSchematicFile() {
|
|||
|
||||
u16 nidmapcount = readU16(is);
|
||||
|
||||
node_names = new std::vector<std::string>;
|
||||
for (int i = 0; i != nidmapcount; i++) {
|
||||
std::string name = deSerializeString(is);
|
||||
if (name == "ignore") {
|
||||
|
@ -738,7 +667,14 @@ bool DecoSchematic::loadSchematicFile() {
|
|||
cignore = i;
|
||||
have_cignore = true;
|
||||
}
|
||||
node_names->push_back(name);
|
||||
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
|
||||
it = replace_names.find(name);
|
||||
if (it != replace_names.end())
|
||||
name = it->second;
|
||||
|
||||
resolver->addNodeList(name.c_str(), &c_nodes);
|
||||
}
|
||||
|
||||
delete []schematic;
|
||||
|
|
37
src/mapgen.h
37
src/mapgen.h
|
@ -47,9 +47,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define OREFLAG_NODEISNT 0x04 // not yet implemented
|
||||
|
||||
/////////////////// Decoration flags
|
||||
#define DECO_PLACE_CENTER_X 1
|
||||
#define DECO_PLACE_CENTER_Y 2
|
||||
#define DECO_PLACE_CENTER_Z 4
|
||||
#define DECO_PLACE_CENTER_X 1
|
||||
#define DECO_PLACE_CENTER_Y 2
|
||||
#define DECO_PLACE_CENTER_Z 4
|
||||
#define DECO_SCHEM_CIDS_UPDATED 8
|
||||
|
||||
#define ORE_RANGE_ACTUAL 1
|
||||
#define ORE_RANGE_MIRROR 2
|
||||
|
@ -164,10 +165,8 @@ struct MapgenFactory {
|
|||
|
||||
class Ore {
|
||||
public:
|
||||
std::string ore_name;
|
||||
std::vector<std::string> wherein_names;
|
||||
content_t ore;
|
||||
std::vector<content_t> wherein; // the node to be replaced
|
||||
content_t c_ore; // the node to place
|
||||
std::vector<content_t> c_wherein; // the nodes to be placed in
|
||||
u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing at a node
|
||||
s16 clust_num_ores; // how many ore nodes are in a chunk
|
||||
s16 clust_size; // how large (in nodes) a chunk of ore is
|
||||
|
@ -180,14 +179,13 @@ public:
|
|||
Noise *noise;
|
||||
|
||||
Ore() {
|
||||
ore = CONTENT_IGNORE;
|
||||
c_ore = CONTENT_IGNORE;
|
||||
np = NULL;
|
||||
noise = NULL;
|
||||
}
|
||||
|
||||
virtual ~Ore();
|
||||
|
||||
void resolveNodeNames(INodeDefManager *ndef);
|
||||
void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
virtual void generate(ManualMapVoxelManipulator *vm, int seed,
|
||||
u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
|
||||
|
@ -234,8 +232,7 @@ public:
|
|||
INodeDefManager *ndef;
|
||||
|
||||
int mapseed;
|
||||
std::string place_on_name;
|
||||
content_t c_place_on;
|
||||
std::vector<content_t> c_place_on;
|
||||
s16 sidelen;
|
||||
float fill_ratio;
|
||||
NoiseParams *np;
|
||||
|
@ -247,7 +244,6 @@ public:
|
|||
Decoration();
|
||||
virtual ~Decoration();
|
||||
|
||||
virtual void resolveNodeNames(INodeDefManager *ndef);
|
||||
void placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
void placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
|
||||
|
@ -258,20 +254,14 @@ public:
|
|||
|
||||
class DecoSimple : public Decoration {
|
||||
public:
|
||||
std::string deco_name;
|
||||
std::string spawnby_name;
|
||||
content_t c_deco;
|
||||
content_t c_spawnby;
|
||||
std::vector<content_t> c_decos;
|
||||
std::vector<content_t> c_spawnby;
|
||||
s16 deco_height;
|
||||
s16 deco_height_max;
|
||||
s16 nspawnby;
|
||||
|
||||
std::vector<std::string> decolist_names;
|
||||
std::vector<content_t> c_decolist;
|
||||
|
||||
~DecoSimple() {}
|
||||
|
||||
void resolveNodeNames(INodeDefManager *ndef);
|
||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||
virtual int getHeight();
|
||||
virtual std::string getName();
|
||||
|
@ -288,9 +278,7 @@ class DecoSchematic : public Decoration {
|
|||
public:
|
||||
std::string filename;
|
||||
|
||||
std::vector<std::string> *node_names;
|
||||
std::vector<content_t> c_nodes;
|
||||
std::map<std::string, std::string> replacements;
|
||||
|
||||
u32 flags;
|
||||
Rotation rotation;
|
||||
|
@ -301,7 +289,7 @@ public:
|
|||
DecoSchematic();
|
||||
~DecoSchematic();
|
||||
|
||||
void resolveNodeNames(INodeDefManager *ndef);
|
||||
void updateContentIds();
|
||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||
virtual int getHeight();
|
||||
virtual std::string getName();
|
||||
|
@ -309,7 +297,8 @@ public:
|
|||
void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
||||
Rotation rot, bool force_placement);
|
||||
|
||||
bool loadSchematicFile();
|
||||
bool loadSchematicFile(NodeResolver *resolver,
|
||||
std::map<std::string, std::string> &replace_names);
|
||||
void saveSchematicFile(INodeDefManager *ndef);
|
||||
|
||||
bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
|
||||
|
|
167
src/nodedef.cpp
167
src/nodedef.cpp
|
@ -402,6 +402,7 @@ public:
|
|||
virtual void updateTextures(IGameDef *gamedef);
|
||||
void serialize(std::ostream &os, u16 protocol_version);
|
||||
void deSerialize(std::istream &is);
|
||||
virtual NodeResolver *getResolver();
|
||||
|
||||
private:
|
||||
void addNameIdMapping(content_t i, std::string name);
|
||||
|
@ -430,10 +431,14 @@ private:
|
|||
|
||||
// Next possibly free id
|
||||
content_t m_next_id;
|
||||
|
||||
// NodeResolver to queue pending node resolutions
|
||||
NodeResolver m_resolver;
|
||||
};
|
||||
|
||||
|
||||
CNodeDefManager::CNodeDefManager()
|
||||
CNodeDefManager::CNodeDefManager() :
|
||||
m_resolver(this)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
@ -1017,6 +1022,12 @@ void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
|
|||
}
|
||||
|
||||
|
||||
NodeResolver *CNodeDefManager::getResolver()
|
||||
{
|
||||
return &m_resolver;
|
||||
}
|
||||
|
||||
|
||||
IWritableNodeDefManager *createNodeDefManager()
|
||||
{
|
||||
return new CNodeDefManager();
|
||||
|
@ -1242,3 +1253,157 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||
throw SerializationError("unsupported ContentFeatures version");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
NodeResolver
|
||||
*/
|
||||
|
||||
NodeResolver::NodeResolver(INodeDefManager *ndef)
|
||||
{
|
||||
m_ndef = ndef;
|
||||
m_is_node_registration_complete = false;
|
||||
}
|
||||
|
||||
|
||||
NodeResolver::~NodeResolver()
|
||||
{
|
||||
while (!m_pending_contents.empty()) {
|
||||
NodeResolveInfo *nri = m_pending_contents.front();
|
||||
m_pending_contents.pop_front();
|
||||
delete nri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int NodeResolver::addNode(std::string n_wanted, 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 == "")
|
||||
return NR_STATUS_FAILURE;
|
||||
|
||||
return m_ndef->getId(n_alt, *content) ?
|
||||
NR_STATUS_SUCCESS : NR_STATUS_FAILURE;
|
||||
} 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 char *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(std::string(nodename), content_vec));
|
||||
return NR_STATUS_PENDING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool NodeResolver::cancelNode(content_t *content)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
std::list<NodeResolveInfo *>::iterator it = m_pending_contents.begin();
|
||||
while (it != m_pending_contents.end()) {
|
||||
NodeResolveInfo *nfi = *it;
|
||||
if (nfi->output == content) {
|
||||
it = m_pending_contents.erase(it);
|
||||
delete nfi;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
int NodeResolver::cancelNodeList(std::vector<content_t> *content_vec)
|
||||
{
|
||||
int num_canceled = 0;
|
||||
|
||||
std::list<std::pair<std::string, std::vector<content_t> *> >::iterator it;
|
||||
it = m_pending_content_vecs.begin();
|
||||
while (it != m_pending_content_vecs.end()) {
|
||||
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 << "' to a content ID" << std::endl;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//// Mark node registration as complete so future resolve
|
||||
//// requests are satisfied immediately
|
||||
m_is_node_registration_complete = true;
|
||||
|
||||
return num_failed;
|
||||
}
|
||||
|
|
|
@ -282,6 +282,40 @@ struct ContentFeatures
|
|||
}
|
||||
};
|
||||
|
||||
struct NodeResolveInfo {
|
||||
std::string n_wanted;
|
||||
std::string n_alt;
|
||||
content_t c_fallback;
|
||||
content_t *output;
|
||||
};
|
||||
|
||||
#define NR_STATUS_FAILURE 0
|
||||
#define NR_STATUS_PENDING 1
|
||||
#define NR_STATUS_SUCCESS 2
|
||||
|
||||
class NodeResolver {
|
||||
public:
|
||||
NodeResolver(INodeDefManager *ndef);
|
||||
~NodeResolver();
|
||||
|
||||
int addNode(std::string n_wanted, std::string n_alt,
|
||||
content_t c_fallback, content_t *content);
|
||||
int addNodeList(const char *nodename, std::vector<content_t> *content_vec);
|
||||
|
||||
bool cancelNode(content_t *content);
|
||||
int cancelNodeList(std::vector<content_t> *content_vec);
|
||||
|
||||
int resolveNodes();
|
||||
|
||||
bool isNodeRegFinished() { return m_is_node_registration_complete; }
|
||||
|
||||
private:
|
||||
INodeDefManager *m_ndef;
|
||||
bool m_is_node_registration_complete;
|
||||
std::list<NodeResolveInfo *> m_pending_contents;
|
||||
std::list<std::pair<std::string, std::vector<content_t> *> > m_pending_content_vecs;
|
||||
};
|
||||
|
||||
class INodeDefManager
|
||||
{
|
||||
public:
|
||||
|
@ -298,6 +332,8 @@ public:
|
|||
virtual const ContentFeatures& get(const std::string &name) const=0;
|
||||
|
||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||
|
||||
virtual NodeResolver *getResolver()=0;
|
||||
};
|
||||
|
||||
class IWritableNodeDefManager : public INodeDefManager
|
||||
|
@ -338,9 +374,11 @@ public:
|
|||
|
||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
|
||||
virtual NodeResolver *getResolver()=0;
|
||||
};
|
||||
|
||||
IWritableNodeDefManager* createNodeDefManager();
|
||||
IWritableNodeDefManager *createNodeDefManager();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -227,6 +227,25 @@ 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)
|
||||
{
|
||||
if (index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
if (lua_istable(L, index)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, index)) {
|
||||
result.push_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isstring(L, index)) {
|
||||
result.push_back(lua_tostring(L, index));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Table field getters
|
||||
*/
|
||||
|
@ -287,6 +306,17 @@ bool getboolfield(lua_State *L, int table,
|
|||
return got;
|
||||
}
|
||||
|
||||
bool getstringlistfield(lua_State *L, int table, const char *fieldname,
|
||||
std::vector<const char *> &result)
|
||||
{
|
||||
lua_getfield(L, table, fieldname);
|
||||
|
||||
bool got = read_stringlist(L, -1, result);
|
||||
|
||||
lua_pop(L, 1);
|
||||
return got;
|
||||
}
|
||||
|
||||
std::string checkstringfield(lua_State *L, int table,
|
||||
const char *fieldname)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ extern "C" {
|
|||
#include <lua.h>
|
||||
}
|
||||
|
||||
std::string getstringfield_default (lua_State *L, int table,
|
||||
std::string getstringfield_default(lua_State *L, int table,
|
||||
const char *fieldname, const std::string &default_);
|
||||
bool getboolfield_default(lua_State *L, int table,
|
||||
const char *fieldname, bool default_);
|
||||
|
@ -48,9 +48,12 @@ 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,
|
||||
const char *fieldname,
|
||||
std::vector<const char *> &result);
|
||||
bool getintfield(lua_State *L, int table,
|
||||
const char *fieldname, int &result);
|
||||
void read_groups (lua_State *L, int index,
|
||||
void read_groups(lua_State *L, int index,
|
||||
std::map<std::string, int> &result);
|
||||
bool getboolfield(lua_State *L, int table,
|
||||
const char *fieldname, bool &result);
|
||||
|
@ -68,28 +71,29 @@ void setboolfield(lua_State *L, int table,
|
|||
const char *fieldname, bool value);
|
||||
|
||||
|
||||
v3f checkFloatPos (lua_State *L, int index);
|
||||
v3f check_v3f (lua_State *L, int index);
|
||||
v3s16 check_v3s16 (lua_State *L, int index);
|
||||
v3f checkFloatPos (lua_State *L, int index);
|
||||
v3f check_v3f (lua_State *L, int index);
|
||||
v3s16 check_v3s16 (lua_State *L, int index);
|
||||
|
||||
v3f read_v3f (lua_State *L, int index);
|
||||
v2f read_v2f (lua_State *L, int index);
|
||||
v2s16 read_v2s16 (lua_State *L, int index);
|
||||
v2s32 read_v2s32 (lua_State *L, int index);
|
||||
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);
|
||||
v3f read_v3f (lua_State *L, int index);
|
||||
v2f read_v2f (lua_State *L, int index);
|
||||
v2s16 read_v2s16 (lua_State *L, int index);
|
||||
v2s32 read_v2s32 (lua_State *L, int index);
|
||||
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);
|
||||
|
||||
void push_v3s16 (lua_State *L, v3s16 p);
|
||||
void pushFloatPos (lua_State *L, v3f p);
|
||||
void push_v3f (lua_State *L, v3f p);
|
||||
void push_v2f (lua_State *L, v2f p);
|
||||
void push_v3s16 (lua_State *L, v3s16 p);
|
||||
void pushFloatPos (lua_State *L, v3f p);
|
||||
void push_v3f (lua_State *L, v3f p);
|
||||
void push_v2f (lua_State *L, v2f p);
|
||||
|
||||
|
||||
|
||||
void warn_if_field_exists (lua_State *L,
|
||||
void warn_if_field_exists (lua_State *L,
|
||||
int table,
|
||||
const char *fieldname,
|
||||
const std::string &message);
|
||||
|
|
|
@ -80,26 +80,28 @@ struct EnumString ModApiMapgen::es_Rotation[] =
|
|||
};
|
||||
|
||||
|
||||
static void read_schematic_replacements(lua_State *L, DecoSchematic *dschem, int index)
|
||||
static void read_schematic_replacements(lua_State *L,
|
||||
std::map<std::string, std::string> replace_names, int index)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, index)) {
|
||||
// key at index -2 and value at index -1
|
||||
std::string replace_from;
|
||||
std::string replace_to;
|
||||
if (lua_istable(L, -1)) { // Old {{"x", "y"}, ...} format
|
||||
|
||||
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
|
||||
} else { // New {x = "y", ...} format
|
||||
replace_from = lua_tostring(L, -2);
|
||||
replace_to = lua_tostring(L, -1);
|
||||
}
|
||||
dschem->replacements[replace_from] = replace_to;
|
||||
// removes value, keeps key for next iteration
|
||||
|
||||
replace_names[replace_from] = replace_to;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
@ -298,7 +300,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||
int index = 1;
|
||||
luaL_checktype(L, index, LUA_TTABLE);
|
||||
|
||||
BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
|
||||
if (!bmgr) {
|
||||
verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
|
||||
return 0;
|
||||
|
@ -308,32 +311,25 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||
"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
|
||||
Biome *b = bmgr->createBiome(terrain);
|
||||
|
||||
b->name = getstringfield_default(L, index, "name",
|
||||
"<no name>");
|
||||
b->nname_top = getstringfield_default(L, index, "node_top",
|
||||
"mapgen_dirt_with_grass");
|
||||
b->nname_filler = getstringfield_default(L, index, "node_filler",
|
||||
"mapgen_dirt");
|
||||
b->nname_water = getstringfield_default(L, index, "node_water",
|
||||
"mapgen_water_source");
|
||||
b->nname_dust = getstringfield_default(L, index, "node_dust",
|
||||
"air");
|
||||
b->nname_dust_water = getstringfield_default(L, index, "node_dust_water",
|
||||
"mapgen_water_source");
|
||||
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_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);
|
||||
|
||||
b->name = getstringfield_default(L, index, "name", "<no name>");
|
||||
b->depth_top = getintfield_default(L, index, "depth_top", 1);
|
||||
b->depth_filler = getintfield_default(L, index, "depth_filler", 3);
|
||||
b->height_min = getintfield_default(L, index, "height_min", 0);
|
||||
b->height_max = getintfield_default(L, index, "height_max", 0);
|
||||
b->heat_point = getfloatfield_default(L, index, "heat_point", 0.);
|
||||
b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
|
||||
|
||||
b->flags = 0; //reserved
|
||||
b->c_top = CONTENT_IGNORE;
|
||||
b->c_filler = CONTENT_IGNORE;
|
||||
b->c_water = CONTENT_IGNORE;
|
||||
b->c_dust = CONTENT_IGNORE;
|
||||
b->c_dust_water = CONTENT_IGNORE;
|
||||
b->flags = 0; //reserved
|
||||
|
||||
verbosestream << "register_biome: " << b->name << std::endl;
|
||||
bmgr->addBiome(b);
|
||||
|
@ -349,6 +345,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
|
||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||
BiomeDefManager *bdef = emerge->biomedef;
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
|
||||
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
|
||||
"deco_type", es_DecorationType, 0);
|
||||
|
@ -364,11 +361,9 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
<< decotype << " not implemented";
|
||||
return 0;
|
||||
}
|
||||
|
||||
deco->c_place_on = CONTENT_IGNORE;
|
||||
deco->place_on_name = getstringfield_default(L, index, "place_on", "ignore");
|
||||
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
||||
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
||||
|
||||
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
||||
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
||||
if (deco->sidelen <= 0) {
|
||||
errorstream << "register_decoration: sidelen must be "
|
||||
"greater than 0" << std::endl;
|
||||
|
@ -376,51 +371,35 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//// Get node name(s) to place decoration on
|
||||
std::vector<const char *> place_on_names;
|
||||
getstringlistfield(L, index, "place_on", place_on_names);
|
||||
for (size_t i = 0; i != place_on_names.size(); i++)
|
||||
resolver->addNodeList(place_on_names[i], &deco->c_place_on);
|
||||
|
||||
//// Get NoiseParams to define how decoration is placed
|
||||
lua_getfield(L, index, "noise_params");
|
||||
deco->np = read_noiseparams(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "biomes");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
const char *s = lua_tostring(L, -1);
|
||||
u8 biomeid = bdef->getBiomeIdByName(s);
|
||||
if (biomeid)
|
||||
deco->biomes.insert(biomeid);
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
//// Get biomes associated with this decoration (if any)
|
||||
std::vector<const char *> biome_list;
|
||||
getstringlistfield(L, index, "biomes", biome_list);
|
||||
for (size_t i = 0; i != biome_list.size(); i++) {
|
||||
u8 biomeid = bdef->getBiomeIdByName(biome_list[i]);
|
||||
if (biomeid)
|
||||
deco->biomes.insert(biomeid);
|
||||
}
|
||||
|
||||
//// Handle decoration type-specific parameters
|
||||
switch (decotype) {
|
||||
case DECO_SIMPLE: {
|
||||
DecoSimple *dsimple = (DecoSimple *)deco;
|
||||
dsimple->c_deco = CONTENT_IGNORE;
|
||||
dsimple->c_spawnby = CONTENT_IGNORE;
|
||||
dsimple->spawnby_name = getstringfield_default(L, index, "spawn_by", "air");
|
||||
|
||||
dsimple->deco_height = getintfield_default(L, index, "height", 1);
|
||||
dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
||||
dsimple->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
|
||||
|
||||
lua_getfield(L, index, "decoration");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
const char *s = lua_tostring(L, -1);
|
||||
std::string str(s);
|
||||
dsimple->decolist_names.push_back(str);
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isstring(L, -1)) {
|
||||
dsimple->deco_name = std::string(lua_tostring(L, -1));
|
||||
} else {
|
||||
dsimple->deco_name = std::string("air");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (dsimple->deco_height <= 0) {
|
||||
errorstream << "register_decoration: simple decoration height"
|
||||
" must be greater than 0" << std::endl;
|
||||
|
@ -428,7 +407,31 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
break; }
|
||||
std::vector<const char *> deco_names;
|
||||
getstringlistfield(L, index, "decoration", deco_names);
|
||||
if (deco_names.size() == 0) {
|
||||
errorstream << "register_decoration: no decoration nodes "
|
||||
"defined" << std::endl;
|
||||
delete dsimple;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<const char *> spawnby_names;
|
||||
getstringlistfield(L, index, "spawn_by", spawnby_names);
|
||||
if (dsimple->nspawnby != -1 && spawnby_names.size() == 0) {
|
||||
errorstream << "register_decoration: no spawn_by nodes defined,"
|
||||
" but num_spawn_by specified" << std::endl;
|
||||
delete dsimple;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != deco_names.size(); i++)
|
||||
resolver->addNodeList(deco_names[i], &dsimple->c_decos);
|
||||
for (size_t i = 0; i != spawnby_names.size(); i++)
|
||||
resolver->addNodeList(spawnby_names[i], &dsimple->c_spawnby);
|
||||
|
||||
break;
|
||||
}
|
||||
case DECO_SCHEMATIC: {
|
||||
DecoSchematic *dschem = (DecoSchematic *)deco;
|
||||
|
||||
|
@ -439,10 +442,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
dschem->rotation = (Rotation)getenumfield(L, index,
|
||||
"rotation", es_Rotation, ROTATE_0);
|
||||
|
||||
std::map<std::string, std::string> replace_names;
|
||||
lua_getfield(L, index, "replacements");
|
||||
if (lua_istable(L, -1)) {
|
||||
read_schematic_replacements(L, dschem, lua_gettop(L));
|
||||
}
|
||||
if (lua_istable(L, -1))
|
||||
read_schematic_replacements(L, replace_names, lua_gettop(L));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "schematic");
|
||||
|
@ -452,17 +455,20 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
}
|
||||
lua_pop(L, -1);
|
||||
|
||||
if (!dschem->filename.empty() && !dschem->loadSchematicFile()) {
|
||||
errorstream << "register_decoration: failed to load schematic file '"
|
||||
<< dschem->filename << "'" << std::endl;
|
||||
if (!dschem->filename.empty() &&
|
||||
!dschem->loadSchematicFile(resolver, replace_names)) {
|
||||
errorstream << "register_decoration: failed to load schematic"
|
||||
" file '" << dschem->filename << "'" << std::endl;
|
||||
delete dschem;
|
||||
return 0;
|
||||
}
|
||||
break; }
|
||||
|
||||
break;
|
||||
}
|
||||
case DECO_LSYSTEM: {
|
||||
//DecoLSystem *decolsystem = (DecoLSystem *)deco;
|
||||
|
||||
break; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emerge->decorations.push_back(deco);
|
||||
|
@ -478,7 +484,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
int index = 1;
|
||||
luaL_checktype(L, index, LUA_TTABLE);
|
||||
|
||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
|
||||
enum OreType oretype = (OreType)getenumfield(L, index,
|
||||
"ore_type", es_OreType, ORE_SCATTER);
|
||||
|
@ -489,7 +496,9 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ore->ore_name = getstringfield_default(L, index, "ore", "");
|
||||
resolver->addNode(getstringfield_default(L, index, "ore", ""),
|
||||
"", CONTENT_AIR, &ore->c_ore);
|
||||
|
||||
ore->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0);
|
||||
ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
|
||||
ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
|
||||
|
@ -500,20 +509,10 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
ore->flags = 0;
|
||||
getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
|
||||
|
||||
lua_getfield(L, index, "wherein");
|
||||
if (lua_istable(L, -1)) {
|
||||
int i = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, i) != 0) {
|
||||
ore->wherein_names.push_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isstring(L, -1)) {
|
||||
ore->wherein_names.push_back(lua_tostring(L, -1));
|
||||
} else {
|
||||
ore->wherein_names.push_back("");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
std::vector<const char *> wherein_names;
|
||||
getstringlistfield(L, index, "wherein", wherein_names);
|
||||
for (size_t i = 0; i != wherein_names.size(); i++)
|
||||
resolver->addNodeList(wherein_names[i], &ore->c_wherein);
|
||||
|
||||
lua_getfield(L, index, "noise_params");
|
||||
ore->np = read_noiseparams(L, -1);
|
||||
|
@ -530,8 +529,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
|
||||
emerge->ores.push_back(ore);
|
||||
|
||||
verbosestream << "register_ore: ore '" << ore->ore_name
|
||||
<< "' registered" << std::endl;
|
||||
//verbosestream << "register_ore: ore '" << ore->ore_name
|
||||
// << "' registered" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -603,7 +602,7 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
|
|||
DecoSchematic dschem;
|
||||
|
||||
Map *map = &(getEnv(L)->getMap());
|
||||
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
|
||||
v3s16 p = read_v3s16(L, 1);
|
||||
if (!read_schematic(L, 2, &dschem, getServer(L)))
|
||||
|
@ -615,21 +614,20 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
|
|||
|
||||
dschem.rotation = (Rotation)rot;
|
||||
|
||||
if (lua_istable(L, 4)) {
|
||||
read_schematic_replacements(L, &dschem, 4);
|
||||
}
|
||||
std::map<std::string, std::string> replace_names;
|
||||
if (lua_istable(L, 4))
|
||||
read_schematic_replacements(L, replace_names, 4);
|
||||
|
||||
bool force_placement = true;
|
||||
if (lua_isboolean(L, 5))
|
||||
force_placement = lua_toboolean(L, 5);
|
||||
|
||||
if (!dschem.filename.empty()) {
|
||||
if (!dschem.loadSchematicFile()) {
|
||||
if (!dschem.loadSchematicFile(resolver, replace_names)) {
|
||||
errorstream << "place_schematic: failed to load schematic file '"
|
||||
<< dschem.filename << "'" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
dschem.resolveNodeNames(ndef);
|
||||
}
|
||||
|
||||
dschem.placeStructure(map, p, force_placement);
|
||||
|
|
|
@ -338,6 +338,9 @@ Server::Server(
|
|||
// Apply item aliases in the node definition manager
|
||||
m_nodedef->updateAliases(m_itemdef);
|
||||
|
||||
// Perform pending node name resolutions
|
||||
m_nodedef->getResolver()->resolveNodes();
|
||||
|
||||
// Load the mapgen params from global settings now after any
|
||||
// initial overrides have been set by the mods
|
||||
m_emerge->loadMapgenParams();
|
||||
|
|
Loading…
Reference in New Issue