Add Generator Element Management framework

Add BiomeManager, OreManager, DecorationManager, and SchematicManager
This commit is contained in:
kwolekr 2014-11-12 23:01:13 -05:00
parent f25cc0dbae
commit 7616537bc0
22 changed files with 620 additions and 464 deletions

@ -40,8 +40,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include "nodedef.h" #include "nodedef.h"
#include "mg_biome.h" #include "mg_biome.h"
#include "mg_decoration.h"
#include "mg_ore.h" #include "mg_ore.h"
#include "mg_decoration.h"
#include "mg_schematic.h"
#include "mapgen_v5.h" #include "mapgen_v5.h"
#include "mapgen_v6.h" #include "mapgen_v6.h"
#include "mapgen_v7.h" #include "mapgen_v7.h"
@ -89,7 +90,10 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
registerMapgen("singlenode", new MapgenFactorySinglenode()); registerMapgen("singlenode", new MapgenFactorySinglenode());
this->ndef = gamedef->getNodeDefManager(); this->ndef = gamedef->getNodeDefManager();
this->biomedef = new BiomeDefManager(gamedef->getNodeDefManager()->getResolver()); this->biomemgr = new BiomeManager(gamedef);
this->oremgr = new OreManager(gamedef);
this->decomgr = new DecorationManager(gamedef);
this->schemmgr = new SchematicManager(gamedef);
this->gennotify = 0; this->gennotify = 0;
// Note that accesses to this variable are not synchronized. // Note that accesses to this variable are not synchronized.
@ -141,21 +145,15 @@ EmergeManager::~EmergeManager() {
emergethread.clear(); emergethread.clear();
mapgen.clear(); mapgen.clear();
for (unsigned int i = 0; i < ores.size(); i++) std::map<std::string, MapgenFactory *>::iterator it;
delete ores[i]; for (it = mglist.begin(); it != mglist.end(); ++it)
ores.clear();
for (unsigned int i = 0; i < decorations.size(); i++)
delete decorations[i];
decorations.clear();
for (std::map<std::string, MapgenFactory *>::iterator it = mglist.begin();
it != mglist.end(); ++it) {
delete it->second; delete it->second;
}
mglist.clear(); mglist.clear();
delete biomedef; delete biomemgr;
delete oremgr;
delete decomgr;
delete schemmgr;
if (params.sparams) { if (params.sparams) {
delete params.sparams; delete params.sparams;

@ -23,8 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <map> #include <map>
#include "irr_v3d.h" #include "irr_v3d.h"
#include "util/container.h" #include "util/container.h"
#include "map.h" // for ManualMapVoxelManipulator
#include "mapgen.h" // for MapgenParams #include "mapgen.h" // for MapgenParams
#include "map.h"
#define MGPARAMS_SET_MGNAME 1 #define MGPARAMS_SET_MGNAME 1
#define MGPARAMS_SET_SEED 2 #define MGPARAMS_SET_SEED 2
@ -34,16 +34,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define BLOCK_EMERGE_ALLOWGEN (1<<0) #define BLOCK_EMERGE_ALLOWGEN (1<<0)
#define EMERGE_DBG_OUT(x) \ #define EMERGE_DBG_OUT(x) \
{ if (enable_mapgen_debug_info) \ do { \
infostream << "EmergeThread: " x << std::endl; } if (enable_mapgen_debug_info) \
infostream << "EmergeThread: " x << std::endl; \
} while (0)
class EmergeThread; class EmergeThread;
class Biome;
class BiomeDefManager;
class Decoration;
class Ore;
class INodeDefManager; class INodeDefManager;
class Settings; class Settings;
//class ManualMapVoxelManipulator;
class BiomeManager;
class OreManager;
class DecorationManager;
class SchematicManager;
struct BlockMakeData { struct BlockMakeData {
ManualMapVoxelManipulator *vmanip; ManualMapVoxelManipulator *vmanip;
@ -88,16 +92,18 @@ public:
u32 gennotify; u32 gennotify;
//block emerge queue data structures //// Block emerge queue data structures
JMutex queuemutex; JMutex queuemutex;
std::map<v3s16, BlockEmergeData *> blocks_enqueued; std::map<v3s16, BlockEmergeData *> blocks_enqueued;
std::map<u16, u16> peer_queue_count; std::map<u16, u16> peer_queue_count;
//Mapgen-related structures //// Managers of map generation-related components
BiomeDefManager *biomedef; BiomeManager *biomemgr;
std::vector<Ore *> ores; OreManager *oremgr;
std::vector<Decoration *> decorations; DecorationManager *decomgr;
SchematicManager *schemmgr;
//// Methods
EmergeManager(IGameDef *gamedef); EmergeManager(IGameDef *gamedef);
~EmergeManager(); ~EmergeManager();

@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h" #include "filesys.h"
#include "log.h" #include "log.h"
const char *GenElementManager::ELEMENT_TITLE = "element";
FlagDesc flagdesc_mapgen[] = { FlagDesc flagdesc_mapgen[] = {
{"trees", MG_TREES}, {"trees", MG_TREES},
@ -57,16 +58,10 @@ FlagDesc flagdesc_gennotify[] = {
{NULL, 0} {NULL, 0}
}; };
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Mapgen::Mapgen() { Mapgen::Mapgen() {
seed = 0; seed = 0;
water_level = 0; water_level = 0;
@ -290,3 +285,78 @@ void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) {
vm->spreadLight(bank, light_sources, ndef); vm->spreadLight(bank, light_sources, ndef);
} }
} }
///////////////////////////////////////////////////////////////////////////////
GenElementManager::~GenElementManager()
{
for (size_t i = 0; i != m_elements.size(); i++)
delete m_elements[i];
}
u32 GenElementManager::add(GenElement *elem)
{
size_t nelem = m_elements.size();
for (size_t i = 0; i != nelem; i++) {
if (m_elements[i] == NULL) {
elem->id = i;
m_elements[i] = elem;
return i;
}
}
if (nelem >= this->ELEMENT_LIMIT)
return -1;
elem->id = nelem;
m_elements.push_back(elem);
verbosestream << "GenElementManager: added " << this->ELEMENT_TITLE
<< " element '" << elem->name << "'" << std::endl;
return nelem;
}
GenElement *GenElementManager::get(u32 id)
{
return (id < m_elements.size()) ? m_elements[id] : NULL;
}
GenElement *GenElementManager::getByName(const char *name)
{
for (size_t i = 0; i != m_elements.size(); i++) {
GenElement *elem = m_elements[i];
if (elem && !strcmp(elem->name.c_str(), name))
return elem;
}
return NULL;
}
GenElement *GenElementManager::getByName(std::string &name)
{
return getByName(name.c_str());
}
GenElement *GenElementManager::update(u32 id, GenElement *elem)
{
if (id >= m_elements.size())
return false;
GenElement *old_elem = m_elements[id];
m_elements[id] = elem;
return old_elem;
}
GenElement *GenElementManager::remove(u32 id)
{
return update(id, NULL);
}

@ -20,13 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef MAPGEN_HEADER #ifndef MAPGEN_HEADER
#define MAPGEN_HEADER #define MAPGEN_HEADER
#include "irrlichttypes_bloated.h"
#include "util/container.h" // UniqueQueue
#include "gamedef.h"
#include "nodedef.h" #include "nodedef.h"
#include "mapnode.h" #include "mapnode.h"
#include "noise.h" #include "util/string.h"
#include "settings.h" #include "util/container.h"
#define DEFAULT_MAPGEN "v6" #define DEFAULT_MAPGEN "v6"
@ -39,11 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define NUM_GEN_NOTIFY 6 #define NUM_GEN_NOTIFY 6
class Settings;
class ManualMapVoxelManipulator;
class INodeDefManager;
extern FlagDesc flagdesc_mapgen[]; extern FlagDesc flagdesc_mapgen[];
extern FlagDesc flagdesc_gennotify[]; extern FlagDesc flagdesc_gennotify[];
class BiomeDefManager;
class Biome; class Biome;
class EmergeManager; class EmergeManager;
class MapBlock; class MapBlock;
@ -53,7 +52,6 @@ struct BlockMakeData;
class VoxelArea; class VoxelArea;
class Map; class Map;
enum MapgenObject { enum MapgenObject {
MGOBJ_VMANIP, MGOBJ_VMANIP,
MGOBJ_HEIGHTMAP, MGOBJ_HEIGHTMAP,
@ -136,5 +134,32 @@ struct MapgenFactory {
virtual ~MapgenFactory() {} virtual ~MapgenFactory() {}
}; };
#endif class GenElement {
public:
uint32_t id;
std::string name;
};
class GenElementManager {
public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = -1;
GenElementManager() {}
virtual ~GenElementManager();
virtual GenElement *create(int type) = 0;
virtual u32 add(GenElement *elem);
virtual GenElement *get(u32 id);
virtual GenElement *update(u32 id, GenElement *elem);
virtual GenElement *remove(u32 id);
virtual GenElement *getByName(const char *name);
virtual GenElement *getByName(std::string &name);
protected:
std::vector<GenElement *> m_elements;
};
#endif

@ -51,7 +51,7 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) {
this->generating = false; this->generating = false;
this->id = mapgenid; this->id = mapgenid;
this->emerge = emerge_; this->emerge = emerge_;
this->bmgr = emerge->biomedef; this->bmgr = emerge->biomemgr;
this->seed = (int)params->seed; this->seed = (int)params->seed;
this->water_level = params->water_level; this->water_level = params->water_level;
@ -247,16 +247,10 @@ void MapgenV5::makeChunk(BlockMakeData *data) {
} }
// Generate the registered decorations // Generate the registered decorations
for (size_t i = 0; i != emerge->decorations.size(); i++) { emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
Decoration *deco = emerge->decorations[i];
deco->placeDeco(this, blockseed + i, node_min, node_max);
}
// Generate the registered ores // Generate the registered ores
for (unsigned int i = 0; i != emerge->ores.size(); i++) { emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
Ore *ore = emerge->ores[i];
ore->placeOre(this, blockseed + i, node_min, node_max);
}
// Sprinkle some dust on top after everything else was generated // Sprinkle some dust on top after everything else was generated
dustTopNodes(); dustTopNodes();
@ -405,7 +399,7 @@ void MapgenV5::generateBiomes() {
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
Biome *biome = bmgr->biomes[biomemap[index]]; Biome *biome = (Biome *)bmgr->get(biomemap[index]);
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index]; s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
s16 y0_top = biome->depth_top; s16 y0_top = biome->depth_top;
s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller; s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller;
@ -467,7 +461,7 @@ void MapgenV5::dustTopNodes() {
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
Biome *biome = bmgr->biomes[biomemap[index]]; Biome *biome = (Biome *)bmgr->get(biomemap[index]);
if (biome->c_dust == CONTENT_IGNORE) if (biome->c_dust == CONTENT_IGNORE)
continue; continue;

@ -50,7 +50,7 @@ struct MapgenV5Params : public MapgenSpecificParams {
class MapgenV5 : public Mapgen { class MapgenV5 : public Mapgen {
public: public:
EmergeManager *emerge; EmergeManager *emerge;
BiomeDefManager *bmgr; BiomeManager *bmgr;
int ystride; int ystride;
int zstride; int zstride;

@ -537,16 +537,10 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
placeTreesAndJungleGrass(); placeTreesAndJungleGrass();
// Generate the registered decorations // Generate the registered decorations
for (unsigned int i = 0; i != emerge->decorations.size(); i++) { emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
Decoration *deco = emerge->decorations[i];
deco->placeDeco(this, blockseed + i, node_min, node_max);
}
// Generate the registered ores // Generate the registered ores
for (unsigned int i = 0; i != emerge->ores.size(); i++) { emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
Ore *ore = emerge->ores[i];
ore->placeOre(this, blockseed + i, node_min, node_max);
}
// Calculate lighting // Calculate lighting
if (flags & MG_LIGHT) if (flags & MG_LIGHT)

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MAPGENV6_HEADER #define MAPGENV6_HEADER
#include "mapgen.h" #include "mapgen.h"
#include "noise.h"
#define AVERAGE_MUD_AMOUNT 4 #define AVERAGE_MUD_AMOUNT 4

@ -53,7 +53,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) {
this->generating = false; this->generating = false;
this->id = mapgenid; this->id = mapgenid;
this->emerge = emerge; this->emerge = emerge;
this->bmgr = emerge->biomedef; this->bmgr = emerge->biomemgr;
this->seed = (int)params->seed; this->seed = (int)params->seed;
this->water_level = params->water_level; this->water_level = params->water_level;
@ -250,15 +250,11 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
dgen.generate(blockseed, full_node_min, full_node_max); dgen.generate(blockseed, full_node_min, full_node_max);
} }
for (size_t i = 0; i != emerge->decorations.size(); i++) { // Generate the registered decorations
Decoration *deco = emerge->decorations[i]; emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
deco->placeDeco(this, blockseed + i, node_min, node_max);
}
for (size_t i = 0; i != emerge->ores.size(); i++) { // Generate the registered ores
Ore *ore = emerge->ores[i]; emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
ore->placeOre(this, blockseed + i, node_min, node_max);
}
// Sprinkle some dust on top after everything else was generated // Sprinkle some dust on top after everything else was generated
dustTopNodes(); dustTopNodes();
@ -538,7 +534,7 @@ void MapgenV7::generateBiomes() {
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
Biome *biome = bmgr->biomes[biomemap[index]]; Biome *biome = (Biome *)bmgr->get(biomemap[index]);
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index]; s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
s16 y0_top = biome->depth_top; s16 y0_top = biome->depth_top;
s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller; s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller;
@ -607,7 +603,7 @@ void MapgenV7::dustTopNodes() {
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
Biome *biome = bmgr->biomes[biomemap[index]]; Biome *biome = (Biome *)bmgr->get(biomemap[index]);
if (biome->c_dust == CONTENT_IGNORE) if (biome->c_dust == CONTENT_IGNORE)
continue; continue;

@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MGV7_MOUNTAINS 0x01 #define MGV7_MOUNTAINS 0x01
#define MGV7_RIDGES 0x02 #define MGV7_RIDGES 0x02
class BiomeManager;
extern FlagDesc flagdesc_mapgen_v7[]; extern FlagDesc flagdesc_mapgen_v7[];
@ -52,7 +53,7 @@ struct MapgenV7Params : public MapgenSpecificParams {
class MapgenV7 : public Mapgen { class MapgenV7 : public Mapgen {
public: public:
EmergeManager *emerge; EmergeManager *emerge;
BiomeDefManager *bmgr; BiomeManager *bmgr;
int ystride; int ystride;
int zstride; int zstride;

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include "mg_biome.h" #include "mg_biome.h"
#include "gamedef.h"
#include "nodedef.h" #include "nodedef.h"
#include "map.h" //for ManualMapVoxelManipulator #include "map.h" //for ManualMapVoxelManipulator
#include "log.h" #include "log.h"
@ -26,13 +27,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/mathconstants.h" #include "util/mathconstants.h"
#include "porting.h" #include "porting.h"
const char *BiomeManager::ELEMENT_TITLE = "biome";
NoiseParams nparams_biome_def_heat(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.70); NoiseParams nparams_biome_def_heat(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.70);
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(NodeResolver *resolver) ///////////////////////////////////////////////////////////////////////////////
BiomeManager::BiomeManager(IGameDef *gamedef)
{ {
biome_registration_finished = false; NodeResolver *resolver = gamedef->getNodeDefManager()->getResolver();
np_heat = &nparams_biome_def_heat; np_heat = &nparams_biome_def_heat;
np_humidity = &nparams_biome_def_humidity; np_humidity = &nparams_biome_def_humidity;
@ -55,41 +62,21 @@ BiomeDefManager::BiomeDefManager(NodeResolver *resolver)
resolver->addNode("air", "", CONTENT_AIR, &b->c_dust); resolver->addNode("air", "", CONTENT_AIR, &b->c_dust);
resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water); resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water);
biomes.push_back(b); add(b);
} }
BiomeDefManager::~BiomeDefManager()
BiomeManager::~BiomeManager()
{ {
//if (biomecache) //if (biomecache)
// delete[] biomecache; // delete[] biomecache;
for (size_t i = 0; i != biomes.size(); i++)
delete biomes[i];
} }
Biome *BiomeDefManager::createBiome(BiomeTerrainType btt)
{
/*switch (btt) {
case BIOME_TERRAIN_NORMAL:
return new Biome;
case BIOME_TERRAIN_LIQUID:
return new BiomeLiquid;
case BIOME_TERRAIN_NETHER:
return new BiomeHell;
case BIOME_TERRAIN_AETHER:
return new BiomeSky;
case BIOME_TERRAIN_FLAT:
return new BiomeSuperflat;
}
return NULL;*/
return new Biome;
}
// just a PoC, obviously needs optimization later on (precalculate this) // just a PoC, obviously needs optimization later on (precalculate this)
void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) void BiomeManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map)
{ {
int i = 0; int i = 0;
for (int y = 0; y != input->mapsize.Y; y++) { for (int y = 0; y != input->mapsize.Y; y++) {
@ -102,38 +89,17 @@ void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map)
} }
bool BiomeDefManager::addBiome(Biome *b) Biome *BiomeManager::getBiome(float heat, float humidity, s16 y)
{
if (biome_registration_finished) {
errorstream << "BiomeDefManager: biome registration already "
"finished, dropping " << b->name << std::endl;
return false;
}
size_t nbiomes = biomes.size();
if (nbiomes >= 0xFF) {
errorstream << "BiomeDefManager: too many biomes, dropping "
<< b->name << std::endl;
return false;
}
b->id = (u8)nbiomes;
biomes.push_back(b);
verbosestream << "BiomeDefManager: added biome " << b->name << std::endl;
return true;
}
Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y)
{ {
Biome *b, *biome_closest = NULL; Biome *b, *biome_closest = NULL;
float dist_min = FLT_MAX; float dist_min = FLT_MAX;
for (size_t i = 1; i < biomes.size(); i++) { for (size_t i = 1; i < m_elements.size(); i++) {
b = biomes[i]; b = (Biome *)m_elements[i];
if (y > b->height_max || y < b->height_min) if (!b || y > b->height_max || y < b->height_min) {
printf("not good - %p %d %d %d\n", b, y, b->height_max, b->height_min);
continue; continue;
}
float d_heat = heat - b->heat_point; float d_heat = heat - b->heat_point;
float d_humidity = humidity - b->humidity_point; float d_humidity = humidity - b->humidity_point;
@ -145,16 +111,5 @@ Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y)
} }
} }
return biome_closest ? biome_closest : biomes[0]; return biome_closest ? biome_closest : (Biome *)m_elements[0];
}
u8 BiomeDefManager::getBiomeIdByName(const char *name)
{
for (size_t i = 0; i != biomes.size(); i++) {
if (!strcasecmp(name, biomes[i]->name.c_str()))
return i;
}
return 0;
} }

@ -20,12 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef MG_BIOME_HEADER #ifndef MG_BIOME_HEADER
#define MG_BIOME_HEADER #define MG_BIOME_HEADER
#include <string>
#include "nodedef.h"
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
#include "mapgen.h" #include "mapgen.h"
#include "noise.h"
//#include <string>
//#include "nodedef.h"
//#include "gamedef.h"
//#include "mapnode.h"
enum BiomeTerrainType enum BiomeTerrainType
{ {
@ -39,10 +40,16 @@ enum BiomeTerrainType
extern NoiseParams nparams_biome_def_heat; extern NoiseParams nparams_biome_def_heat;
extern NoiseParams nparams_biome_def_humidity; extern NoiseParams nparams_biome_def_humidity;
class Biome {
struct BiomeNoiseInput {
v2s16 mapsize;
float *heat_map;
float *humidity_map;
s16 *height_map;
};
class Biome : public GenElement {
public: public:
u8 id;
std::string name;
u32 flags; u32 flags;
content_t c_top; content_t c_top;
@ -60,33 +67,24 @@ public:
float humidity_point; float humidity_point;
}; };
struct BiomeNoiseInput { class BiomeManager : public GenElementManager {
v2s16 mapsize;
float *heat_map;
float *humidity_map;
s16 *height_map;
};
class BiomeDefManager {
public: public:
std::vector<Biome *> biomes; static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x100;
bool biome_registration_finished;
NoiseParams *np_heat; NoiseParams *np_heat;
NoiseParams *np_humidity; NoiseParams *np_humidity;
BiomeDefManager(NodeResolver *resolver); BiomeManager(IGameDef *gamedef);
~BiomeDefManager(); ~BiomeManager();
Biome *create(int btt)
{
return new Biome;
}
Biome *createBiome(BiomeTerrainType btt);
void calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map); void calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map);
Biome *getBiome(float heat, float humidity, s16 y); Biome *getBiome(float heat, float humidity, s16 y);
bool addBiome(Biome *b);
u8 getBiomeIdByName(const char *name);
s16 calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime);
s16 calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime);
}; };
#endif #endif

