From 7616537bc071bc93f8d36c84b94603528be1efb0 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Wed, 12 Nov 2014 23:01:13 -0500 Subject: [PATCH] Add Generator Element Management framework Add BiomeManager, OreManager, DecorationManager, and SchematicManager --- src/emerge.cpp | 28 +++--- src/emerge.h | 32 ++++--- src/mapgen.cpp | 84 +++++++++++++++-- src/mapgen.h | 43 +++++++-- src/mapgen_v5.cpp | 16 ++-- src/mapgen_v5.h | 2 +- src/mapgen_v6.cpp | 10 +-- src/mapgen_v6.h | 1 + src/mapgen_v7.cpp | 22 ++--- src/mapgen_v7.h | 3 +- src/mg_biome.cpp | 87 +++++------------- src/mg_biome.h | 54 ++++++----- src/mg_decoration.cpp | 71 ++++++++++++--- src/mg_decoration.h | 57 ++++++++++-- src/mg_ore.cpp | 48 +++++++--- src/mg_ore.h | 48 +++++++--- src/mg_schematic.cpp | 131 ++++++++++----------------- src/mg_schematic.h | 47 +++++----- src/script/common/c_content.cpp | 154 +++++++++++++++++--------------- src/script/common/c_content.h | 12 ++- src/script/lua_api/l_mapgen.cpp | 131 ++++++++++++++------------- src/script/lua_api/l_mapgen.h | 3 +- 22 files changed, 620 insertions(+), 464 deletions(-) diff --git a/src/emerge.cpp b/src/emerge.cpp index 7427f6f4b..6410e56e9 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -40,8 +40,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "nodedef.h" #include "mg_biome.h" -#include "mg_decoration.h" #include "mg_ore.h" +#include "mg_decoration.h" +#include "mg_schematic.h" #include "mapgen_v5.h" #include "mapgen_v6.h" #include "mapgen_v7.h" @@ -88,8 +89,11 @@ EmergeManager::EmergeManager(IGameDef *gamedef) { registerMapgen("v7", new MapgenFactoryV7()); registerMapgen("singlenode", new MapgenFactorySinglenode()); - this->ndef = gamedef->getNodeDefManager(); - this->biomedef = new BiomeDefManager(gamedef->getNodeDefManager()->getResolver()); + this->ndef = gamedef->getNodeDefManager(); + this->biomemgr = new BiomeManager(gamedef); + this->oremgr = new OreManager(gamedef); + this->decomgr = new DecorationManager(gamedef); + this->schemmgr = new SchematicManager(gamedef); this->gennotify = 0; // Note that accesses to this variable are not synchronized. @@ -141,21 +145,15 @@ EmergeManager::~EmergeManager() { emergethread.clear(); mapgen.clear(); - for (unsigned int i = 0; i < ores.size(); i++) - delete ores[i]; - ores.clear(); - - for (unsigned int i = 0; i < decorations.size(); i++) - delete decorations[i]; - decorations.clear(); - - for (std::map::iterator it = mglist.begin(); - it != mglist.end(); ++it) { + std::map::iterator it; + for (it = mglist.begin(); it != mglist.end(); ++it) delete it->second; - } mglist.clear(); - delete biomedef; + delete biomemgr; + delete oremgr; + delete decomgr; + delete schemmgr; if (params.sparams) { delete params.sparams; diff --git a/src/emerge.h b/src/emerge.h index c8b99a6e1..712289d30 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -23,8 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "irr_v3d.h" #include "util/container.h" -#include "map.h" // for ManualMapVoxelManipulator #include "mapgen.h" // for MapgenParams +#include "map.h" #define MGPARAMS_SET_MGNAME 1 #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 EMERGE_DBG_OUT(x) \ - { if (enable_mapgen_debug_info) \ - infostream << "EmergeThread: " x << std::endl; } + do { \ + if (enable_mapgen_debug_info) \ + infostream << "EmergeThread: " x << std::endl; \ + } while (0) class EmergeThread; -class Biome; -class BiomeDefManager; -class Decoration; -class Ore; class INodeDefManager; class Settings; +//class ManualMapVoxelManipulator; + +class BiomeManager; +class OreManager; +class DecorationManager; +class SchematicManager; struct BlockMakeData { ManualMapVoxelManipulator *vmanip; @@ -88,16 +92,18 @@ public: u32 gennotify; - //block emerge queue data structures + //// Block emerge queue data structures JMutex queuemutex; std::map blocks_enqueued; std::map peer_queue_count; - //Mapgen-related structures - BiomeDefManager *biomedef; - std::vector ores; - std::vector decorations; + //// Managers of map generation-related components + BiomeManager *biomemgr; + OreManager *oremgr; + DecorationManager *decomgr; + SchematicManager *schemmgr; + //// Methods EmergeManager(IGameDef *gamedef); ~EmergeManager(); @@ -105,7 +111,7 @@ public: void initMapgens(); Mapgen *getCurrentMapgen(); Mapgen *createMapgen(std::string mgname, int mgid, - MapgenParams *mgparams); + MapgenParams *mgparams); MapgenSpecificParams *createMapgenParams(std::string mgname); void startThreads(); void stopThreads(); diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 3627675dc..1d3b5869b 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "log.h" +const char *GenElementManager::ELEMENT_TITLE = "element"; FlagDesc flagdesc_mapgen[] = { {"trees", MG_TREES}, @@ -57,16 +58,10 @@ FlagDesc flagdesc_gennotify[] = { {NULL, 0} }; -/////////////////////////////////////////////////////////////////////////////// - - - - /////////////////////////////////////////////////////////////////////////////// - Mapgen::Mapgen() { seed = 0; water_level = 0; @@ -283,10 +278,85 @@ void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) { std::map unlight_from; voxalgo::clearLightAndCollectSources(*vm, a, bank, ndef, - light_sources, unlight_from); + light_sources, unlight_from); voxalgo::propagateSunlight(*vm, a, sunlight, light_sources, ndef); vm->unspreadLight(bank, unlight_from, 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); +} diff --git a/src/mapgen.h b/src/mapgen.h index e29616342..5b189d963 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -20,13 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MAPGEN_HEADER #define MAPGEN_HEADER -#include "irrlichttypes_bloated.h" -#include "util/container.h" // UniqueQueue -#include "gamedef.h" #include "nodedef.h" #include "mapnode.h" -#include "noise.h" -#include "settings.h" +#include "util/string.h" +#include "util/container.h" #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 +class Settings; +class ManualMapVoxelManipulator; +class INodeDefManager; extern FlagDesc flagdesc_mapgen[]; extern FlagDesc flagdesc_gennotify[]; -class BiomeDefManager; class Biome; class EmergeManager; class MapBlock; @@ -53,7 +52,6 @@ struct BlockMakeData; class VoxelArea; class Map; - enum MapgenObject { MGOBJ_VMANIP, MGOBJ_HEIGHTMAP, @@ -131,10 +129,37 @@ public: struct MapgenFactory { virtual Mapgen *createMapgen(int mgid, MapgenParams *params, - EmergeManager *emerge) = 0; + EmergeManager *emerge) = 0; virtual MapgenSpecificParams *createMapgenParams() = 0; 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 m_elements; +}; + +#endif diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp index 4cc382807..afe34164c 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -51,7 +51,7 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) { this->generating = false; this->id = mapgenid; this->emerge = emerge_; - this->bmgr = emerge->biomedef; + this->bmgr = emerge->biomemgr; this->seed = (int)params->seed; this->water_level = params->water_level; @@ -247,16 +247,10 @@ void MapgenV5::makeChunk(BlockMakeData *data) { } // Generate the registered decorations - for (size_t i = 0; i != emerge->decorations.size(); i++) { - Decoration *deco = emerge->decorations[i]; - deco->placeDeco(this, blockseed + i, node_min, node_max); - } + emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); // Generate the registered ores - for (unsigned int i = 0; i != emerge->ores.size(); i++) { - Ore *ore = emerge->ores[i]; - ore->placeOre(this, blockseed + i, node_min, node_max); - } + emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Sprinkle some dust on top after everything else was generated dustTopNodes(); @@ -405,7 +399,7 @@ void MapgenV5::generateBiomes() { for (s16 z = node_min.Z; z <= node_max.Z; z++) 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 y0_top = biome->depth_top; 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 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) continue; diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h index 6f98ad2e4..f50afc42d 100644 --- a/src/mapgen_v5.h +++ b/src/mapgen_v5.h @@ -50,7 +50,7 @@ struct MapgenV5Params : public MapgenSpecificParams { class MapgenV5 : public Mapgen { public: EmergeManager *emerge; - BiomeDefManager *bmgr; + BiomeManager *bmgr; int ystride; int zstride; diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index c126165dc..30d512783 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -537,16 +537,10 @@ void MapgenV6::makeChunk(BlockMakeData *data) { placeTreesAndJungleGrass(); // Generate the registered decorations - for (unsigned int i = 0; i != emerge->decorations.size(); i++) { - Decoration *deco = emerge->decorations[i]; - deco->placeDeco(this, blockseed + i, node_min, node_max); - } + emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); // Generate the registered ores - for (unsigned int i = 0; i != emerge->ores.size(); i++) { - Ore *ore = emerge->ores[i]; - ore->placeOre(this, blockseed + i, node_min, node_max); - } + emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Calculate lighting if (flags & MG_LIGHT) diff --git a/src/mapgen_v6.h b/src/mapgen_v6.h index fa9ea3b1b..1fac37fb6 100644 --- a/src/mapgen_v6.h +++ b/src/mapgen_v6.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MAPGENV6_HEADER #include "mapgen.h" +#include "noise.h" #define AVERAGE_MUD_AMOUNT 4 diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 77aff6e06..8961d8431 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -53,7 +53,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) { this->generating = false; this->id = mapgenid; this->emerge = emerge; - this->bmgr = emerge->biomedef; + this->bmgr = emerge->biomemgr; this->seed = (int)params->seed; this->water_level = params->water_level; @@ -250,16 +250,12 @@ void MapgenV7::makeChunk(BlockMakeData *data) { dgen.generate(blockseed, full_node_min, full_node_max); } - for (size_t i = 0; i != emerge->decorations.size(); i++) { - Decoration *deco = emerge->decorations[i]; - deco->placeDeco(this, blockseed + i, node_min, node_max); - } + // Generate the registered decorations + emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + + // Generate the registered ores + emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); - for (size_t i = 0; i != emerge->ores.size(); i++) { - Ore *ore = emerge->ores[i]; - ore->placeOre(this, blockseed + i, node_min, node_max); - } - // Sprinkle some dust on top after everything else was generated dustTopNodes(); @@ -538,11 +534,11 @@ void MapgenV7::generateBiomes() { for (s16 z = node_min.Z; z <= node_max.Z; z++) 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 y0_top = biome->depth_top; s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller; - + s16 nplaced = 0; u32 i = vm->m_area.index(x, node_max.Y, z); @@ -607,7 +603,7 @@ void MapgenV7::dustTopNodes() { for (s16 z = node_min.Z; z <= node_max.Z; z++) 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) continue; diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index a7c80928f..bc497309b 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MGV7_MOUNTAINS 0x01 #define MGV7_RIDGES 0x02 +class BiomeManager; extern FlagDesc flagdesc_mapgen_v7[]; @@ -52,7 +53,7 @@ struct MapgenV7Params : public MapgenSpecificParams { class MapgenV7 : public Mapgen { public: EmergeManager *emerge; - BiomeDefManager *bmgr; + BiomeManager *bmgr; int ystride; int zstride; diff --git a/src/mg_biome.cpp b/src/mg_biome.cpp index b1172a09d..4b9bc0dc1 100644 --- a/src/mg_biome.cpp +++ b/src/mg_biome.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "mg_biome.h" +#include "gamedef.h" #include "nodedef.h" #include "map.h" //for ManualMapVoxelManipulator #include "log.h" @@ -26,19 +27,25 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/mathconstants.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_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_humidity = &nparams_biome_def_humidity; // Create default biome to be used in case none exist Biome *b = new Biome; - + b->id = 0; b->name = "Default"; b->flags = 0; @@ -55,41 +62,21 @@ BiomeDefManager::BiomeDefManager(NodeResolver *resolver) resolver->addNode("air", "", CONTENT_AIR, &b->c_dust); resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water); - biomes.push_back(b); + add(b); } -BiomeDefManager::~BiomeDefManager() + +BiomeManager::~BiomeManager() { //if (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) -void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) +void BiomeManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) { int i = 0; 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) -{ - 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 *BiomeManager::getBiome(float heat, float humidity, s16 y) { Biome *b, *biome_closest = NULL; float dist_min = FLT_MAX; - for (size_t i = 1; i < biomes.size(); i++) { - b = biomes[i]; - if (y > b->height_max || y < b->height_min) + for (size_t i = 1; i < m_elements.size(); i++) { + b = (Biome *)m_elements[i]; + 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; + } float d_heat = heat - b->heat_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]; -} - - -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; + return biome_closest ? biome_closest : (Biome *)m_elements[0]; } diff --git a/src/mg_biome.h b/src/mg_biome.h index 3724652bd..9c653a768 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -20,12 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MG_BIOME_HEADER #define MG_BIOME_HEADER -#include -#include "nodedef.h" -#include "gamedef.h" -#include "mapnode.h" -#include "noise.h" #include "mapgen.h" +#include "noise.h" + +//#include +//#include "nodedef.h" +//#include "gamedef.h" +//#include "mapnode.h" enum BiomeTerrainType { @@ -39,10 +40,16 @@ enum BiomeTerrainType extern NoiseParams nparams_biome_def_heat; 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: - u8 id; - std::string name; u32 flags; content_t c_top; @@ -60,33 +67,24 @@ public: float humidity_point; }; -struct BiomeNoiseInput { - v2s16 mapsize; - float *heat_map; - float *humidity_map; - s16 *height_map; -}; - -class BiomeDefManager { +class BiomeManager : public GenElementManager { public: - std::vector biomes; + static const char *ELEMENT_TITLE; + static const size_t ELEMENT_LIMIT = 0x100; - bool biome_registration_finished; NoiseParams *np_heat; NoiseParams *np_humidity; - BiomeDefManager(NodeResolver *resolver); - ~BiomeDefManager(); + BiomeManager(IGameDef *gamedef); + ~BiomeManager(); - Biome *createBiome(BiomeTerrainType btt); - void calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map); + Biome *create(int btt) + { + return new Biome; + } + + void calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map); 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 diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index 7f6126bfc..3604b06c0 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -20,28 +20,44 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mg_schematic.h" #include "mapgen.h" +#include "noise.h" #include "map.h" #include "log.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) { - case DECO_SIMPLE: - return new DecoSimple; - case DECO_SCHEMATIC: - return new DecoSchematic; - //case DECO_LSYSTEM: - // return new DecoLSystem; - default: - return NULL; + size_t nplaced = 0; + + for (size_t i = 0; i != m_elements.size(); i++) { + Decoration *deco = (Decoration *)m_elements[i]; + if (!deco) + continue; + + nplaced += deco->placeDeco(mg, seed, nmin, nmax); + seed++; } + + return nplaced; } +/////////////////////////////////////////////////////////////////////////////// + + Decoration::Decoration() { 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); 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)); } } + + return 0; } @@ -190,6 +208,7 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) /////////////////////////////////////////////////////////////////////////////// + bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p) { // 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; } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index 78ff9dc2e..d5c9f0165 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -21,12 +21,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_DECORATION_HEADER #include -#include "mapnode.h" +#include "mapgen.h" class NoiseParams; class Mapgen; class ManualMapVoxelManipulator; class PseudoRandom; +class Schematic; enum DecorationType { DECO_SIMPLE, @@ -34,6 +35,13 @@ enum DecorationType { 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 struct CutoffData { VoxelArea a; @@ -49,7 +57,7 @@ struct CutoffData { }; #endif -class Decoration { +class Decoration : public GenElement { public: INodeDefManager *ndef; @@ -66,12 +74,11 @@ public: Decoration(); virtual ~Decoration(); - void placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); - void placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); + size_t placeDeco(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 int getHeight() = 0; - virtual std::string getName() = 0; }; class DecoSimple : public Decoration { @@ -87,9 +94,22 @@ public: bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p); virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p); 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 { 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 diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index c8d224dc6..9e2d456ee 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -19,10 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_ore.h" #include "mapgen.h" +#include "noise.h" #include "util/numeric.h" #include "map.h" #include "log.h" +const char *OreManager::ELEMENT_TITLE = "ore"; FlagDesc flagdesc_ore[] = { {"absheight", OREFLAG_ABSHEIGHT}, @@ -31,24 +33,36 @@ FlagDesc flagdesc_ore[] = { {NULL, 0} }; + /////////////////////////////////////////////////////////////////////////////// -Ore *createOre(OreType type) +size_t OreManager::placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax) { - 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 nplaced = 0; + + for (size_t i = 0; i != m_elements.size(); i++) { + Ore *ore = (Ore *)m_elements[i]; + if (!ore) + continue; + + nplaced += ore->placeOre(mg, seed, nmin, nmax); + seed++; } + + return nplaced; } +/////////////////////////////////////////////////////////////////////////////// + +Ore::Ore() +{ + c_ore = CONTENT_IGNORE; + np = NULL; + noise = NULL; +} + Ore::~Ore() { delete np; @@ -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; @@ -64,7 +84,7 @@ void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) if (flags & OREFLAG_ABSHEIGHT) in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1; if (!in_range) - return; + return 0; int ymin, ymax; 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); } if (clust_size >= ymax - ymin + 1) - return; + return 0; nmin.Y = ymin; nmax.Y = ymax; generate(mg->vm, mg->seed, blockseed, nmin, nmax); + + return 0; } diff --git a/src/mg_ore.h b/src/mg_ore.h index c279703a8..c1124b0f9 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_ORE_HEADER #include "util/string.h" -#include "mapnode.h" +#include "mapgen.h" class NoiseParams; class Noise; @@ -29,10 +29,13 @@ class Mapgen; class ManualMapVoxelManipulator; /////////////////// Ore generation flags + // Use absolute value of height to determine ore placement #define OREFLAG_ABSHEIGHT 0x01 + // Use 3d noise to get density of ore placement, instead of just the position #define OREFLAG_DENSITY 0x02 // not yet implemented + // For claylike ore types, place ore if the number of surrounding // nodes isn't the specified node #define OREFLAG_NODEISNT 0x04 // not yet implemented @@ -40,7 +43,6 @@ class ManualMapVoxelManipulator; #define ORE_RANGE_ACTUAL 1 #define ORE_RANGE_MIRROR 2 -extern FlagDesc flagdesc_ore[]; enum OreType { ORE_SCATTER, @@ -48,7 +50,9 @@ enum OreType { ORE_CLAYLIKE }; -class Ore { +extern FlagDesc flagdesc_ore[]; + +class Ore : public GenElement { public: content_t c_ore; // the node to place std::vector c_wherein; // the nodes to be placed in @@ -63,32 +67,50 @@ public: NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering) Noise *noise; - Ore() { - c_ore = CONTENT_IGNORE; - np = NULL; - noise = NULL; - } - + 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, u32 blockseed, v3s16 nmin, v3s16 nmax) = 0; + virtual std::string getName(); }; class OreScatter : public Ore { - ~OreScatter() {} + virtual ~OreScatter() {} virtual void generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax); }; class OreSheet : public Ore { - ~OreSheet() {} + virtual ~OreSheet() {} virtual void generate(ManualMapVoxelManipulator *vm, int seed, 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 diff --git a/src/mg_schematic.cpp b/src/mg_schematic.cpp index 8b34fb4fd..92cbf8e4e 100644 --- a/src/mg_schematic.cpp +++ b/src/mg_schematic.cpp @@ -28,79 +28,42 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" #include "filesys.h" -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} -}; +const char *SchematicManager::ELEMENT_TITLE = "schematic"; + /////////////////////////////////////////////////////////////////////////////// -DecoSchematic::DecoSchematic() +Schematic::Schematic() { - schematic = NULL; + schemdata = NULL; slice_probs = NULL; flags = 0; size = v3s16(0, 0, 0); } -DecoSchematic::~DecoSchematic() +Schematic::~Schematic() { - delete []schematic; + delete []schemdata; delete []slice_probs; } -void DecoSchematic::updateContentIds() +void Schematic::updateContentIds() { - if (flags & DECO_SCHEM_CIDS_UPDATED) + if (flags & SCHEM_CIDS_UPDATED) return; - flags |= DECO_SCHEM_CIDS_UPDATED; + flags |= SCHEM_CIDS_UPDATED; 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) -{ - 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) +void Schematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm, + Rotation rot, bool force_placement, INodeDefManager *ndef) { int xstride = 1; int ystride = size.X; @@ -150,10 +113,10 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm, if (!vm->m_area.contains(vi)) continue; - if (schematic[i].getContent() == CONTENT_IGNORE) + if (schemdata[i].getContent() == CONTENT_IGNORE) continue; - if (schematic[i].param1 == MTSCHEM_PROB_NEVER) + if (schemdata[i].param1 == MTSCHEM_PROB_NEVER) continue; if (!force_placement) { @@ -162,11 +125,11 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm, continue; } - if (schematic[i].param1 != MTSCHEM_PROB_ALWAYS && - myrand_range(1, 255) > schematic[i].param1) + if (schemdata[i].param1 != MTSCHEM_PROB_ALWAYS && + myrand_range(1, 255) > schemdata[i].param1) continue; - vm->m_data[vi] = schematic[i]; + vm->m_data[vi] = schemdata[i]; vm->m_data[vi].param1 = 0; 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); - Rotation rot = (rotation == ROTATE_RAND) ? - (Rotation)myrand_range(ROTATE_0, ROTATE_270) : rotation; + if (rot == ROTATE_RAND) + rot = (Rotation)myrand_range(ROTATE_0, ROTATE_270); v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ? 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)); vm->initialEmerge(bp1, bp2); - blitToVManip(p, vm, rot, force_placement); + blitToVManip(p, vm, rot, force_placement, ndef); std::map lighting_modified_blocks; std::map 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 &replace_names) { content_t cignore = CONTENT_IGNORE; 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); if (signature != MTSCHEM_FILE_SIGNATURE) { @@ -247,13 +212,8 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver, delete []slice_probs; slice_probs = new u8[size.Y]; - if (version >= 3) { - for (int y = 0; y != size.Y; y++) - slice_probs[y] = readU8(is); - } else { - for (int y = 0; y != size.Y; y++) - slice_probs[y] = MTSCHEM_PROB_ALWAYS; - } + for (int y = 0; y != size.Y; y++) + slice_probs[y] = (version >= 3) ? readU8(is) : MTSCHEM_PROB_ALWAYS; int nodecount = size.X * size.Y * size.Z; @@ -268,7 +228,6 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver, } std::map::iterator it; - it = replace_names.find(name); if (it != replace_names.end()) name = it->second; @@ -276,17 +235,17 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver, resolver->addNodeList(name.c_str(), &c_nodes); } - delete []schematic; - schematic = new MapNode[nodecount]; - MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic, + delete []schemdata; + schemdata = new MapNode[nodecount]; + MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schemdata, nodecount, 2, 2, true); if (version == 1) { // fix up the probability values for (int i = 0; i != nodecount; i++) { - if (schematic[i].param1 == 0) - schematic[i].param1 = MTSCHEM_PROB_ALWAYS; - if (have_cignore && schematic[i].getContent() == cignore) - schematic[i].param1 = MTSCHEM_PROB_NEVER; + if (schemdata[i].param1 == 0) + schemdata[i].param1 = MTSCHEM_PROB_ALWAYS; + if (have_cignore && schemdata[i].getContent() == cignore) + 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 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); @@ -337,7 +296,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) std::vector usednodes; 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(); writeU16(ss, numids); // name count @@ -345,7 +304,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) ss << serializeString(ndef->get(usednodes[i]).name); // node names // 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); 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); @@ -391,15 +350,15 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) for (s16 y = 0; y != size.Y; y++) 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; for (s16 z = p1.Z; z <= p2.Z; z++) for (s16 y = p1.Y; y <= p2.Y; y++) { u32 vi = vm->m_area.index(p1.X, y, z); for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) { - schematic[i] = vm->m_data[vi]; - schematic[i].param1 = MTSCHEM_PROB_ALWAYS; + schemdata[i] = vm->m_data[vi]; + 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 > *plist, std::vector > *splist) { @@ -417,11 +376,11 @@ void DecoSchematic::applyProbabilities(v3s16 p0, int index = p.Z * (size.Y * size.X) + p.Y * size.X + p.X; if (index < size.Z * size.Y * size.X) { u8 prob = (*plist)[i].second; - schematic[index].param1 = prob; + schemdata[index].param1 = prob; // trim unnecessary node names from schematic if (prob == MTSCHEM_PROB_NEVER) - schematic[index].setContent(CONTENT_AIR); + schemdata[index].setContent(CONTENT_AIR); } } diff --git a/src/mg_schematic.h b/src/mg_schematic.h index 8a495fef2..9d4d4a716 100644 --- a/src/mg_schematic.h +++ b/src/mg_schematic.h @@ -30,11 +30,8 @@ class ManualMapVoxelManipulator; class PseudoRandom; class NodeResolver; -/////////////////// Decoration flags -#define DECO_PLACE_CENTER_X 1 -#define DECO_PLACE_CENTER_Y 2 -#define DECO_PLACE_CENTER_Z 4 -#define DECO_SCHEM_CIDS_UPDATED 8 +/////////////////// Schematic flags +#define SCHEM_CIDS_UPDATED 0x08 #define MTSCHEM_FILE_SIGNATURE 0x4d54534d // 'MTSM' @@ -44,42 +41,50 @@ class NodeResolver; #define MTSCHEM_PROB_NEVER 0x00 #define MTSCHEM_PROB_ALWAYS 0xFF -extern FlagDesc flagdesc_deco_schematic[]; -class DecoSchematic : public Decoration { +class Schematic : public GenElement { public: - std::string filename; - std::vector c_nodes; u32 flags; - Rotation rotation; v3s16 size; - MapNode *schematic; + MapNode *schemdata; u8 *slice_probs; - DecoSchematic(); - ~DecoSchematic(); + Schematic(); + ~Schematic(); 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, - 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 &replace_names); - void saveSchematicFile(INodeDefManager *ndef); - + void saveSchematicToFile(const char *filename, INodeDefManager *ndef); 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, std::vector > *plist, std::vector > *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, std::vector *usednodes); diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 88bbedec5..0e1e608c4 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1009,86 +1009,98 @@ 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 &replace_names) +{ if (index < 0) index = lua_gettop(L) + 1 + index; - INodeDefManager *ndef = server->getNodeDefManager(); - if (lua_istable(L, index)) { - lua_getfield(L, index, "size"); - v3s16 size = read_v3s16(L, -1); - lua_pop(L, 1); - - int numnodes = size.X * size.Y * size.Z; - MapNode *schemdata = new MapNode[numnodes]; - int i = 0; - - // Get schematic data - lua_getfield(L, index, "data"); - luaL_checktype(L, -1, LUA_TTABLE); - - lua_pushnil(L); - while (lua_next(L, -2)) { - if (i < numnodes) { - // same as readnode, except param1 default is MTSCHEM_PROB_CONST - lua_getfield(L, -1, "name"); - const char *name = luaL_checkstring(L, -1); - lua_pop(L, 1); - - u8 param1; - lua_getfield(L, -1, "param1"); - param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS; - lua_pop(L, 1); - - u8 param2; - lua_getfield(L, -1, "param2"); - param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; - lua_pop(L, 1); - - schemdata[i] = MapNode(ndef, name, param1, param2); - } - - i++; - lua_pop(L, 1); - } - - if (i != numnodes) { - errorstream << "read_schematic: incorrect number of " - "nodes provided in raw schematic data (got " << i << - ", expected " << numnodes << ")." << std::endl; - return false; - } - - u8 *sliceprobs = new u8[size.Y]; - for (i = 0; i != size.Y; i++) - sliceprobs[i] = MTSCHEM_PROB_ALWAYS; - - // Get Y-slice probability values (if present) - lua_getfield(L, index, "yslice_prob"); - if (lua_istable(L, -1)) { - lua_pushnil(L); - while (lua_next(L, -2)) { - if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) { - sliceprobs[i] = getintfield_default(L, -1, - "prob", MTSCHEM_PROB_ALWAYS); - } - lua_pop(L, 1); - } - } - - dschem->size = size; - dschem->schematic = schemdata; - dschem->slice_probs = sliceprobs; - + return read_schematic(L, index, schem, ndef, replace_names); } else if (lua_isstring(L, index)) { - dschem->filename = std::string(lua_tostring(L, index)); + NodeResolver *resolver = ndef->getResolver(); + const char *filename = lua_tostring(L, index); + return schem->loadSchematicFromFile(filename, resolver, replace_names); } else { - errorstream << "read_schematic: missing schematic " - "filename or raw schematic data" << std::endl; return false; } +} + +bool read_schematic(lua_State *L, int index, Schematic *schem, + INodeDefManager *ndef, std::map &replace_names) +{ + //// Get schematic size + lua_getfield(L, index, "size"); + v3s16 size = read_v3s16(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; + MapNode *schemdata = new MapNode[numnodes]; + int i = 0; + + lua_pushnil(L); + while (lua_next(L, -2)) { + if (i < numnodes) { + // same as readnode, except param1 default is MTSCHEM_PROB_CONST + lua_getfield(L, -1, "name"); + std::string name = luaL_checkstring(L, -1); + lua_pop(L, 1); + + u8 param1; + lua_getfield(L, -1, "param1"); + param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS; + lua_pop(L, 1); + + u8 param2; + lua_getfield(L, -1, "param2"); + param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; + lua_pop(L, 1); + + std::map::iterator it; + it = replace_names.find(name); + if (it != replace_names.end()) + name = it->second; + + schemdata[i] = MapNode(ndef, name, param1, param2); + } + + i++; + lua_pop(L, 1); + } + + if (i != numnodes) { + errorstream << "read_schematic: incorrect number of " + "nodes provided in raw schematic data (got " << i << + ", expected " << numnodes << ")." << std::endl; + return false; + } + + //// Get Y-slice probability values (if present) + u8 *slice_probs = new u8[size.Y]; + for (i = 0; i != size.Y; i++) + slice_probs[i] = MTSCHEM_PROB_ALWAYS; + + lua_getfield(L, index, "yslice_prob"); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2)) { + if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) { + slice_probs[i] = getintfield_default(L, -1, + "prob", MTSCHEM_PROB_ALWAYS); + } + lua_pop(L, 1); + } + } + + schem->flags = 0; + schem->size = size; + schem->schemdata = schemdata; + schem->slice_probs = slice_probs; return true; } diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index f48c673bd..5b4dff2bd 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -59,7 +59,7 @@ struct DigParams; struct HitParams; struct EnumString; struct NoiseParams; -class DecoSchematic; +class Schematic; 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, NoiseParams *np); - +bool get_schematic (lua_State *L, int index, + Schematic *schem, + INodeDefManager *ndef, + std::map &replace_names); bool read_schematic (lua_State *L, int index, - DecoSchematic *dschem, - Server *server); + Schematic *dschem, + INodeDefManager *ndef, + std::map &replace_names); void luaentity_get (lua_State *L,u16 id); diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 2ed9fadf9..71b1f4740 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -25,13 +25,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/serialize.h" #include "server.h" #include "environment.h" -#include "mg_biome.h" #include "emerge.h" #include "mg_biome.h" #include "mg_ore.h" #include "mg_decoration.h" #include "mg_schematic.h" #include "mapgen_v7.h" +#include "settings.h" #include "main.h" #include "log.h" @@ -85,7 +85,7 @@ struct EnumString ModApiMapgen::es_Rotation[] = static void read_schematic_replacements(lua_State *L, - std::map replace_names, int index) + std::map &replace_names, int index) { lua_pushnil(L); while (lua_next(L, index)) { @@ -310,13 +310,13 @@ int ModApiMapgen::l_register_biome(lua_State *L) luaL_checktype(L, index, LUA_TTABLE); 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, "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL); - Biome *b = bmgr->createBiome(terrain); + Biome *b = bmgr->create(terrain); - b->name = getstringfield_default(L, index, "name", ""); + b->name = getstringfield_default(L, index, "name", ""); b->depth_top = getintfield_default(L, index, "depth_top", 1); b->depth_filler = getintfield_default(L, index, "depth_filler", 3); b->height_min = getintfield_default(L, index, "height_min", 0); @@ -325,7 +325,8 @@ int ModApiMapgen::l_register_biome(lua_State *L) b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.); b->flags = 0; //reserved - if (!bmgr->addBiome(b)) { + u32 id = bmgr->add(b); + if (id == (u32)-1) { delete b; return 0; } @@ -344,7 +345,8 @@ int ModApiMapgen::l_register_biome(lua_State *L) verbosestream << "register_biome: " << b->name << std::endl; - return 0; + lua_pushinteger(L, id); + return 1; } // register_decoration({lots of stuff}) @@ -353,20 +355,22 @@ int ModApiMapgen::l_register_decoration(lua_State *L) int index = 1; luaL_checktype(L, index, LUA_TTABLE); - EmergeManager *emerge = getServer(L)->getEmergeManager(); - BiomeDefManager *bdef = emerge->biomedef; - NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + 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, "deco_type", es_DecorationType, -1); - Decoration *deco = createDecoration(decotype); + Decoration *deco = decomgr->create(decotype); if (!deco) { errorstream << "register_decoration: decoration placement type " << decotype << " not implemented"; return 0; } + deco->name = getstringfield_default(L, index, "name", ""); deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); deco->sidelen = getintfield_default(L, index, "sidelen", 8); if (deco->sidelen <= 0) { @@ -391,9 +395,11 @@ int ModApiMapgen::l_register_decoration(lua_State *L) std::vector biome_list; getstringlistfield(L, index, "biomes", biome_list); for (size_t i = 0; i != biome_list.size(); i++) { - u8 biomeid = bdef->getBiomeIdByName(biome_list[i]); - if (biomeid) - deco->biomes.insert(biomeid); + Biome *b = (Biome *)biomemgr->getByName(biome_list[i]); + if (!b) + continue; + + deco->biomes.insert(b->id); } //// Handle decoration type-specific parameters @@ -403,7 +409,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) success = regDecoSimple(L, resolver, (DecoSimple *)deco); break; case DECO_SCHEMATIC: - success = regDecoSchematic(L, resolver, (DecoSchematic *)deco); + success = regDecoSchematic(L, ndef, (DecoSchematic *)deco); break; case DECO_LSYSTEM: break; @@ -414,12 +420,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L) return 0; } - emerge->decorations.push_back(deco); + u32 id = decomgr->add(deco); + if (id == (u32)-1) { + delete deco; + return 0; + } - verbosestream << "register_decoration: decoration '" << deco->getName() - << "' registered" << std::endl; - - return 0; + lua_pushinteger(L, id); + return 1; } bool ModApiMapgen::regDecoSimple(lua_State *L, @@ -461,8 +469,8 @@ bool ModApiMapgen::regDecoSimple(lua_State *L, return true; } -bool ModApiMapgen::regDecoSchematic(lua_State *L, - NodeResolver *resolver, DecoSchematic *deco) +bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef, + DecoSchematic *deco) { int index = 1; @@ -478,19 +486,16 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L, read_schematic_replacements(L, replace_names, lua_gettop(L)); lua_pop(L, 1); + Schematic *schem = new 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); + delete schem; return false; } lua_pop(L, 1); - if (!deco->filename.empty() && - !deco->loadSchematicFile(resolver, replace_names)) { - errorstream << "register_decoration: failed to load schematic" - " file '" << deco->filename << "'" << std::endl; - return false; - } + deco->schematic = schem; return true; } @@ -501,25 +506,25 @@ int ModApiMapgen::l_register_ore(lua_State *L) int index = 1; luaL_checktype(L, index, LUA_TTABLE); - EmergeManager *emerge = getServer(L)->getEmergeManager(); NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); + OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr; enum OreType oretype = (OreType)getenumfield(L, index, "ore_type", es_OreType, ORE_SCATTER); - Ore *ore = createOre(oretype); + Ore *ore = oremgr->create(oretype); if (!ore) { - errorstream << "register_ore: ore_type " - << oretype << " not implemented"; + errorstream << "register_ore: ore_type " << oretype << " not implemented"; return 0; } + ore->name = getstringfield_default(L, index, "name", ""); ore->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0); ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1); ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1); ore->clust_size = getintfield_default(L, index, "clust_size", 0); ore->height_min = getintfield_default(L, index, "height_min", 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->flags = 0; @@ -536,6 +541,12 @@ int ModApiMapgen::l_register_ore(lua_State *L) ore->np = read_noiseparams(L, -1); lua_pop(L, 1); + u32 id = oremgr->add(ore); + if (id == (u32)-1) { + delete ore; + return 0; + } + std::vector wherein_names; getstringlistfield(L, index, "wherein", wherein_names); 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", ""), "", CONTENT_AIR, &ore->c_ore); - emerge->ores.push_back(ore); - - //verbosestream << "register_ore: ore '" << ore->ore_name - // << "' registered" << std::endl; - return 0; + lua_pushinteger(L, id); + return 1; } // create_schematic(p1, p2, probability_list, filename) int ModApiMapgen::l_create_schematic(lua_State *L) { - DecoSchematic dschem; + Schematic schem; Map *map = &(getEnv(L)->getMap()); INodeDefManager *ndef = getServer(L)->getNodeDefManager(); @@ -594,20 +602,19 @@ int ModApiMapgen::l_create_schematic(lua_State *L) } } - const char *s = lua_tostring(L, 4); - dschem.filename = std::string(s ? s : ""); + const char *filename = luaL_checkstring(L, 4); - if (!dschem.getSchematicFromMap(map, p1, p2)) { + if (!schem.getSchematicFromMap(map, p1, p2)) { errorstream << "create_schematic: failed to get schematic " "from map" << std::endl; 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 '" - << dschem.filename << "'." << std::endl; + << filename << "'." << std::endl; return 1; } @@ -615,38 +622,36 @@ int ModApiMapgen::l_create_schematic(lua_State *L) // place_schematic(p, schematic, rotation, replacement) int ModApiMapgen::l_place_schematic(lua_State *L) { - DecoSchematic dschem; + Schematic schem; Map *map = &(getEnv(L)->getMap()); - NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver(); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + //// Read position v3s16 p = read_v3s16(L, 1); - if (!read_schematic(L, 2, &dschem, getServer(L))) - return 0; + //// Read rotation int rot = ROTATE_0; if (lua_isstring(L, 3)) string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3))); - dschem.rotation = (Rotation)rot; - - std::map replace_names; - if (lua_istable(L, 4)) - read_schematic_replacements(L, replace_names, 4); - + //// Read force placement bool force_placement = true; if (lua_isboolean(L, 5)) force_placement = lua_toboolean(L, 5); - if (!dschem.filename.empty()) { - if (!dschem.loadSchematicFile(resolver, replace_names)) { - errorstream << "place_schematic: failed to load schematic file '" - << dschem.filename << "'" << std::endl; - return 0; - } + //// Read node replacements + std::map replace_names; + if (lua_istable(L, 4)) + 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; } - dschem.placeStructure(map, p, force_placement); + schem.placeStructure(map, p, 0, (Rotation)rot, force_placement, ndef); return 1; } diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index d14471a08..dac0f00a7 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" +class INodeDefManager; class NodeResolver; class DecoSimple; class DecoSchematic; @@ -60,7 +61,7 @@ private: static bool regDecoSimple(lua_State *L, NodeResolver *resolver, DecoSimple *deco); static bool regDecoSchematic(lua_State *L, - NodeResolver *resolver, DecoSchematic *deco); + INodeDefManager *ndef, DecoSchematic *deco); static struct EnumString es_BiomeTerrainType[]; static struct EnumString es_DecorationType[];