mirror of
https://github.com/minetest/minetest.git
synced 2024-11-24 00:23:46 +01:00
Add NodeResolver and clean up node name -> content ID resolution system
This commit is contained in:
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);
|
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;
|
biome_registration_finished = false;
|
||||||
np_heat = &nparams_biome_def_heat;
|
np_heat = &nparams_biome_def_heat;
|
||||||
np_humidity = &nparams_biome_def_humidity;
|
np_humidity = &nparams_biome_def_humidity;
|
||||||
@ -41,27 +41,19 @@ BiomeDefManager::BiomeDefManager() {
|
|||||||
b->id = 0;
|
b->id = 0;
|
||||||
b->name = "Default";
|
b->name = "Default";
|
||||||
b->flags = 0;
|
b->flags = 0;
|
||||||
|
|
||||||
b->depth_top = 0;
|
b->depth_top = 0;
|
||||||
b->depth_filler = 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->height_min = -MAP_GENERATION_LIMIT;
|
b->height_min = -MAP_GENERATION_LIMIT;
|
||||||
b->height_max = MAP_GENERATION_LIMIT;
|
b->height_max = MAP_GENERATION_LIMIT;
|
||||||
b->heat_point = 0.0;
|
b->heat_point = 0.0;
|
||||||
b->humidity_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);
|
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) {
|
void BiomeDefManager::addBiome(Biome *b) {
|
||||||
if (biome_registration_finished) {
|
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;
|
delete b;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nbiomes = biomes.size();
|
size_t nbiomes = biomes.size();
|
||||||
if (nbiomes >= 0xFF) {
|
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;
|
delete b;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,13 @@ public:
|
|||||||
std::string name;
|
std::string name;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
|
||||||
|
/*
|
||||||
std::string nname_top;
|
std::string nname_top;
|
||||||
std::string nname_filler;
|
std::string nname_filler;
|
||||||
std::string nname_water;
|
std::string nname_water;
|
||||||
std::string nname_dust;
|
std::string nname_dust;
|
||||||
std::string nname_dust_water;
|
std::string nname_dust_water;
|
||||||
|
*/
|
||||||
|
|
||||||
content_t c_top;
|
content_t c_top;
|
||||||
content_t c_filler;
|
content_t c_filler;
|
||||||
@ -81,7 +83,7 @@ public:
|
|||||||
NoiseParams *np_heat;
|
NoiseParams *np_heat;
|
||||||
NoiseParams *np_humidity;
|
NoiseParams *np_humidity;
|
||||||
|
|
||||||
BiomeDefManager();
|
BiomeDefManager(NodeResolver *resolver);
|
||||||
~BiomeDefManager();
|
~BiomeDefManager();
|
||||||
|
|
||||||
Biome *createBiome(BiomeTerrainType btt);
|
Biome *createBiome(BiomeTerrainType btt);
|
||||||
|
@ -85,7 +85,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
|
|||||||
registerMapgen("singlenode", new MapgenFactorySinglenode());
|
registerMapgen("singlenode", new MapgenFactorySinglenode());
|
||||||
|
|
||||||
this->ndef = gamedef->getNodeDefManager();
|
this->ndef = gamedef->getNodeDefManager();
|
||||||
this->biomedef = new BiomeDefManager();
|
this->biomedef = new BiomeDefManager(gamedef->getNodeDefManager()->getResolver());
|
||||||
this->gennotify = 0;
|
this->gennotify = 0;
|
||||||
|
|
||||||
// Note that accesses to this variable are not synchronized.
|
// Note that accesses to this variable are not synchronized.
|
||||||
@ -145,9 +145,9 @@ EmergeManager::~EmergeManager() {
|
|||||||
delete decorations[i];
|
delete decorations[i];
|
||||||
decorations.clear();
|
decorations.clear();
|
||||||
|
|
||||||
for (std::map<std::string, MapgenFactory *>::iterator iter = mglist.begin();
|
for (std::map<std::string, MapgenFactory *>::iterator it = mglist.begin();
|
||||||
iter != mglist.end(); iter ++) {
|
it != mglist.end(); ++it) {
|
||||||
delete iter->second;
|
delete it->second;
|
||||||
}
|
}
|
||||||
mglist.clear();
|
mglist.clear();
|
||||||
|
|
||||||
@ -176,16 +176,6 @@ void EmergeManager::initMapgens() {
|
|||||||
if (mapgen.size())
|
if (mapgen.size())
|
||||||
return;
|
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) {
|
if (!params.sparams) {
|
||||||
params.sparams = createMapgenParams(params.mg_name);
|
params.sparams = createMapgenParams(params.mg_name);
|
||||||
if (!params.sparams) {
|
if (!params.sparams) {
|
||||||
|
168
src/mapgen.cpp
168
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) {
|
void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||||
int in_range = 0;
|
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,
|
void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
|
||||||
u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||||
PseudoRandom pr(blockseed);
|
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) *
|
int volume = (nmax.X - nmin.X + 1) *
|
||||||
(nmax.Y - nmin.Y + 1) *
|
(nmax.Y - nmin.Y + 1) *
|
||||||
@ -171,8 +149,8 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
|
u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
|
||||||
for (size_t ii = 0; ii < wherein.size(); ii++)
|
for (size_t ii = 0; ii < c_wherein.size(); ii++)
|
||||||
if (vm->m_data[i].getContent() == wherein[ii])
|
if (vm->m_data[i].getContent() == c_wherein[ii])
|
||||||
vm->m_data[i] = n_ore;
|
vm->m_data[i] = n_ore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,7 +160,7 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
|
|||||||
void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
|
void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
|
||||||
u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||||
PseudoRandom pr(blockseed + 4234);
|
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 max_height = clust_size;
|
||||||
int y_start = pr.range(nmin.Y, nmax.Y - max_height);
|
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))
|
if (!vm->m_area.contains(i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (size_t ii = 0; ii < wherein.size(); ii++)
|
for (size_t ii = 0; ii < c_wherein.size(); ii++) {
|
||||||
if (vm->m_data[i].getContent() == wherein[ii])
|
if (vm->m_data[i].getContent() == c_wherein[ii]) {
|
||||||
vm->m_data[i] = n_ore;
|
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) {
|
void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
|
||||||
PseudoRandom ps(blockseed + 53);
|
PseudoRandom ps(blockseed + 53);
|
||||||
int carea_size = nmax.X - nmin.X + 1;
|
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) {
|
void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) {
|
||||||
ManualMapVoxelManipulator *vm = mg->vm;
|
ManualMapVoxelManipulator *vm = mg->vm;
|
||||||
|
|
||||||
u32 vi = vm->m_area.index(p);
|
u32 vi = vm->m_area.index(p);
|
||||||
if (vm->m_data[vi].getContent() != c_place_on &&
|
content_t c = vm->m_data[vi].getContent();
|
||||||
c_place_on != CONTENT_IGNORE)
|
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;
|
return;
|
||||||
|
|
||||||
if (nspawnby != -1) {
|
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++) {
|
for (int i = 0; i != 8; i++) {
|
||||||
u32 index = vm->m_area.index(p + dirs[i]);
|
u32 index = vm->m_area.index(p + dirs[i]);
|
||||||
if (vm->m_area.contains(index) &&
|
if (!vm->m_area.contains(index))
|
||||||
vm->m_data[index].getContent() == c_spawnby)
|
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++;
|
nneighs++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nneighs < nspawnby)
|
if (nneighs < nspawnby)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ndecos = c_decolist.size();
|
if (c_decos.size() == 0)
|
||||||
content_t c_place = ndecos ? c_decolist[pr->range(0, ndecos - 1)] : c_deco;
|
return;
|
||||||
|
content_t c_place = c_decos[pr->range(0, c_decos.size() - 1)];
|
||||||
|
|
||||||
s16 height = (deco_height_max > 0) ?
|
s16 height = (deco_height_max > 0) ?
|
||||||
pr->range(deco_height, deco_height_max) : deco_height;
|
pr->range(deco_height, deco_height_max) : deco_height;
|
||||||
@ -483,7 +433,7 @@ int DecoSimple::getHeight() {
|
|||||||
|
|
||||||
|
|
||||||
std::string DecoSimple::getName() {
|
std::string DecoSimple::getName() {
|
||||||
return deco_name;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -491,7 +441,6 @@ std::string DecoSimple::getName() {
|
|||||||
|
|
||||||
|
|
||||||
DecoSchematic::DecoSchematic() {
|
DecoSchematic::DecoSchematic() {
|
||||||
node_names = NULL;
|
|
||||||
schematic = NULL;
|
schematic = NULL;
|
||||||
slice_probs = NULL;
|
slice_probs = NULL;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
@ -500,47 +449,19 @@ DecoSchematic::DecoSchematic() {
|
|||||||
|
|
||||||
|
|
||||||
DecoSchematic::~DecoSchematic() {
|
DecoSchematic::~DecoSchematic() {
|
||||||
delete node_names;
|
|
||||||
delete []schematic;
|
delete []schematic;
|
||||||
delete []slice_probs;
|
delete []slice_probs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DecoSchematic::resolveNodeNames(INodeDefManager *ndef) {
|
void DecoSchematic::updateContentIds() {
|
||||||
Decoration::resolveNodeNames(ndef);
|
if (flags & DECO_SCHEM_CIDS_UPDATED)
|
||||||
|
|
||||||
if (filename.empty())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!node_names) {
|
flags |= DECO_SCHEM_CIDS_UPDATED;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i != size.X * size.Y * size.Z; i++)
|
for (int i = 0; i != size.X * size.Y * size.Z; i++)
|
||||||
schematic[i].setContent(c_nodes[schematic[i].getContent()]);
|
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;
|
p.Z -= (size.Z + 1) / 2;
|
||||||
|
|
||||||
u32 vi = vm->m_area.index(p);
|
u32 vi = vm->m_area.index(p);
|
||||||
if (vm->m_data[vi].getContent() != c_place_on &&
|
content_t c = vm->m_data[vi].getContent();
|
||||||
c_place_on != CONTENT_IGNORE)
|
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;
|
return;
|
||||||
|
|
||||||
Rotation rot = (rotation == ROTATE_RAND) ?
|
Rotation rot = (rotation == ROTATE_RAND) ?
|
||||||
@ -582,6 +508,8 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
|||||||
int ystride = size.X;
|
int ystride = size.X;
|
||||||
int zstride = size.X * size.Y;
|
int zstride = size.X * size.Y;
|
||||||
|
|
||||||
|
updateContentIds();
|
||||||
|
|
||||||
s16 sx = size.X;
|
s16 sx = size.X;
|
||||||
s16 sy = size.Y;
|
s16 sy = size.Y;
|
||||||
s16 sz = size.Z;
|
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;
|
content_t cignore = CONTENT_IGNORE;
|
||||||
bool have_cignore = false;
|
bool have_cignore = false;
|
||||||
|
|
||||||
@ -730,7 +660,6 @@ bool DecoSchematic::loadSchematicFile() {
|
|||||||
|
|
||||||
u16 nidmapcount = readU16(is);
|
u16 nidmapcount = readU16(is);
|
||||||
|
|
||||||
node_names = new std::vector<std::string>;
|
|
||||||
for (int i = 0; i != nidmapcount; i++) {
|
for (int i = 0; i != nidmapcount; i++) {
|
||||||
std::string name = deSerializeString(is);
|
std::string name = deSerializeString(is);
|
||||||
if (name == "ignore") {
|
if (name == "ignore") {
|
||||||
@ -738,7 +667,14 @@ bool DecoSchematic::loadSchematicFile() {
|
|||||||
cignore = i;
|
cignore = i;
|
||||||
have_cignore = true;
|
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;
|
delete []schematic;
|
||||||
|
31
src/mapgen.h
31
src/mapgen.h
@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define DECO_PLACE_CENTER_X 1
|
#define DECO_PLACE_CENTER_X 1
|
||||||
#define DECO_PLACE_CENTER_Y 2
|
#define DECO_PLACE_CENTER_Y 2
|
||||||
#define DECO_PLACE_CENTER_Z 4
|
#define DECO_PLACE_CENTER_Z 4
|
||||||
|
#define DECO_SCHEM_CIDS_UPDATED 8
|
||||||
|
|
||||||
#define ORE_RANGE_ACTUAL 1
|
#define ORE_RANGE_ACTUAL 1
|
||||||
#define ORE_RANGE_MIRROR 2
|
#define ORE_RANGE_MIRROR 2
|
||||||
@ -164,10 +165,8 @@ struct MapgenFactory {
|
|||||||
|
|
||||||
class Ore {
|
class Ore {
|
||||||
public:
|
public:
|
||||||
std::string ore_name;
|
content_t c_ore; // the node to place
|
||||||
std::vector<std::string> wherein_names;
|
std::vector<content_t> c_wherein; // the nodes to be placed in
|
||||||
content_t ore;
|
|
||||||
std::vector<content_t> wherein; // the node to be replaced
|
|
||||||
u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing at a node
|
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_num_ores; // how many ore nodes are in a chunk
|
||||||
s16 clust_size; // how large (in nodes) a chunk of ore is
|
s16 clust_size; // how large (in nodes) a chunk of ore is
|
||||||
@ -180,14 +179,13 @@ public:
|
|||||||
Noise *noise;
|
Noise *noise;
|
||||||
|
|
||||||
Ore() {
|
Ore() {
|
||||||
ore = CONTENT_IGNORE;
|
c_ore = CONTENT_IGNORE;
|
||||||
np = NULL;
|
np = NULL;
|
||||||
noise = NULL;
|
noise = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Ore();
|
virtual ~Ore();
|
||||||
|
|
||||||
void resolveNodeNames(INodeDefManager *ndef);
|
|
||||||
void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||||
virtual void generate(ManualMapVoxelManipulator *vm, int seed,
|
virtual void generate(ManualMapVoxelManipulator *vm, int seed,
|
||||||
u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
|
u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
|
||||||
@ -234,8 +232,7 @@ public:
|
|||||||
INodeDefManager *ndef;
|
INodeDefManager *ndef;
|
||||||
|
|
||||||
int mapseed;
|
int mapseed;
|
||||||
std::string place_on_name;
|
std::vector<content_t> c_place_on;
|
||||||
content_t c_place_on;
|
|
||||||
s16 sidelen;
|
s16 sidelen;
|
||||||
float fill_ratio;
|
float fill_ratio;
|
||||||
NoiseParams *np;
|
NoiseParams *np;
|
||||||
@ -247,7 +244,6 @@ public:
|
|||||||
Decoration();
|
Decoration();
|
||||||
virtual ~Decoration();
|
virtual ~Decoration();
|
||||||
|
|
||||||
virtual void resolveNodeNames(INodeDefManager *ndef);
|
|
||||||
void placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
void placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||||
void placeCutoffs(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 {
|
class DecoSimple : public Decoration {
|
||||||
public:
|
public:
|
||||||
std::string deco_name;
|
std::vector<content_t> c_decos;
|
||||||
std::string spawnby_name;
|
std::vector<content_t> c_spawnby;
|
||||||
content_t c_deco;
|
|
||||||
content_t c_spawnby;
|
|
||||||
s16 deco_height;
|
s16 deco_height;
|
||||||
s16 deco_height_max;
|
s16 deco_height_max;
|
||||||
s16 nspawnby;
|
s16 nspawnby;
|
||||||
|
|
||||||
std::vector<std::string> decolist_names;
|
|
||||||
std::vector<content_t> c_decolist;
|
|
||||||
|
|
||||||
~DecoSimple() {}
|
~DecoSimple() {}
|
||||||
|
|
||||||
void resolveNodeNames(INodeDefManager *ndef);
|
|
||||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||||
virtual int getHeight();
|
virtual int getHeight();
|
||||||
virtual std::string getName();
|
virtual std::string getName();
|
||||||
@ -288,9 +278,7 @@ class DecoSchematic : public Decoration {
|
|||||||
public:
|
public:
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
|
||||||
std::vector<std::string> *node_names;
|
|
||||||
std::vector<content_t> c_nodes;
|
std::vector<content_t> c_nodes;
|
||||||
std::map<std::string, std::string> replacements;
|
|
||||||
|
|
||||||
u32 flags;
|
u32 flags;
|
||||||
Rotation rotation;
|
Rotation rotation;
|
||||||
@ -301,7 +289,7 @@ public:
|
|||||||
DecoSchematic();
|
DecoSchematic();
|
||||||
~DecoSchematic();
|
~DecoSchematic();
|
||||||
|
|
||||||
void resolveNodeNames(INodeDefManager *ndef);
|
void updateContentIds();
|
||||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||||
virtual int getHeight();
|
virtual int getHeight();
|
||||||
virtual std::string getName();
|
virtual std::string getName();
|
||||||
@ -309,7 +297,8 @@ public:
|
|||||||
void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
||||||
Rotation rot, bool force_placement);
|
Rotation rot, bool force_placement);
|
||||||
|
|
||||||
bool loadSchematicFile();
|
bool loadSchematicFile(NodeResolver *resolver,
|
||||||
|
std::map<std::string, std::string> &replace_names);
|
||||||
void saveSchematicFile(INodeDefManager *ndef);
|
void saveSchematicFile(INodeDefManager *ndef);
|
||||||
|
|
||||||
bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
|
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);
|
virtual void updateTextures(IGameDef *gamedef);
|
||||||
void serialize(std::ostream &os, u16 protocol_version);
|
void serialize(std::ostream &os, u16 protocol_version);
|
||||||
void deSerialize(std::istream &is);
|
void deSerialize(std::istream &is);
|
||||||
|
virtual NodeResolver *getResolver();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addNameIdMapping(content_t i, std::string name);
|
void addNameIdMapping(content_t i, std::string name);
|
||||||
@ -430,10 +431,14 @@ private:
|
|||||||
|
|
||||||
// Next possibly free id
|
// Next possibly free id
|
||||||
content_t m_next_id;
|
content_t m_next_id;
|
||||||
|
|
||||||
|
// NodeResolver to queue pending node resolutions
|
||||||
|
NodeResolver m_resolver;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CNodeDefManager::CNodeDefManager()
|
CNodeDefManager::CNodeDefManager() :
|
||||||
|
m_resolver(this)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
@ -1017,6 +1022,12 @@ void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NodeResolver *CNodeDefManager::getResolver()
|
||||||
|
{
|
||||||
|
return &m_resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IWritableNodeDefManager *createNodeDefManager()
|
IWritableNodeDefManager *createNodeDefManager()
|
||||||
{
|
{
|
||||||
return new CNodeDefManager();
|
return new CNodeDefManager();
|
||||||
@ -1242,3 +1253,157 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||||||
throw SerializationError("unsupported ContentFeatures 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
|
class INodeDefManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -298,6 +332,8 @@ public:
|
|||||||
virtual const ContentFeatures& get(const std::string &name) const=0;
|
virtual const ContentFeatures& get(const std::string &name) const=0;
|
||||||
|
|
||||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||||
|
|
||||||
|
virtual NodeResolver *getResolver()=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IWritableNodeDefManager : public INodeDefManager
|
class IWritableNodeDefManager : public INodeDefManager
|
||||||
@ -338,6 +374,8 @@ public:
|
|||||||
|
|
||||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||||
virtual void deSerialize(std::istream &is)=0;
|
virtual void deSerialize(std::istream &is)=0;
|
||||||
|
|
||||||
|
virtual NodeResolver *getResolver()=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
IWritableNodeDefManager *createNodeDefManager();
|
IWritableNodeDefManager *createNodeDefManager();
|
||||||
|
@ -227,6 +227,25 @@ std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
|
|||||||
return boxes;
|
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
|
Table field getters
|
||||||
*/
|
*/
|
||||||
@ -287,6 +306,17 @@ bool getboolfield(lua_State *L, int table,
|
|||||||
return got;
|
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,
|
std::string checkstringfield(lua_State *L, int table,
|
||||||
const char *fieldname)
|
const char *fieldname)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,9 @@ int getintfield_default (lua_State *L, int table,
|
|||||||
|
|
||||||
bool getstringfield(lua_State *L, int table,
|
bool getstringfield(lua_State *L, int table,
|
||||||
const char *fieldname, std::string &result);
|
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,
|
bool getintfield(lua_State *L, int table,
|
||||||
const char *fieldname, int &result);
|
const char *fieldname, int &result);
|
||||||
void read_groups(lua_State *L, int index,
|
void read_groups(lua_State *L, int index,
|
||||||
@ -79,8 +82,9 @@ v2s32 read_v2s32 (lua_State *L, int index);
|
|||||||
video::SColor readARGB8 (lua_State *L, int index);
|
video::SColor readARGB8 (lua_State *L, int index);
|
||||||
aabb3f read_aabb3f (lua_State *L, int index, f32 scale);
|
aabb3f read_aabb3f (lua_State *L, int index, f32 scale);
|
||||||
v3s16 read_v3s16 (lua_State *L, int index);
|
v3s16 read_v3s16 (lua_State *L, int index);
|
||||||
std::vector<aabb3f>
|
std::vector<aabb3f> read_aabb3f_vector (lua_State *L, int index, f32 scale);
|
||||||
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 push_v3s16 (lua_State *L, v3s16 p);
|
||||||
void pushFloatPos (lua_State *L, v3f p);
|
void pushFloatPos (lua_State *L, v3f p);
|
||||||
|
@ -80,17 +80,19 @@ 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);
|
lua_pushnil(L);
|
||||||
while (lua_next(L, index)) {
|
while (lua_next(L, index)) {
|
||||||
// key at index -2 and value at index -1
|
|
||||||
std::string replace_from;
|
std::string replace_from;
|
||||||
std::string replace_to;
|
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);
|
lua_rawgeti(L, -1, 1);
|
||||||
replace_from = lua_tostring(L, -1);
|
replace_from = lua_tostring(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_rawgeti(L, -1, 2);
|
lua_rawgeti(L, -1, 2);
|
||||||
replace_to = lua_tostring(L, -1);
|
replace_to = lua_tostring(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
@ -98,8 +100,8 @@ static void read_schematic_replacements(lua_State *L, DecoSchematic *dschem, int
|
|||||||
replace_from = lua_tostring(L, -2);
|
replace_from = lua_tostring(L, -2);
|
||||||
replace_to = lua_tostring(L, -1);
|
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);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,6 +300,7 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||||||
int index = 1;
|
int index = 1;
|
||||||
luaL_checktype(L, index, LUA_TTABLE);
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
|
||||||
|
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||||
BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
|
BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
|
||||||
if (!bmgr) {
|
if (!bmgr) {
|
||||||
verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
|
verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
|
||||||
@ -308,32 +311,25 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||||||
"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
|
"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
|
||||||
Biome *b = bmgr->createBiome(terrain);
|
Biome *b = bmgr->createBiome(terrain);
|
||||||
|
|
||||||
b->name = getstringfield_default(L, index, "name",
|
resolver->addNode(getstringfield_default(L, index, "node_top", ""),
|
||||||
"<no name>");
|
"mapgen_dirt_with_grass", CONTENT_AIR, &b->c_top);
|
||||||
b->nname_top = getstringfield_default(L, index, "node_top",
|
resolver->addNode(getstringfield_default(L, index, "node_filler", ""),
|
||||||
"mapgen_dirt_with_grass");
|
"mapgen_dirt", CONTENT_AIR, &b->c_filler);
|
||||||
b->nname_filler = getstringfield_default(L, index, "node_filler",
|
resolver->addNode(getstringfield_default(L, index, "node_water", ""),
|
||||||
"mapgen_dirt");
|
"mapgen_water_source", CONTENT_AIR, &b->c_water);
|
||||||
b->nname_water = getstringfield_default(L, index, "node_water",
|
resolver->addNode(getstringfield_default(L, index, "node_dust", ""),
|
||||||
"mapgen_water_source");
|
"air", CONTENT_IGNORE, &b->c_dust);
|
||||||
b->nname_dust = getstringfield_default(L, index, "node_dust",
|
resolver->addNode(getstringfield_default(L, index, "node_dust_water", ""),
|
||||||
"air");
|
"mapgen_water_source", CONTENT_IGNORE, &b->c_dust_water);
|
||||||
b->nname_dust_water = getstringfield_default(L, index, "node_dust_water",
|
|
||||||
"mapgen_water_source");
|
|
||||||
|
|
||||||
|
b->name = getstringfield_default(L, index, "name", "<no name>");
|
||||||
b->depth_top = getintfield_default(L, index, "depth_top", 1);
|
b->depth_top = getintfield_default(L, index, "depth_top", 1);
|
||||||
b->depth_filler = getintfield_default(L, index, "depth_filler", 3);
|
b->depth_filler = getintfield_default(L, index, "depth_filler", 3);
|
||||||
b->height_min = getintfield_default(L, index, "height_min", 0);
|
b->height_min = getintfield_default(L, index, "height_min", 0);
|
||||||
b->height_max = getintfield_default(L, index, "height_max", 0);
|
b->height_max = getintfield_default(L, index, "height_max", 0);
|
||||||
b->heat_point = getfloatfield_default(L, index, "heat_point", 0.);
|
b->heat_point = getfloatfield_default(L, index, "heat_point", 0.);
|
||||||
b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
|
b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
|
||||||
|
|
||||||
b->flags = 0; //reserved
|
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;
|
|
||||||
|
|
||||||
verbosestream << "register_biome: " << b->name << std::endl;
|
verbosestream << "register_biome: " << b->name << std::endl;
|
||||||
bmgr->addBiome(b);
|
bmgr->addBiome(b);
|
||||||
@ -349,6 +345,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
|
|
||||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||||
BiomeDefManager *bdef = emerge->biomedef;
|
BiomeDefManager *bdef = emerge->biomedef;
|
||||||
|
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||||
|
|
||||||
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
|
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
|
||||||
"deco_type", es_DecorationType, 0);
|
"deco_type", es_DecorationType, 0);
|
||||||
@ -365,8 +362,6 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
return 0;
|
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->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
||||||
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
||||||
if (deco->sidelen <= 0) {
|
if (deco->sidelen <= 0) {
|
||||||
@ -376,51 +371,35 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
return 0;
|
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");
|
lua_getfield(L, index, "noise_params");
|
||||||
deco->np = read_noiseparams(L, -1);
|
deco->np = read_noiseparams(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L, index, "biomes");
|
//// Get biomes associated with this decoration (if any)
|
||||||
if (lua_istable(L, -1)) {
|
std::vector<const char *> biome_list;
|
||||||
lua_pushnil(L);
|
getstringlistfield(L, index, "biomes", biome_list);
|
||||||
while (lua_next(L, -2)) {
|
for (size_t i = 0; i != biome_list.size(); i++) {
|
||||||
const char *s = lua_tostring(L, -1);
|
u8 biomeid = bdef->getBiomeIdByName(biome_list[i]);
|
||||||
u8 biomeid = bdef->getBiomeIdByName(s);
|
|
||||||
if (biomeid)
|
if (biomeid)
|
||||||
deco->biomes.insert(biomeid);
|
deco->biomes.insert(biomeid);
|
||||||
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//// Handle decoration type-specific parameters
|
||||||
switch (decotype) {
|
switch (decotype) {
|
||||||
case DECO_SIMPLE: {
|
case DECO_SIMPLE: {
|
||||||
DecoSimple *dsimple = (DecoSimple *)deco;
|
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 = getintfield_default(L, index, "height", 1);
|
||||||
dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
||||||
dsimple->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
|
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) {
|
if (dsimple->deco_height <= 0) {
|
||||||
errorstream << "register_decoration: simple decoration height"
|
errorstream << "register_decoration: simple decoration height"
|
||||||
" must be greater than 0" << std::endl;
|
" must be greater than 0" << std::endl;
|
||||||
@ -428,7 +407,31 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
return 0;
|
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: {
|
case DECO_SCHEMATIC: {
|
||||||
DecoSchematic *dschem = (DecoSchematic *)deco;
|
DecoSchematic *dschem = (DecoSchematic *)deco;
|
||||||
|
|
||||||
@ -439,10 +442,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
dschem->rotation = (Rotation)getenumfield(L, index,
|
dschem->rotation = (Rotation)getenumfield(L, index,
|
||||||
"rotation", es_Rotation, ROTATE_0);
|
"rotation", es_Rotation, ROTATE_0);
|
||||||
|
|
||||||
|
std::map<std::string, std::string> replace_names;
|
||||||
lua_getfield(L, index, "replacements");
|
lua_getfield(L, index, "replacements");
|
||||||
if (lua_istable(L, -1)) {
|
if (lua_istable(L, -1))
|
||||||
read_schematic_replacements(L, dschem, lua_gettop(L));
|
read_schematic_replacements(L, replace_names, lua_gettop(L));
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L, index, "schematic");
|
lua_getfield(L, index, "schematic");
|
||||||
@ -452,17 +455,20 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||||||
}
|
}
|
||||||
lua_pop(L, -1);
|
lua_pop(L, -1);
|
||||||
|
|
||||||
if (!dschem->filename.empty() && !dschem->loadSchematicFile()) {
|
if (!dschem->filename.empty() &&
|
||||||
errorstream << "register_decoration: failed to load schematic file '"
|
!dschem->loadSchematicFile(resolver, replace_names)) {
|
||||||
<< dschem->filename << "'" << std::endl;
|
errorstream << "register_decoration: failed to load schematic"
|
||||||
|
" file '" << dschem->filename << "'" << std::endl;
|
||||||
delete dschem;
|
delete dschem;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break; }
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DECO_LSYSTEM: {
|
case DECO_LSYSTEM: {
|
||||||
//DecoLSystem *decolsystem = (DecoLSystem *)deco;
|
//DecoLSystem *decolsystem = (DecoLSystem *)deco;
|
||||||
|
break;
|
||||||
break; }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emerge->decorations.push_back(deco);
|
emerge->decorations.push_back(deco);
|
||||||
@ -479,6 +485,7 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||||||
luaL_checktype(L, index, LUA_TTABLE);
|
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,
|
enum OreType oretype = (OreType)getenumfield(L, index,
|
||||||
"ore_type", es_OreType, ORE_SCATTER);
|
"ore_type", es_OreType, ORE_SCATTER);
|
||||||
@ -489,7 +496,9 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||||||
return 0;
|
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->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0);
|
||||||
ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
|
ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
|
||||||
ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 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;
|
ore->flags = 0;
|
||||||
getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
|
getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
|
||||||
|
|
||||||
lua_getfield(L, index, "wherein");
|
std::vector<const char *> wherein_names;
|
||||||
if (lua_istable(L, -1)) {
|
getstringlistfield(L, index, "wherein", wherein_names);
|
||||||
int i = lua_gettop(L);
|
for (size_t i = 0; i != wherein_names.size(); i++)
|
||||||
lua_pushnil(L);
|
resolver->addNodeList(wherein_names[i], &ore->c_wherein);
|
||||||
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);
|
|
||||||
|
|
||||||
lua_getfield(L, index, "noise_params");
|
lua_getfield(L, index, "noise_params");
|
||||||
ore->np = read_noiseparams(L, -1);
|
ore->np = read_noiseparams(L, -1);
|
||||||
@ -530,8 +529,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||||||
|
|
||||||
emerge->ores.push_back(ore);
|
emerge->ores.push_back(ore);
|
||||||
|
|
||||||
verbosestream << "register_ore: ore '" << ore->ore_name
|
//verbosestream << "register_ore: ore '" << ore->ore_name
|
||||||
<< "' registered" << std::endl;
|
// << "' registered" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +602,7 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
|
|||||||
DecoSchematic dschem;
|
DecoSchematic dschem;
|
||||||
|
|
||||||
Map *map = &(getEnv(L)->getMap());
|
Map *map = &(getEnv(L)->getMap());
|
||||||
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||||
|
|
||||||
v3s16 p = read_v3s16(L, 1);
|
v3s16 p = read_v3s16(L, 1);
|
||||||
if (!read_schematic(L, 2, &dschem, getServer(L)))
|
if (!read_schematic(L, 2, &dschem, getServer(L)))
|
||||||
@ -615,21 +614,20 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
|
|||||||
|
|
||||||
dschem.rotation = (Rotation)rot;
|
dschem.rotation = (Rotation)rot;
|
||||||
|
|
||||||
if (lua_istable(L, 4)) {
|
std::map<std::string, std::string> replace_names;
|
||||||
read_schematic_replacements(L, &dschem, 4);
|
if (lua_istable(L, 4))
|
||||||
}
|
read_schematic_replacements(L, replace_names, 4);
|
||||||
|
|
||||||
bool force_placement = true;
|
bool force_placement = true;
|
||||||
if (lua_isboolean(L, 5))
|
if (lua_isboolean(L, 5))
|
||||||
force_placement = lua_toboolean(L, 5);
|
force_placement = lua_toboolean(L, 5);
|
||||||
|
|
||||||
if (!dschem.filename.empty()) {
|
if (!dschem.filename.empty()) {
|
||||||
if (!dschem.loadSchematicFile()) {
|
if (!dschem.loadSchematicFile(resolver, replace_names)) {
|
||||||
errorstream << "place_schematic: failed to load schematic file '"
|
errorstream << "place_schematic: failed to load schematic file '"
|
||||||
<< dschem.filename << "'" << std::endl;
|
<< dschem.filename << "'" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dschem.resolveNodeNames(ndef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dschem.placeStructure(map, p, force_placement);
|
dschem.placeStructure(map, p, force_placement);
|
||||||
|
@ -338,6 +338,9 @@ Server::Server(
|
|||||||
// Apply item aliases in the node definition manager
|
// Apply item aliases in the node definition manager
|
||||||
m_nodedef->updateAliases(m_itemdef);
|
m_nodedef->updateAliases(m_itemdef);
|
||||||
|
|
||||||
|
// Perform pending node name resolutions
|
||||||
|
m_nodedef->getResolver()->resolveNodes();
|
||||||
|
|
||||||
// Load the mapgen params from global settings now after any
|
// Load the mapgen params from global settings now after any
|
||||||
// initial overrides have been set by the mods
|
// initial overrides have been set by the mods
|
||||||
m_emerge->loadMapgenParams();
|
m_emerge->loadMapgenParams();
|
||||||
|
Loading…
Reference in New Issue
Block a user