@ -20,28 +20,44 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mg_decoration.h" #include "mg_decoration.h"
#include "mg_schematic.h" #include "mg_schematic.h"
#include "mapgen.h" #include "mapgen.h"
#include "noise.h"
#include "map.h" #include "map.h"
#include "log.h" #include "log.h"
#include "util/numeric.h" #include "util/numeric.h"
const char *DecorationManager::ELEMENT_TITLE = "decoration";
FlagDesc flagdesc_deco_schematic[] = {
{"place_center_x", DECO_PLACE_CENTER_X},
{"place_center_y", DECO_PLACE_CENTER_Y},
{"place_center_z", DECO_PLACE_CENTER_Z},
{NULL, 0}
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Decoration *createDecoration(DecorationType type) size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax)
{ {
switch (type) { size_t nplaced = 0;
case DECO_SIMPLE:
return new DecoSimple; for (size_t i = 0; i != m_elements.size(); i++) {
case DECO_SCHEMATIC: Decoration *deco = (Decoration *)m_elements[i];
return new DecoSchematic; if (!deco)
//case DECO_LSYSTEM: continue;
// return new DecoLSystem;
default: nplaced += deco->placeDeco(mg, seed, nmin, nmax);
return NULL; seed++;
} }
return nplaced;
} }
///////////////////////////////////////////////////////////////////////////////
Decoration::Decoration() Decoration::Decoration()
{ {
mapseed = 0; mapseed = 0;
@ -57,7 +73,7 @@ Decoration::~Decoration()
} }
void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) size_t 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;
@ -131,6 +147,8 @@ void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
generate(mg, &ps, max_y, v3s16(x, y, z)); generate(mg, &ps, max_y, v3s16(x, y, z));
} }
} }
return 0;
} }
@ -190,6 +208,7 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p) bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p)
{ {
// Don't bother if there aren't any decorations to place // Don't bother if there aren't any decorations to place
@ -269,7 +288,33 @@ int DecoSimple::getHeight()
} }
std::string DecoSimple::getName() ///////////////////////////////////////////////////////////////////////////////
void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p)
{ {
return ""; ManualMapVoxelManipulator *vm = mg->vm;
if (flags & DECO_PLACE_CENTER_X)
p.X -= (schematic->size.X + 1) / 2;
if (flags & DECO_PLACE_CENTER_Y)
p.Y -= (schematic->size.Y + 1) / 2;
if (flags & DECO_PLACE_CENTER_Z)
p.Z -= (schematic->size.Z + 1) / 2;
u32 vi = vm->m_area.index(p);
content_t c = vm->m_data[vi].getContent();
if (!CONTAINS(c_place_on, c))
return;
Rotation rot = (rotation == ROTATE_RAND) ?
(Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation;
schematic->blitToVManip(p, vm, rot, false, mg->ndef);
}
int DecoSchematic::getHeight()
{
return schematic->size.Y;
} }

@ -21,12 +21,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MG_DECORATION_HEADER #define MG_DECORATION_HEADER
#include <set> #include <set>
#include "mapnode.h" #include "mapgen.h"
class NoiseParams; class NoiseParams;
class Mapgen; class Mapgen;
class ManualMapVoxelManipulator; class ManualMapVoxelManipulator;
class PseudoRandom; class PseudoRandom;
class Schematic;
enum DecorationType { enum DecorationType {
DECO_SIMPLE, DECO_SIMPLE,
@ -34,6 +35,13 @@ enum DecorationType {
DECO_LSYSTEM DECO_LSYSTEM
}; };
#define DECO_PLACE_CENTER_X 0x01
#define DECO_PLACE_CENTER_Y 0x02
#define DECO_PLACE_CENTER_Z 0x04
extern FlagDesc flagdesc_deco_schematic[];
#if 0 #if 0
struct CutoffData { struct CutoffData {
VoxelArea a; VoxelArea a;
@ -49,7 +57,7 @@ struct CutoffData {
}; };
#endif #endif
class Decoration { class Decoration : public GenElement {
public: public:
INodeDefManager *ndef; INodeDefManager *ndef;
@ -66,12 +74,11 @@ public:
Decoration(); Decoration();
virtual ~Decoration(); virtual ~Decoration();
void placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
void placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0; virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0;
virtual int getHeight() = 0; virtual int getHeight() = 0;
virtual std::string getName() = 0;
}; };
class DecoSimple : public Decoration { class DecoSimple : public Decoration {
@ -87,9 +94,22 @@ public:
bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p); bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p);
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();
}; };
class DecoSchematic : public Decoration {
public:
u32 flags;
Rotation rotation;
Schematic *schematic;
std::string filename;
~DecoSchematic() {}
void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
virtual int getHeight();
};
/* /*
class DecoLSystem : public Decoration { class DecoLSystem : public Decoration {
public: public:
@ -97,6 +117,29 @@ public:
}; };
*/ */
Decoration *createDecoration(DecorationType type); class DecorationManager : public GenElementManager {
public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x10000;
DecorationManager(IGameDef *gamedef) {}
~DecorationManager() {}
Decoration *create(int type)
{
switch (type) {
case DECO_SIMPLE:
return new DecoSimple;
case DECO_SCHEMATIC:
return new DecoSchematic;
//case DECO_LSYSTEM:
// return new DecoLSystem;
default:
return NULL;
}
}
size_t placeAllDecos(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax);
};
#endif #endif

@ -19,10 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mg_ore.h" #include "mg_ore.h"
#include "mapgen.h" #include "mapgen.h"
#include "noise.h"
#include "util/numeric.h" #include "util/numeric.h"
#include "map.h" #include "map.h"
#include "log.h" #include "log.h"
const char *OreManager::ELEMENT_TITLE = "ore";
FlagDesc flagdesc_ore[] = { FlagDesc flagdesc_ore[] = {
{"absheight", OREFLAG_ABSHEIGHT}, {"absheight", OREFLAG_ABSHEIGHT},
@ -31,23 +33,35 @@ FlagDesc flagdesc_ore[] = {
{NULL, 0} {NULL, 0}
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Ore *createOre(OreType type) size_t OreManager::placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax)
{ {
switch (type) { size_t nplaced = 0;
case ORE_SCATTER:
return new OreScatter; for (size_t i = 0; i != m_elements.size(); i++) {
case ORE_SHEET: Ore *ore = (Ore *)m_elements[i];
return new OreSheet; if (!ore)
//case ORE_CLAYLIKE: //TODO: implement this! continue;
// return new OreClaylike;
default: nplaced += ore->placeOre(mg, seed, nmin, nmax);
return NULL; seed++;
}
} }
return nplaced;
}
///////////////////////////////////////////////////////////////////////////////
Ore::Ore()
{
c_ore = CONTENT_IGNORE;
np = NULL;
noise = NULL;
}
Ore::~Ore() Ore::~Ore()
{ {
@ -56,7 +70,13 @@ Ore::~Ore()
} }
void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) std::string Ore::getName()
{
return name;
}
size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
{ {
int in_range = 0; int in_range = 0;
@ -64,7 +84,7 @@ void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
if (flags & OREFLAG_ABSHEIGHT) if (flags & OREFLAG_ABSHEIGHT)
in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1; in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1;
if (!in_range) if (!in_range)
return; return 0;
int ymin, ymax; int ymin, ymax;
if (in_range & ORE_RANGE_MIRROR) { if (in_range & ORE_RANGE_MIRROR) {
@ -75,11 +95,13 @@ void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
ymax = MYMIN(nmax.Y, height_max); ymax = MYMIN(nmax.Y, height_max);
} }
if (clust_size >= ymax - ymin + 1) if (clust_size >= ymax - ymin + 1)
return; return 0;
nmin.Y = ymin; nmin.Y = ymin;
nmax.Y = ymax; nmax.Y = ymax;
generate(mg->vm, mg->seed, blockseed, nmin, nmax); generate(mg->vm, mg->seed, blockseed, nmin, nmax);
return 0;
} }

@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MG_ORE_HEADER #define MG_ORE_HEADER
#include "util/string.h" #include "util/string.h"
#include "mapnode.h" #include "mapgen.h"
class NoiseParams; class NoiseParams;
class Noise; class Noise;
@ -29,10 +29,13 @@ class Mapgen;
class ManualMapVoxelManipulator; class ManualMapVoxelManipulator;
/////////////////// Ore generation flags /////////////////// Ore generation flags
// Use absolute value of height to determine ore placement // Use absolute value of height to determine ore placement
#define OREFLAG_ABSHEIGHT 0x01 #define OREFLAG_ABSHEIGHT 0x01
// Use 3d noise to get density of ore placement, instead of just the position // Use 3d noise to get density of ore placement, instead of just the position
#define OREFLAG_DENSITY 0x02 // not yet implemented #define OREFLAG_DENSITY 0x02 // not yet implemented
// For claylike ore types, place ore if the number of surrounding // For claylike ore types, place ore if the number of surrounding
// nodes isn't the specified node // nodes isn't the specified node
#define OREFLAG_NODEISNT 0x04 // not yet implemented #define OREFLAG_NODEISNT 0x04 // not yet implemented
@ -40,7 +43,6 @@ class ManualMapVoxelManipulator;
#define ORE_RANGE_ACTUAL 1 #define ORE_RANGE_ACTUAL 1
#define ORE_RANGE_MIRROR 2 #define ORE_RANGE_MIRROR 2
extern FlagDesc flagdesc_ore[];
enum OreType { enum OreType {
ORE_SCATTER, ORE_SCATTER,
@ -48,7 +50,9 @@ enum OreType {
ORE_CLAYLIKE ORE_CLAYLIKE
}; };
class Ore { extern FlagDesc flagdesc_ore[];
class Ore : public GenElement {
public: public:
content_t c_ore; // the node to place content_t c_ore; // the node to place
std::vector<content_t> c_wherein; // the nodes to be placed in std::vector<content_t> c_wherein; // the nodes to be placed in
@ -63,32 +67,50 @@ public:
NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering) NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering)
Noise *noise; Noise *noise;
Ore() { Ore();
c_ore = CONTENT_IGNORE;
np = NULL;
noise = NULL;
}
virtual ~Ore(); virtual ~Ore();
void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); size_t 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;
virtual std::string getName();
}; };
class OreScatter : public Ore { class OreScatter : public Ore {
~OreScatter() {} virtual ~OreScatter() {}
virtual void generate(ManualMapVoxelManipulator *vm, int seed, virtual void generate(ManualMapVoxelManipulator *vm, int seed,
u32 blockseed, v3s16 nmin, v3s16 nmax); u32 blockseed, v3s16 nmin, v3s16 nmax);
}; };
class OreSheet : public Ore { class OreSheet : public Ore {
~OreSheet() {} virtual ~OreSheet() {}
virtual void generate(ManualMapVoxelManipulator *vm, int seed, virtual void generate(ManualMapVoxelManipulator *vm, int seed,
u32 blockseed, v3s16 nmin, v3s16 nmax); u32 blockseed, v3s16 nmin, v3s16 nmax);
}; };
Ore *createOre(OreType type); class OreManager : public GenElementManager {
public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x10000;
OreManager(IGameDef *gamedef) {}
~OreManager() {}
Ore *create(int type)
{
switch (type) {
case ORE_SCATTER:
return new OreScatter;
case ORE_SHEET:
return new OreSheet;
//case ORE_CLAYLIKE: //TODO: implement this!
// return new OreClaylike;
default:
return NULL;
}
}
size_t placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax);
};
#endif #endif

@ -28,79 +28,42 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" #include "serialization.h"
#include "filesys.h" #include "filesys.h"
FlagDesc flagdesc_deco_schematic[] = { const char *SchematicManager::ELEMENT_TITLE = "schematic";
{"place_center_x", DECO_PLACE_CENTER_X},
{"place_center_y", DECO_PLACE_CENTER_Y},
{"place_center_z", DECO_PLACE_CENTER_Z},
{NULL, 0}
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
DecoSchematic::DecoSchematic() Schematic::Schematic()
{ {
schematic = NULL; schemdata = NULL;
slice_probs = NULL; slice_probs = NULL;
flags = 0; flags = 0;
size = v3s16(0, 0, 0); size = v3s16(0, 0, 0);
} }
DecoSchematic::~DecoSchematic() Schematic::~Schematic()
{ {
delete []schematic; delete []schemdata;
delete []slice_probs; delete []slice_probs;
} }
void DecoSchematic::updateContentIds() void Schematic::updateContentIds()
{ {
if (flags & DECO_SCHEM_CIDS_UPDATED) if (flags & SCHEM_CIDS_UPDATED)
return; return;
flags |= DECO_SCHEM_CIDS_UPDATED; flags |= SCHEM_CIDS_UPDATED;
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()]); schemdata[i].setContent(c_nodes[schemdata[i].getContent()]);
} }
void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) void Schematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
{ Rotation rot, bool force_placement, INodeDefManager *ndef)
ManualMapVoxelManipulator *vm = mg->vm;
if (flags & DECO_PLACE_CENTER_X)
p.X -= (size.X + 1) / 2;
if (flags & DECO_PLACE_CENTER_Y)
p.Y -= (size.Y + 1) / 2;
if (flags & DECO_PLACE_CENTER_Z)
p.Z -= (size.Z + 1) / 2;
u32 vi = vm->m_area.index(p);
content_t c = vm->m_data[vi].getContent();
if (!CONTAINS(c_place_on, c))
return;
Rotation rot = (rotation == ROTATE_RAND) ?
(Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation;
blitToVManip(p, vm, rot, false);
}
int DecoSchematic::getHeight() {
return size.Y;
}
std::string DecoSchematic::getName() {
return filename;
}
void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
Rotation rot, bool force_placement)
{ {
int xstride = 1; int xstride = 1;
int ystride = size.X; int ystride = size.X;
@ -150,10 +113,10 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
if (!vm->m_area.contains(vi)) if (!vm->m_area.contains(vi))
continue; continue;
if (schematic[i].getContent() == CONTENT_IGNORE) if (schemdata[i].getContent() == CONTENT_IGNORE)
continue; continue;
if (schematic[i].param1 == MTSCHEM_PROB_NEVER) if (schemdata[i].param1 == MTSCHEM_PROB_NEVER)
continue; continue;
if (!force_placement) { if (!force_placement) {
@ -162,11 +125,11 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
continue; continue;
} }
if (schematic[i].param1 != MTSCHEM_PROB_ALWAYS && if (schemdata[i].param1 != MTSCHEM_PROB_ALWAYS &&
myrand_range(1, 255) > schematic[i].param1) myrand_range(1, 255) > schemdata[i].param1)
continue; continue;
vm->m_data[vi] = schematic[i]; vm->m_data[vi] = schemdata[i];
vm->m_data[vi].param1 = 0; vm->m_data[vi].param1 = 0;
if (rot) if (rot)
@ -178,13 +141,14 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
} }
void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement) void Schematic::placeStructure(Map *map, v3s16 p, u32 flags,
Rotation rot, bool force_placement, INodeDefManager *ndef)
{ {
assert(schematic != NULL); assert(schemdata != NULL);
ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map); ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
Rotation rot = (rotation == ROTATE_RAND) ? if (rot == ROTATE_RAND)
(Rotation)myrand_range(ROTATE_0, ROTATE_270) : rotation; rot = (Rotation)myrand_range(ROTATE_0, ROTATE_270);
v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ? v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ?
v3s16(size.Z, size.Y, size.X) : size; v3s16(size.Z, size.Y, size.X) : size;
@ -200,7 +164,7 @@ void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement)
v3s16 bp2 = getNodeBlockPos(p + s - v3s16(1,1,1)); v3s16 bp2 = getNodeBlockPos(p + s - v3s16(1,1,1));
vm->initialEmerge(bp1, bp2); vm->initialEmerge(bp1, bp2);
blitToVManip(p, vm, rot, force_placement); blitToVManip(p, vm, rot, force_placement, ndef);
std::map<v3s16, MapBlock *> lighting_modified_blocks; std::map<v3s16, MapBlock *> lighting_modified_blocks;
std::map<v3s16, MapBlock *> modified_blocks; std::map<v3s16, MapBlock *> modified_blocks;
@ -221,13 +185,14 @@ void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement)
} }
bool DecoSchematic::loadSchematicFile(NodeResolver *resolver, bool Schematic::loadSchematicFromFile(const char *filename,
NodeResolver *resolver,
std::map<std::string, std::string> &replace_names) 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;
std::ifstream is(filename.c_str(), std::ios_base::binary); std::ifstream is(filename, std::ios_base::binary);
u32 signature = readU32(is); u32 signature = readU32(is);
if (signature != MTSCHEM_FILE_SIGNATURE) { if (signature != MTSCHEM_FILE_SIGNATURE) {
@ -247,13 +212,8 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
delete []slice_probs; delete []slice_probs;
slice_probs = new u8[size.Y]; slice_probs = new u8[size.Y];
if (version >= 3) {
for (int y = 0; y != size.Y; y++) for (int y = 0; y != size.Y; y++)
slice_probs[y] = readU8(is); slice_probs[y] = (version >= 3) ? readU8(is) : MTSCHEM_PROB_ALWAYS;
} else {
for (int y = 0; y != size.Y; y++)
slice_probs[y] = MTSCHEM_PROB_ALWAYS;
}
int nodecount = size.X * size.Y * size.Z; int nodecount = size.X * size.Y * size.Z;
@ -268,7 +228,6 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
} }
std::map<std::string, std::string>::iterator it; std::map<std::string, std::string>::iterator it;
it = replace_names.find(name); it = replace_names.find(name);
if (it != replace_names.end()) if (it != replace_names.end())
name = it->second; name = it->second;
@ -276,17 +235,17 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
resolver->addNodeList(name.c_str(), &c_nodes); resolver->addNodeList(name.c_str(), &c_nodes);
} }
delete []schematic; delete []schemdata;
schematic = new MapNode[nodecount]; schemdata = new MapNode[nodecount];
MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic, MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schemdata,
nodecount, 2, 2, true); nodecount, 2, 2, true);
if (version == 1) { // fix up the probability values if (version == 1) { // fix up the probability values
for (int i = 0; i != nodecount; i++) { for (int i = 0; i != nodecount; i++) {
if (schematic[i].param1 == 0) if (schemdata[i].param1 == 0)
schematic[i].param1 = MTSCHEM_PROB_ALWAYS; schemdata[i].param1 = MTSCHEM_PROB_ALWAYS;
if (have_cignore && schematic[i].getContent() == cignore) if (have_cignore && schemdata[i].getContent() == cignore)
schematic[i].param1 = MTSCHEM_PROB_NEVER; schemdata[i].param1 = MTSCHEM_PROB_NEVER;
} }
} }
@ -324,7 +283,7 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
2 - Fixed messy never/always place; 0 probability is now never, 0xFF is always 2 - Fixed messy never/always place; 0 probability is now never, 0xFF is always
3 - Added y-slice probabilities; this allows for variable height structures 3 - Added y-slice probabilities; this allows for variable height structures
*/ */
void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) void Schematic::saveSchematicToFile(const char *filename, INodeDefManager *ndef)
{ {
std::ostringstream ss(std::ios_base::binary); std::ostringstream ss(std::ios_base::binary);
@ -337,7 +296,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef)
std::vector<content_t> usednodes; std::vector<content_t> usednodes;
int nodecount = size.X * size.Y * size.Z; int nodecount = size.X * size.Y * size.Z;
build_nnlist_and_update_ids(schematic, nodecount, &usednodes); build_nnlist_and_update_ids(schemdata, nodecount, &usednodes);
u16 numids = usednodes.size(); u16 numids = usednodes.size();
writeU16(ss, numids); // name count writeU16(ss, numids); // name count
@ -345,7 +304,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef)
ss << serializeString(ndef->get(usednodes[i]).name); // node names ss << serializeString(ndef->get(usednodes[i]).name); // node names
// compressed bulk node data // compressed bulk node data
MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schematic, MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schemdata,
nodecount, 2, 2, true); nodecount, 2, 2, true);
fs::safeWriteToFile(filename, ss.str()); fs::safeWriteToFile(filename, ss.str());
@ -377,7 +336,7 @@ void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
} }
bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) bool Schematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
{ {
ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map); ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
@ -391,15 +350,15 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
for (s16 y = 0; y != size.Y; y++) for (s16 y = 0; y != size.Y; y++)
slice_probs[y] = MTSCHEM_PROB_ALWAYS; slice_probs[y] = MTSCHEM_PROB_ALWAYS;
schematic = new MapNode[size.X * size.Y * size.Z]; schemdata = new MapNode[size.X * size.Y * size.Z];
u32 i = 0; u32 i = 0;
for (s16 z = p1.Z; z <= p2.Z; z++) for (s16 z = p1.Z; z <= p2.Z; z++)
for (s16 y = p1.Y; y <= p2.Y; y++) { for (s16 y = p1.Y; y <= p2.Y; y++) {
u32 vi = vm->m_area.index(p1.X, y, z); u32 vi = vm->m_area.index(p1.X, y, z);
for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) { for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) {
schematic[i] = vm->m_data[vi]; schemdata[i] = vm->m_data[vi];
schematic[i].param1 = MTSCHEM_PROB_ALWAYS; schemdata[i].param1 = MTSCHEM_PROB_ALWAYS;
} }
} }
@ -408,7 +367,7 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
} }
void DecoSchematic::applyProbabilities(v3s16 p0, void Schematic::applyProbabilities(v3s16 p0,
std::vector<std::pair<v3s16, u8> > *plist, std::vector<std::pair<v3s16, u8> > *plist,
std::vector<std::pair<s16, u8> > *splist) std::vector<std::pair<s16, u8> > *splist)
{ {
@ -417,11 +376,11 @@ void DecoSchematic::applyProbabilities(v3s16 p0,
int index = p.Z * (size.Y * size.X) + p.Y * size.X + p.X; int index = p.Z * (size.Y * size.X) + p.Y * size.X + p.X;
if (index < size.Z * size.Y * size.X) { if (index < size.Z * size.Y * size.X) {
u8 prob = (*plist)[i].second; u8 prob = (*plist)[i].second;
schematic[index].param1 = prob; schemdata[index].param1 = prob;
// trim unnecessary node names from schematic // trim unnecessary node names from schematic
if (prob == MTSCHEM_PROB_NEVER) if (prob == MTSCHEM_PROB_NEVER)
schematic[index].setContent(CONTENT_AIR); schemdata[index].setContent(CONTENT_AIR);
} }
} }

@ -30,11 +30,8 @@ class ManualMapVoxelManipulator;
class PseudoRandom; class PseudoRandom;
class NodeResolver; class NodeResolver;
/////////////////// Decoration flags /////////////////// Schematic flags
#define DECO_PLACE_CENTER_X 1 #define SCHEM_CIDS_UPDATED 0x08
#define DECO_PLACE_CENTER_Y 2
#define DECO_PLACE_CENTER_Z 4
#define DECO_SCHEM_CIDS_UPDATED 8
#define MTSCHEM_FILE_SIGNATURE 0x4d54534d // 'MTSM' #define MTSCHEM_FILE_SIGNATURE 0x4d54534d // 'MTSM'
@ -44,42 +41,50 @@ class NodeResolver;
#define MTSCHEM_PROB_NEVER 0x00 #define MTSCHEM_PROB_NEVER 0x00
#define MTSCHEM_PROB_ALWAYS 0xFF #define MTSCHEM_PROB_ALWAYS 0xFF
extern FlagDesc flagdesc_deco_schematic[];
class DecoSchematic : public Decoration { class Schematic : public GenElement {
public: public:
std::string filename;
std::vector<content_t> c_nodes; std::vector<content_t> c_nodes;
u32 flags; u32 flags;
Rotation rotation;
v3s16 size; v3s16 size;
MapNode *schematic; MapNode *schemdata;
u8 *slice_probs; u8 *slice_probs;
DecoSchematic(); Schematic();
~DecoSchematic(); ~Schematic();
void updateContentIds(); void updateContentIds();
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
virtual int getHeight();
virtual std::string getName();
void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm, void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
Rotation rot, bool force_placement); Rotation rot, bool force_placement, INodeDefManager *ndef);
bool loadSchematicFile(NodeResolver *resolver, bool loadSchematicFromFile(const char *filename, NodeResolver *resolver,
std::map<std::string, std::string> &replace_names); std::map<std::string, std::string> &replace_names);
void saveSchematicFile(INodeDefManager *ndef); void saveSchematicToFile(const char *filename, INodeDefManager *ndef);
bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2); bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
void placeStructure(Map *map, v3s16 p, bool force_placement);
void placeStructure(Map *map, v3s16 p, u32 flags,
Rotation rot, bool force_placement, INodeDefManager *nef);
void applyProbabilities(v3s16 p0, void applyProbabilities(v3s16 p0,
std::vector<std::pair<v3s16, u8> > *plist, std::vector<std::pair<v3s16, u8> > *plist,
std::vector<std::pair<s16, u8> > *splist); std::vector<std::pair<s16, u8> > *splist);
}; };
class SchematicManager : public GenElementManager {
public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x10000;
SchematicManager(IGameDef *gamedef) {}
~SchematicManager() {}
Schematic *create(int type)
{
return new Schematic;
}
};
void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount, void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
std::vector<content_t> *usednodes); std::vector<content_t> *usednodes);

@ -1009,31 +1009,46 @@ bool read_noiseparams_nc(lua_State *L, int index, NoiseParams *np)
} }
/******************************************************************************/ /******************************************************************************/
bool read_schematic(lua_State *L, int index, DecoSchematic *dschem, Server *server) {
bool get_schematic(lua_State *L, int index, Schematic *schem,
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
{
if (index < 0) if (index < 0)
index = lua_gettop(L) + 1 + index; index = lua_gettop(L) + 1 + index;
INodeDefManager *ndef = server->getNodeDefManager();
if (lua_istable(L, index)) { if (lua_istable(L, index)) {
return read_schematic(L, index, schem, ndef, replace_names);
} else if (lua_isstring(L, index)) {
NodeResolver *resolver = ndef->getResolver();
const char *filename = lua_tostring(L, index);
return schem->loadSchematicFromFile(filename, resolver, replace_names);
} else {
return false;
}
}
bool read_schematic(lua_State *L, int index, Schematic *schem,
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
{
//// Get schematic size
lua_getfield(L, index, "size"); lua_getfield(L, index, "size");
v3s16 size = read_v3s16(L, -1); v3s16 size = read_v3s16(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
//// Get schematic data
lua_getfield(L, index, "data");
luaL_checktype(L, -1, LUA_TTABLE);
int numnodes = size.X * size.Y * size.Z; int numnodes = size.X * size.Y * size.Z;
MapNode *schemdata = new MapNode[numnodes]; MapNode *schemdata = new MapNode[numnodes];
int i = 0; int i = 0;
// Get schematic data
lua_getfield(L, index, "data");
luaL_checktype(L, -1, LUA_TTABLE);
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, -2)) { while (lua_next(L, -2)) {
if (i < numnodes) { if (i < numnodes) {
// same as readnode, except param1 default is MTSCHEM_PROB_CONST // same as readnode, except param1 default is MTSCHEM_PROB_CONST
lua_getfield(L, -1, "name"); lua_getfield(L, -1, "name");
const char *name = luaL_checkstring(L, -1); std::string name = luaL_checkstring(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
u8 param1; u8 param1;
@ -1046,6 +1061,11 @@ bool read_schematic(lua_State *L, int index, DecoSchematic *dschem, Server *serv
param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
lua_pop(L, 1); lua_pop(L, 1);
std::map<std::string, std::string>::iterator it;
it = replace_names.find(name);
if (it != replace_names.end())
name = it->second;
schemdata[i] = MapNode(ndef, name, param1, param2); schemdata[i] = MapNode(ndef, name, param1, param2);
} }
@ -1060,35 +1080,27 @@ bool read_schematic(lua_State *L, int index, DecoSchematic *dschem, Server *serv
return false; return false;
} }
u8 *sliceprobs = new u8[size.Y]; //// Get Y-slice probability values (if present)
u8 *slice_probs = new u8[size.Y];
for (i = 0; i != size.Y; i++) for (i = 0; i != size.Y; i++)
sliceprobs[i] = MTSCHEM_PROB_ALWAYS; slice_probs[i] = MTSCHEM_PROB_ALWAYS;
// Get Y-slice probability values (if present)
lua_getfield(L, index, "yslice_prob"); lua_getfield(L, index, "yslice_prob");
if (lua_istable(L, -1)) { if (lua_istable(L, -1)) {
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, -2)) { while (lua_next(L, -2)) {
if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) { if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) {
sliceprobs[i] = getintfield_default(L, -1, slice_probs[i] = getintfield_default(L, -1,
"prob", MTSCHEM_PROB_ALWAYS); "prob", MTSCHEM_PROB_ALWAYS);
} }
lua_pop(L, 1); lua_pop(L, 1);
} }
} }
dschem->size = size; schem->flags = 0;
dschem->schematic = schemdata; schem->size = size;
dschem->slice_probs = sliceprobs; schem->schemdata = schemdata;
schem->slice_probs = slice_probs;
} else if (lua_isstring(L, index)) {
dschem->filename = std::string(lua_tostring(L, index));
} else {
errorstream << "read_schematic: missing schematic "
"filename or raw schematic data" << std::endl;
return false;
}
return true; return true;
} }

@ -59,7 +59,7 @@ struct DigParams;
struct HitParams; struct HitParams;
struct EnumString; struct EnumString;
struct NoiseParams; struct NoiseParams;
class DecoSchematic; class Schematic;
ContentFeatures read_content_features (lua_State *L, int index); ContentFeatures read_content_features (lua_State *L, int index);
@ -151,10 +151,14 @@ NoiseParams* read_noiseparams (lua_State *L, int index);
bool read_noiseparams_nc (lua_State *L, int index, bool read_noiseparams_nc (lua_State *L, int index,
NoiseParams *np); NoiseParams *np);
bool get_schematic (lua_State *L, int index,
Schematic *schem,
INodeDefManager *ndef,
std::map<std::string, std::string> &replace_names);
bool read_schematic (lua_State *L, int index, bool read_schematic (lua_State *L, int index,
DecoSchematic *dschem, Schematic *dschem,
Server *server); INodeDefManager *ndef,
std::map<std::string, std::string> &replace_names);
void luaentity_get (lua_State *L,u16 id); void luaentity_get (lua_State *L,u16 id);

@ -25,13 +25,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/serialize.h" #include "util/serialize.h"
#include "server.h" #include "server.h"
#include "environment.h" #include "environment.h"
#include "mg_biome.h"
#include "emerge.h" #include "emerge.h"
#include "mg_biome.h" #include "mg_biome.h"
#include "mg_ore.h" #include "mg_ore.h"
#include "mg_decoration.h" #include "mg_decoration.h"
#include "mg_schematic.h" #include "mg_schematic.h"
#include "mapgen_v7.h" #include "mapgen_v7.h"
#include "settings.h"
#include "main.h" #include "main.h"
#include "log.h" #include "log.h"
@ -85,7 +85,7 @@ struct EnumString ModApiMapgen::es_Rotation[] =
static void read_schematic_replacements(lua_State *L, static void read_schematic_replacements(lua_State *L,
std::map<std::string, std::string> replace_names, int index) 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)) {
@ -310,13 +310,13 @@ int ModApiMapgen::l_register_biome(lua_State *L)
luaL_checktype(L, index, LUA_TTABLE); luaL_checktype(L, index, LUA_TTABLE);
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef; BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index, enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL); "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
Biome *b = bmgr->createBiome(terrain); Biome *b = bmgr->create(terrain);
b->name = getstringfield_default(L, index, "name", "<no name>"); b->name = getstringfield_default(L, index, "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);
@ -325,7 +325,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
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
if (!bmgr->addBiome(b)) { u32 id = bmgr->add(b);
if (id == (u32)-1) {
delete b; delete b;
return 0; return 0;
} }
@ -344,7 +345,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
verbosestream << "register_biome: " << b->name << std::endl; verbosestream << "register_biome: " << b->name << std::endl;
return 0; lua_pushinteger(L, id);
return 1;
} }
// register_decoration({lots of stuff}) // register_decoration({lots of stuff})
@ -353,20 +355,22 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
int index = 1; int index = 1;
luaL_checktype(L, index, LUA_TTABLE); luaL_checktype(L, index, LUA_TTABLE);
EmergeManager *emerge = getServer(L)->getEmergeManager(); INodeDefManager *ndef = getServer(L)->getNodeDefManager();
BiomeDefManager *bdef = emerge->biomedef;
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr;
enum DecorationType decotype = (DecorationType)getenumfield(L, index, enum DecorationType decotype = (DecorationType)getenumfield(L, index,
"deco_type", es_DecorationType, -1); "deco_type", es_DecorationType, -1);
Decoration *deco = createDecoration(decotype); Decoration *deco = decomgr->create(decotype);
if (!deco) { if (!deco) {
errorstream << "register_decoration: decoration placement type " errorstream << "register_decoration: decoration placement type "
<< decotype << " not implemented"; << decotype << " not implemented";
return 0; return 0;
} }
deco->name = getstringfield_default(L, index, "name", "");
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) {
@ -391,9 +395,11 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
std::vector<const char *> biome_list; std::vector<const char *> biome_list;
getstringlistfield(L, index, "biomes", biome_list); getstringlistfield(L, index, "biomes", biome_list);
for (size_t i = 0; i != biome_list.size(); i++) { for (size_t i = 0; i != biome_list.size(); i++) {
u8 biomeid = bdef->getBiomeIdByName(biome_list[i]); Biome *b = (Biome *)biomemgr->getByName(biome_list[i]);
if (biomeid) if (!b)
deco->biomes.insert(biomeid); continue;
deco->biomes.insert(b->id);
} }
//// Handle decoration type-specific parameters //// Handle decoration type-specific parameters
@ -403,7 +409,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
success = regDecoSimple(L, resolver, (DecoSimple *)deco); success = regDecoSimple(L, resolver, (DecoSimple *)deco);
break; break;
case DECO_SCHEMATIC: case DECO_SCHEMATIC:
success = regDecoSchematic(L, resolver, (DecoSchematic *)deco); success = regDecoSchematic(L, ndef, (DecoSchematic *)deco);
break; break;
case DECO_LSYSTEM: case DECO_LSYSTEM:
break; break;
@ -414,14 +420,16 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
return 0; return 0;
} }
emerge->decorations.push_back(deco); u32 id = decomgr->add(deco);
if (id == (u32)-1) {
verbosestream << "register_decoration: decoration '" << deco->getName() delete deco;
<< "' registered" << std::endl;
return 0; return 0;
} }
lua_pushinteger(L, id);
return 1;
}
bool ModApiMapgen::regDecoSimple(lua_State *L, bool ModApiMapgen::regDecoSimple(lua_State *L,
NodeResolver *resolver, DecoSimple *deco) NodeResolver *resolver, DecoSimple *deco)
{ {
@ -461,8 +469,8 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
return true; return true;
} }
bool ModApiMapgen::regDecoSchematic(lua_State *L, bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
NodeResolver *resolver, DecoSchematic *deco) DecoSchematic *deco)
{ {
int index = 1; int index = 1;
@ -478,19 +486,16 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L,
read_schematic_replacements(L, replace_names, lua_gettop(L)); read_schematic_replacements(L, replace_names, lua_gettop(L));
lua_pop(L, 1); lua_pop(L, 1);
Schematic *schem = new Schematic;
lua_getfield(L, index, "schematic"); lua_getfield(L, index, "schematic");
if (!read_schematic(L, -1, deco, getServer(L))) { if (!get_schematic(L, -1, schem, ndef, replace_names)) {
lua_pop(L, 1); lua_pop(L, 1);
delete schem;
return false; return false;
} }
lua_pop(L, 1); lua_pop(L, 1);
if (!deco->filename.empty() && deco->schematic = schem;
!deco->loadSchematicFile(resolver, replace_names)) {
errorstream << "register_decoration: failed to load schematic"
" file '" << deco->filename << "'" << std::endl;
return false;
}
return true; return true;
} }
@ -501,25 +506,25 @@ int ModApiMapgen::l_register_ore(lua_State *L)
int index = 1; int index = 1;
luaL_checktype(L, index, LUA_TTABLE); luaL_checktype(L, index, LUA_TTABLE);
EmergeManager *emerge = getServer(L)->getEmergeManager();
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr;
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);
Ore *ore = createOre(oretype); Ore *ore = oremgr->create(oretype);
if (!ore) { if (!ore) {
errorstream << "register_ore: ore_type " errorstream << "register_ore: ore_type " << oretype << " not implemented";
<< oretype << " not implemented";
return 0; return 0;
} }
ore->name = getstringfield_default(L, index, "name", "");
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);
ore->clust_size = getintfield_default(L, index, "clust_size", 0); ore->clust_size = getintfield_default(L, index, "clust_size", 0);
ore->height_min = getintfield_default(L, index, "height_min", 0); ore->height_min = getintfield_default(L, index, "height_min", 0);
ore->height_max = getintfield_default(L, index, "height_max", 0); ore->height_max = getintfield_default(L, index, "height_max", 0);
ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.); ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0);
ore->noise = NULL; ore->noise = NULL;
ore->flags = 0; ore->flags = 0;
@ -536,6 +541,12 @@ int ModApiMapgen::l_register_ore(lua_State *L)
ore->np = read_noiseparams(L, -1); ore->np = read_noiseparams(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
u32 id = oremgr->add(ore);
if (id == (u32)-1) {
delete ore;
return 0;
}
std::vector<const char *> wherein_names; std::vector<const char *> wherein_names;
getstringlistfield(L, index, "wherein", wherein_names); getstringlistfield(L, index, "wherein", wherein_names);
for (size_t i = 0; i != wherein_names.size(); i++) for (size_t i = 0; i != wherein_names.size(); i++)
@ -544,17 +555,14 @@ int ModApiMapgen::l_register_ore(lua_State *L)
resolver->addNode(getstringfield_default(L, index, "ore", ""), resolver->addNode(getstringfield_default(L, index, "ore", ""),
"", CONTENT_AIR, &ore->c_ore); "", CONTENT_AIR, &ore->c_ore);
emerge->ores.push_back(ore); lua_pushinteger(L, id);
return 1;
//verbosestream << "register_ore: ore '" << ore->ore_name
// << "' registered" << std::endl;
return 0;
} }
// create_schematic(p1, p2, probability_list, filename) // create_schematic(p1, p2, probability_list, filename)
int ModApiMapgen::l_create_schematic(lua_State *L) int ModApiMapgen::l_create_schematic(lua_State *L)
{ {
DecoSchematic dschem; Schematic schem;
Map *map = &(getEnv(L)->getMap()); Map *map = &(getEnv(L)->getMap());
INodeDefManager *ndef = getServer(L)->getNodeDefManager(); INodeDefManager *ndef = getServer(L)->getNodeDefManager();
@ -594,20 +602,19 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
} }
} }
const char *s = lua_tostring(L, 4); const char *filename = luaL_checkstring(L, 4);
dschem.filename = std::string(s ? s : "");
if (!dschem.getSchematicFromMap(map, p1, p2)) { if (!schem.getSchematicFromMap(map, p1, p2)) {
errorstream << "create_schematic: failed to get schematic " errorstream << "create_schematic: failed to get schematic "
"from map" << std::endl; "from map" << std::endl;
return 0; return 0;
} }
dschem.applyProbabilities(p1, &prob_list, &slice_prob_list); schem.applyProbabilities(p1, &prob_list, &slice_prob_list);
dschem.saveSchematicFile(ndef); schem.saveSchematicToFile(filename, ndef);
actionstream << "create_schematic: saved schematic file '" actionstream << "create_schematic: saved schematic file '"
<< dschem.filename << "'." << std::endl; << filename << "'." << std::endl;
return 1; return 1;
} }
@ -615,38 +622,36 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
// place_schematic(p, schematic, rotation, replacement) // place_schematic(p, schematic, rotation, replacement)
int ModApiMapgen::l_place_schematic(lua_State *L) int ModApiMapgen::l_place_schematic(lua_State *L)
{ {
DecoSchematic dschem; Schematic schem;
Map *map = &(getEnv(L)->getMap()); Map *map = &(getEnv(L)->getMap());
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); INodeDefManager *ndef = getServer(L)->getNodeDefManager();
//// Read position
v3s16 p = read_v3s16(L, 1); v3s16 p = read_v3s16(L, 1);
if (!read_schematic(L, 2, &dschem, getServer(L)))
return 0;
//// Read rotation
int rot = ROTATE_0; int rot = ROTATE_0;
if (lua_isstring(L, 3)) if (lua_isstring(L, 3))
string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3))); string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3)));
dschem.rotation = (Rotation)rot; //// Read force placement
std::map<std::string, std::string> replace_names;
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()) { //// Read node replacements
if (!dschem.loadSchematicFile(resolver, replace_names)) { std::map<std::string, std::string> replace_names;
errorstream << "place_schematic: failed to load schematic file '" if (lua_istable(L, 4))
<< dschem.filename << "'" << std::endl; read_schematic_replacements(L, replace_names, 4);
//// Read schematic
if (!get_schematic(L, 2, &schem, ndef, replace_names)) {
errorstream << "place_schematic: failed to get schematic" << std::endl;
return 0; return 0;
} }
}
dschem.placeStructure(map, p, force_placement); schem.placeStructure(map, p, 0, (Rotation)rot, force_placement, ndef);
return 1; return 1;
} }

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h" #include "lua_api/l_base.h"
class INodeDefManager;
class NodeResolver; class NodeResolver;
class DecoSimple; class DecoSimple;
class DecoSchematic; class DecoSchematic;
@ -60,7 +61,7 @@ private:
static bool regDecoSimple(lua_State *L, static bool regDecoSimple(lua_State *L,
NodeResolver *resolver, DecoSimple *deco); NodeResolver *resolver, DecoSimple *deco);
static bool regDecoSchematic(lua_State *L, static bool regDecoSchematic(lua_State *L,
NodeResolver *resolver, DecoSchematic *deco); INodeDefManager *ndef, DecoSchematic *deco);
static struct EnumString es_BiomeTerrainType[]; static struct EnumString es_BiomeTerrainType[];
static struct EnumString es_DecorationType[]; static struct EnumString es_DecorationType[];