From 631a835e0782a2696762e3d55f75616f5a063394 Mon Sep 17 00:00:00 2001
From: kwolekr <mirrorisim@gmail.com>
Date: Sun, 6 Jan 2013 14:40:24 -0500
Subject: [PATCH] Finish and clean up mapgen configuration

---
 src/biome.cpp           |   6 +-
 src/defaultsettings.cpp |  26 ++++-
 src/map.cpp             |  95 +++++++++---------
 src/map.h               |  88 +++++++++--------
 src/mapgen.cpp          | 213 +++++++++++++++++++++++++++-------------
 src/mapgen.h            | 129 ++++++++----------------
 src/mapgen_v6.cpp       |  69 ++++---------
 src/noise.cpp           |   2 +-
 src/noise.h             |  10 +-
 src/scriptapi.cpp       |   4 +-
 src/server.cpp          |  23 +++--
 src/server.h            |   5 +
 src/settings.h          |  70 ++++++++-----
 13 files changed, 397 insertions(+), 343 deletions(-)

diff --git a/src/biome.cpp b/src/biome.cpp
index 07dad1f23..80b8d8f4f 100644
--- a/src/biome.cpp
+++ b/src/biome.cpp
@@ -78,7 +78,7 @@ BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
 
 
 BiomeDefManager::~BiomeDefManager() {
-	for (int i = 0; i != bgroups.size(); i++)
+	for (unsigned int i = 0; i != bgroups.size(); i++)
 		delete bgroups[i];
 }
 
@@ -96,6 +96,7 @@ Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) {
 		case BIOME_TERRAIN_FLAT:
 			return new BiomeSuperflat;
 	}
+	return NULL;
 }
 
 
@@ -116,7 +117,7 @@ void BiomeDefManager::addBiomeGroup(float freq) {
 void BiomeDefManager::addBiome(Biome *b) {
 	std::vector<Biome *> *bgroup;
 
-	if (b->groupid >= bgroups.size()) {
+	if ((unsigned int)b->groupid >= bgroups.size()) {
 		errorstream << "BiomeDefManager: attempted to add biome '" << b->name
 		 << "' to nonexistent biome group " << b->groupid << std::endl;
 		return;
@@ -131,7 +132,6 @@ void BiomeDefManager::addBiome(Biome *b) {
 
 
 void BiomeDefManager::addDefaultBiomes() {
-	std::vector<Biome *> *bgroup;
 	Biome *b;
 
 	b = new Biome;
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 1ccaf887d..b2d14d3c4 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -153,7 +153,6 @@ void set_default_settings(Settings *settings)
 
 	settings->setDefault("profiler_print_interval", "0");
 	settings->setDefault("enable_mapgen_debug_info", "false");
-	settings->setDefault("use_mapgen_version", "6");
 	settings->setDefault("active_object_send_range_blocks", "3");
 	settings->setDefault("active_block_range", "2");
 	//settings->setDefault("max_simultaneous_block_sends_per_client", "1");
@@ -164,16 +163,37 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("max_block_generate_distance", "7");
 	settings->setDefault("time_send_interval", "5");
 	settings->setDefault("time_speed", "72");
-	settings->setDefault("default_water_level", "1");
 	settings->setDefault("server_unload_unused_data_timeout", "29");
 	settings->setDefault("server_map_save_interval", "5.3");
 	settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
 	settings->setDefault("dedicated_server_step", "0.1");
 	settings->setDefault("ignore_world_load_errors", "false");
-	settings->setDefault("mgv6_use_smooth_biome_trans", "true"); //temporary
 	settings->setDefault("congestion_control_aim_rtt", "0.2");
 	settings->setDefault("congestion_control_max_rate", "400");
 	settings->setDefault("congestion_control_min_rate", "10");
 	settings->setDefault("remote_media", "");
+	
+	//mapgen related things
+	settings->setDefault("mg_version", "6");
+	settings->setDefault("water_level", "1");
+	settings->setDefault("chunksize", "5");
+	settings->setDefault("mg_flags", "19");
+	settings->setDefault("mgv6_freq_desert", "0.45");
+	settings->setDefault("mgv6_freq_beach", "0.15");
+
+	settings->setDefault("mgv6_np_terrain_base",   "-4, 20, (250.0, 250, 250), 82341, 5, 0.6");
+	settings->setDefault("mgv6_np_terrain_higher", "20, 16, (500, 500, 500), 85039, 5, 0.6");
+	settings->setDefault("mgv6_np_steepness",      "0.85, 0.5, (125, 125, 125), -932, 5, 0.7");
+	settings->setDefault("mgv6_np_height_select",  "0.5, 1, (250, 250, 250), 4213, 5, 0.69");
+	settings->setDefault("mgv6_np_trees",          "0, 1, (125, 125, 125), 2, 4, 0.66");
+	settings->setDefault("mgv6_np_mud",            "4, 2, (200, 200, 200), 91013, 3, 0.55");
+	settings->setDefault("mgv6_np_beach",          "0, 1, (250, 250, 250), 59420, 3, 0.50");
+	settings->setDefault("mgv6_np_biome",          "0, 1, (250, 250, 250), 9130, 3, 0.50");
+	settings->setDefault("mgv6_np_cave",           "6, 6, (250, 250, 250), 34329, 3, 0.50");
+
+	settings->setDefault("mgv7_np_terrain",  "10, 12, (350, 350, 350), 82341, 5, 0.6");
+	settings->setDefault("mgv7_np_bgroup",   "0.5, 0.3125, (350, 350, 350), 5923, 2, 0.6");
+	settings->setDefault("mgv7_np_heat",     "25, 50, (500, 500, 500), 35293, 1, 0");
+	settings->setDefault("mgv7_np_humidity", "50, 31.25, (750, 750, 750), 12094, 2, 0.6");
 }
 
diff --git a/src/map.cpp b/src/map.cpp
index d6d8c5611..0099e4157 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1993,10 +1993,10 @@ void Map::removeNodeTimer(v3s16 p)
 /*
 	ServerMap
 */
-
-ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge):
+ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
 	Map(dout_server, gamedef),
 	m_seed(0),
+	m_emerge(NULL),
 	m_map_metadata_changed(true),
 	m_database(NULL),
 	m_database_read(NULL),
@@ -2004,26 +2004,22 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer
 {
 	verbosestream<<__FUNCTION_NAME<<std::endl;
 
-	m_emerge = emerge;
-
 	//m_chunksize = 8; // Takes a few seconds
 
+	m_mgparams = MapgenParams::getParamsFromSettings(g_settings);
+	if (!m_mgparams)
+		m_mgparams = new MapgenV6Params();
+		
+	m_seed = m_mgparams->seed;
+
 	if (g_settings->get("fixed_map_seed").empty())
 	{
 		m_seed = (((u64)(myrand()%0xffff)<<0)
 				+ ((u64)(myrand()%0xffff)<<16)
 				+ ((u64)(myrand()%0xffff)<<32)
 				+ ((u64)(myrand()&0xffff)<<48));
+		m_mgparams->seed = m_seed;
 	}
-	else
-	{
-		m_seed = g_settings->getU64("fixed_map_seed");
-	}
-	//emerge->params.seed = m_seed;
-	//emerge->params.water_level = g_settings->getS16("default_water_level");
-	//mapgen version
-	//chunksize
-	//noiseparams
 
 	/*
 		Experimental and debug stuff
@@ -2057,6 +2053,10 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer
 					// Load map metadata (seed, chunksize)
 					loadMapMeta();
 				}
+				catch(SettingNotFoundException &e){
+					infostream<<"ServerMap:  Some metadata not found."
+							  <<" Using default settings."<<std::endl;
+				}
 				catch(FileNotGoodException &e){
 					infostream<<"WARNING: Could not load map metadata"
 							//<<" Disabling chunk-based generator."
@@ -3079,25 +3079,38 @@ void ServerMap::saveMapMeta()
 
 	Settings params;
 
-	params.setS16("mg_version", m_emerge->mg_version);
+	params.setS16("mg_version", m_emerge->params->mg_version);
 
 	params.setU64("seed", m_emerge->params->seed);
 	params.setS16("water_level", m_emerge->params->water_level);
 	params.setS16("chunksize", m_emerge->params->chunksize);
-	params.setS32("flags", m_emerge->params->flags);
-	switch (m_emerge->mg_version) {
+	params.setS32("mg_flags", m_emerge->params->flags);
+	switch (m_emerge->params->mg_version) {
 		case 6:
 		{
-			MapgenV6Params *v6params = m_emerge->params;
-
-			params.setFloat("freq_desert", v6params->freq_desert);
-			params.setFloat("freq_beach", v6params->freq_beach);
-
+			MapgenV6Params *v6params = (MapgenV6Params *)m_emerge->params;
+
+			params.setFloat("mgv6_freq_desert", v6params->freq_desert);
+			params.setFloat("mgv6_freq_beach", v6params->freq_beach);
+			params.setNoiseParams("mgv6_np_terrain_base",   v6params->np_terrain_base);
+			params.setNoiseParams("mgv6_np_terrain_higher", v6params->np_terrain_higher);
+			params.setNoiseParams("mgv6_np_steepness",      v6params->np_steepness);
+			params.setNoiseParams("mgv6_np_height_select",  v6params->np_height_select);
+			params.setNoiseParams("mgv6_np_trees",          v6params->np_trees);
+			params.setNoiseParams("mgv6_np_mud",            v6params->np_mud);
+			params.setNoiseParams("mgv6_np_beach",          v6params->np_beach);
+			params.setNoiseParams("mgv6_np_biome",          v6params->np_biome);
+			params.setNoiseParams("mgv6_np_cave",           v6params->np_cave);
 			break;
 		}
 		case 7:
 		{
-			MapgenV7Params *v7params = m_emerge->params;
+			MapgenV7Params *v7params = (MapgenV7Params *)m_emerge->params;
+
+			params.setNoiseParams("mgv7_np_terrain",  v7params->np_terrain);
+			params.setNoiseParams("mgv7_np_bgroup",   v7params->np_bgroup);
+			params.setNoiseParams("mgv7_np_heat",     v7params->np_heat);
+			params.setNoiseParams("mgv7_np_humidity", v7params->np_humidity);
 			break;
 		}
 		default:
@@ -3142,37 +3155,19 @@ void ServerMap::loadMapMeta()
 		params.parseConfigLine(line);
 	}
 
-	m_emerge->mg_version  = params.getS16("mg_version");
-	m_emerge->setMapgenParams();
-
-	m_emerge->params->seed        = params.getU64("seed");
-	m_emerge->params->water_level = params.getS16("water_level");
-	m_emerge->params->chunksize   = params.getS16("chunksize");
-	m_emerge->params->flags       = params.getS32("flags");
-
-	m_seed = m_emerge->params->seed;
-
-	switch (m_emerge->mg_version) {
-		case 6:
-		{
-			MapgenV6Params *v6params = m_emerge->params;
-
-			v6params->freq_desert = params.getFloat("freq_desert");
-			v6params->freq_beach  = params.getFloat("freq_beach");
-
-			break;
+	MapgenParams *mgparams = MapgenParams::getParamsFromSettings(&params);
+	if (mgparams) {
+		if (m_mgparams)
+			delete m_mgparams;
+		m_mgparams = mgparams;
+		m_seed = mgparams->seed;
+	} else {
+		if (params.exists("seed")) {
+			m_seed = params.getU64("seed");
+			m_mgparams->seed = m_seed;
 		}
-		case 7:
-		{
-			MapgenV7Params *v6params = m_emerge->params;
-
-			break;
-		}
-		default:
-			; //complain here
 	}
 
-
 	verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
 }
 
diff --git a/src/map.h b/src/map.h
index 3097d15b9..760b23de5 100644
--- a/src/map.h
+++ b/src/map.h
@@ -81,7 +81,7 @@ struct MapEditEvent
 		already_known_by_peer(0)
 	{
 	}
-	
+
 	MapEditEvent * clone()
 	{
 		MapEditEvent *event = new MapEditEvent();
@@ -155,7 +155,7 @@ class Map /*: public NodeContainer*/
 	{
 		return MAPTYPE_BASE;
 	}
-	
+
 	/*
 		Drop (client) or delete (server) the map.
 	*/
@@ -168,7 +168,7 @@ class Map /*: public NodeContainer*/
 	void removeEventReceiver(MapEventReceiver *event_receiver);
 	// event shall be deleted by caller after the call.
 	void dispatchEvent(MapEditEvent *event);
-	
+
 	// On failure returns NULL
 	MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
 	// Same as the above (there exists no lock anymore)
@@ -190,22 +190,22 @@ class Map /*: public NodeContainer*/
 	MapBlock * getBlockNoCreate(v3s16 p);
 	// Returns NULL if not found
 	MapBlock * getBlockNoCreateNoEx(v3s16 p);
-	
+
 	/* Server overrides */
 	virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true)
 	{ return getBlockNoCreateNoEx(p); }
 
 	// Returns InvalidPositionException if not found
 	bool isNodeUnderground(v3s16 p);
-	
+
 	bool isValidPosition(v3s16 p);
-	
+
 	// throws InvalidPositionException if not found
 	MapNode getNode(v3s16 p);
 
 	// throws InvalidPositionException if not found
 	void setNode(v3s16 p, MapNode & n);
-	
+
 	// Returns a CONTENT_IGNORE node if not found
 	MapNode getNodeNoEx(v3s16 p);
 
@@ -218,11 +218,11 @@ class Map /*: public NodeContainer*/
 			v3s16 pos, u8 lightwas,
 			core::map<v3s16, bool> & light_sources,
 			core::map<v3s16, MapBlock*> & modified_blocks);
-	
+
 	void spreadLight(enum LightBank bank,
 			core::map<v3s16, bool> & from_nodes,
 			core::map<v3s16, MapBlock*> & modified_blocks);
-	
+
 	void lightNeighbors(enum LightBank bank,
 			v3s16 pos,
 			core::map<v3s16, MapBlock*> & modified_blocks);
@@ -231,14 +231,14 @@ class Map /*: public NodeContainer*/
 
 	s16 propagateSunlight(v3s16 start,
 			core::map<v3s16, MapBlock*> & modified_blocks);
-	
+
 	void updateLighting(enum LightBank bank,
 			core::map<v3s16, MapBlock*>  & a_blocks,
 			core::map<v3s16, MapBlock*> & modified_blocks);
-			
+
 	void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
 			core::map<v3s16, MapBlock*> & modified_blocks);
-			
+
 	/*
 		These handle lighting but not faces.
 	*/
@@ -254,7 +254,7 @@ class Map /*: public NodeContainer*/
 	*/
 	bool addNodeWithEvent(v3s16 p, MapNode n);
 	bool removeNodeWithEvent(v3s16 p);
-	
+
 	/*
 		Takes the blocks at the edges into account
 	*/
@@ -267,9 +267,9 @@ class Map /*: public NodeContainer*/
 	// Call these before and after saving of many blocks
 	virtual void beginSave() {return;};
 	virtual void endSave() {return;};
-	
+
 	virtual void save(ModifiedState save_level){assert(0);};
-	
+
 	// Server implements this.
 	// Client leaves it as no-op.
 	virtual void saveBlock(MapBlock *block){};
@@ -280,7 +280,7 @@ class Map /*: public NodeContainer*/
 	*/
 	void timerUpdate(float dtime, float unload_timeout,
 			core::list<v3s16> *unloaded_blocks=NULL);
-		
+
 	// Deletes sectors and their blocks from memory
 	// Takes cache into account
 	// If deleted sector is in sector cache, clears cache
@@ -298,14 +298,14 @@ class Map /*: public NodeContainer*/
 
 	// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
 	virtual void PrintInfo(std::ostream &out);
-	
+
 	void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
 
 	/*
 		Node metadata
 		These are basically coordinate wrappers to MapBlock
 	*/
-	
+
 	NodeMetadata* getNodeMetadata(v3s16 p);
 	void setNodeMetadata(v3s16 p, NodeMetadata *meta);
 	void removeNodeMetadata(v3s16 p);
@@ -314,7 +314,7 @@ class Map /*: public NodeContainer*/
 		Node Timers
 		These are basically coordinate wrappers to MapBlock
 	*/
-	
+
 	NodeTimer getNodeTimer(v3s16 p);
 	void setNodeTimer(v3s16 p, NodeTimer t);
 	void removeNodeTimer(v3s16 p);
@@ -327,7 +327,7 @@ class Map /*: public NodeContainer*/
 	/*
 		Variables
 	*/
-	
+
 protected:
 
 	std::ostream &m_dout; // A bit deprecated, could be removed
@@ -338,7 +338,7 @@ class Map /*: public NodeContainer*/
 
 	core::map<v2s16, MapSector*> m_sectors;
 
-	// Be sure to set this to NULL when the cached sector is deleted 
+	// Be sure to set this to NULL when the cached sector is deleted
 	MapSector *m_sector_cache;
 	v2s16 m_sector_cache_p;
 
@@ -358,7 +358,7 @@ class ServerMap : public Map
 	/*
 		savedir: directory to which map data should be saved
 	*/
-	ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge);
+	ServerMap(std::string savedir, IGameDef *gamedef);
 	~ServerMap();
 
 	s32 mapType() const
@@ -380,13 +380,13 @@ class ServerMap : public Map
 	void initBlockMake(BlockMakeData *data, v3s16 blockpos);
 	MapBlock* finishBlockMake(BlockMakeData *data,
 			core::map<v3s16, MapBlock*> &changed_blocks);
-	
+
 	// A non-threaded wrapper to the above  - DEFUNCT
 /*	MapBlock * generateBlock(
 			v3s16 p,
 			core::map<v3s16, MapBlock*> &modified_blocks
 	);*/
-	
+
 	/*
 		Get a block from somewhere.
 		- Memory
@@ -399,10 +399,10 @@ class ServerMap : public Map
 		- Memory
 		- Load from disk
 		- Create blank filled with CONTENT_IGNORE
-		
+
 	*/
 	MapBlock * emergeBlock(v3s16 p, bool create_blank=true);
-	
+
 	// Helper for placing objects on ground level
 	s16 findGroundLevel(v2s16 p2d);
 
@@ -438,32 +438,32 @@ class ServerMap : public Map
 
 	void save(ModifiedState save_level);
 	//void loadAll();
-	
+
 	void listAllLoadableBlocks(core::list<v3s16> &dst);
-	
+
 	// Saves map seed and possibly other stuff
 	void saveMapMeta();
 	void loadMapMeta();
-	
+
 	/*void saveChunkMeta();
 	void loadChunkMeta();*/
-	
+
 	// The sector mutex should be locked when calling most of these
-	
+
 	// This only saves sector-specific data such as the heightmap
 	// (no MapBlocks)
 	// DEPRECATED? Sectors have no metadata anymore.
 	void saveSectorMeta(ServerMapSector *sector);
 	MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
 	bool loadSectorMeta(v2s16 p2d);
-	
+
 	// Full load of a sector including all blocks.
 	// returns true on success, false on failure.
 	bool loadSectorFull(v2s16 p2d);
 	// If sector is not found in memory, try to load it from disk.
 	// Returns true if sector now resides in memory
 	//bool deFlushSector(v2s16 p2d);
-	
+
 	void saveBlock(MapBlock *block);
 	// This will generate a sector with getSector if not found.
 	void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
@@ -478,11 +478,21 @@ class ServerMap : public Map
 
 	u64 getSeed(){ return m_seed; }
 
-	EmergeManager *m_emerge;
+	MapgenParams *getMapgenParams(){ return m_mgparams; }
+
+	void setEmerge(EmergeManager *emerge){ m_emerge = emerge; }
+
+	// Parameters fed to the Mapgen
+	MapgenParams *m_mgparams;
 private:
 	// Seed used for all kinds of randomness in generation
 	u64 m_seed;
-	
+
+
+
+	// Emerge manager
+	EmergeManager *m_emerge;
+
 	std::string m_savedir;
 	bool m_map_saving_enabled;
 
@@ -499,7 +509,7 @@ class ServerMap : public Map
 		This is reset to false when written on disk.
 	*/
 	bool m_map_metadata_changed;
-	
+
 	/*
 		SQLite database and statements
 	*/
@@ -514,7 +524,7 @@ class MapVoxelManipulator : public VoxelManipulator
 public:
 	MapVoxelManipulator(Map *map);
 	virtual ~MapVoxelManipulator();
-	
+
 	virtual void clear()
 	{
 		VoxelManipulator::clear();
@@ -542,11 +552,11 @@ class ManualMapVoxelManipulator : public MapVoxelManipulator
 
 	void setMap(Map *map)
 	{m_map = map;}
-	
+
 	virtual void emerge(VoxelArea a, s32 caller_id=-1);
 
 	void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
-	
+
 	// This is much faster with big chunks of generated data
 	void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
 
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 7564999cc..233fa9b99 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -34,19 +34,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "main.h" // For g_profiler
 #include "treegen.h"
 
-
-
-/*
-MapgenV7Params mg_def_params_v7 = {
-	0,
-	1,
-	5,
-	MG_TREES | MG_CAVES | MG_DUNGEONS,
-	&nparams_v7_def_terrain,
-	&nparams_v7_def_bgroup,
-	&nparams_v7_def_heat,
-	&nparams_v7_def_humidity
-};*/
+/////////////////// Mapgen V6 perlin noise default values
+NoiseParams nparams_v6_def_terrain_base =
+	{-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6};
+NoiseParams nparams_v6_def_terrain_higher =
+	{20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6};
+NoiseParams nparams_v6_def_steepness =
+	{0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7};
+NoiseParams nparams_v6_def_height_select =
+	{0.5, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69};
+NoiseParams nparams_v6_def_trees =
+	{0.0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66};
+NoiseParams nparams_v6_def_mud =
+	{AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55};
+NoiseParams nparams_v6_def_beach =
+	{0.0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50};
+NoiseParams nparams_v6_def_biome =
+	{0.0, 1.0, v3f(250.0, 250.0, 250.0), 9130, 3, 0.50};
+NoiseParams nparams_v6_def_cave =
+	{6.0, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50};
+
+/////////////////// Mapgen V7 perlin noise default values
+NoiseParams nparams_v7_def_terrain =
+	{10.0, 12.0, v3f(350., 350., 350.), 82341, 5, 0.6}; //terrain
+NoiseParams nparams_v7_def_bgroup =
+	{0.5, 1/(2*1.6), v3f(350., 350., 350.), 5923, 2, 0.60}; //0 to 1
+NoiseParams nparams_v7_def_heat =
+	{25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75
+NoiseParams nparams_v7_def_humidity =
+	{50, 100/(2*1.6), v3f(750., 750., 750.), 12094, 2, 0.60}; //0 to 100
 
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -56,25 +72,18 @@ MapgenV7::MapgenV7(BiomeDefManager *biomedef, int mapgenid, MapgenV7Params *para
 	this->generating  = false;
 	this->id       = mapgenid;
 	this->biomedef = biomedef;
+	this->ndef     = biomedef->ndef;
 
-	this->seed        = params->seed;
-	this->csize       = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; /////////////////get this from config!
+	this->seed        = (int)params->seed;
+	this->csize       = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
 	this->water_level = params->water_level;
 
-	//g_settings->getS16("default_water_level");
-
-	/*
-	this->np_terrain  = np_terrain;
-	this->np_bgroup   = np_bgroup;
-	this->np_heat     = np_heat;
-	this->np_humidity = np_humidity;
-	*/
 	noise_terrain  = new Noise(params->np_terrain,  seed, csize.X, csize.Y);
 	noise_bgroup   = new Noise(params->np_bgroup,   seed, csize.X, csize.Y);
 	noise_heat     = new Noise(params->np_heat,     seed, csize.X, csize.Y);
 	noise_humidity = new Noise(params->np_humidity, seed, csize.X, csize.Y);
 
-	this->ndef = biomedef->ndef;
+
 	n_air   = MapNode(ndef->getId("mapgen_air"));
 	n_water = MapNode(ndef->getId("mapgen_water_source"));
 	n_lava  = MapNode(ndef->getId("mapgen_lava_source"));
@@ -200,12 +209,33 @@ void MapgenV7::updateLighting(v3s16 nmin, v3s16 nmax) {
 }
 
 
-EmergeManager::EmergeManager(IGameDef *gamedef, int mg_version) {
-	this->mg_version = mg_version;
-	this->biomedef   = new BiomeDefManager(gamedef);
+Biome *MapgenV7::getBiomeAtPoint(v3s16 p) {
+	float bgroup   = NoisePerlin2D(noise_bgroup->np,   p.X, p.Y, seed);
+	float heat     = NoisePerlin2D(noise_heat->np,     p.X, p.Y, seed);
+	float humidity = NoisePerlin2D(noise_humidity->np, p.X, p.Y, seed);
+	return biomedef->getBiome(bgroup, heat, humidity);
+}
+
+
+//FIXME:  This assumes y == 0, that is, always in a non-hell/non-sky biome
+int MapgenV7::getGroundLevelAtPoint(v2s16 p) {
+	float terrain = NoisePerlin2D(noise_terrain->np, p.X, p.Y, seed);
+	Biome *biome = getBiomeAtPoint(v3s16(p.X, p.Y, 0));
+	return biome->getSurfaceHeight(terrain);
+}
+
+
+/////////////////////////////// Emerge Manager ////////////////////////////////
+
 
-	this->params     = NULL;
-	setMapgenParams();
+
+EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef,
+							 MapgenParams *mgparams) {
+	//the order of these assignments is pretty important
+	this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef);
+	this->params   = mgparams;
+	this->mapgen   = NULL;
+	this->mapgen   = getMapgen();
 }
 
 
@@ -217,59 +247,33 @@ EmergeManager::~EmergeManager() {
 
 Mapgen *EmergeManager::getMapgen() {
 	if (!mapgen) {
-		switch (mg_version) {
+		switch (params->mg_version) {
 			case 6:
-				mapgen = new MapgenV6(0, params);
+				mapgen = new MapgenV6(0, (MapgenV6Params *)params);
 				break;
 			case 7:
-				mapgen = new MapgenV7(biomedef, 0, params);
+				mapgen = new MapgenV7(biomedef, 0, (MapgenV7Params *)params);
 				break;
 			default:
 				errorstream << "EmergeManager: Unsupported mapgen version "
-					<< mg_version << ", falling back to V6" << std::endl;
-				mg_version = 6;
-				mapgen = new MapgenV6(0, mgv6params);
+					<< params->mg_version << ", falling back to V6" << std::endl;
+				params->mg_version = 6;
+				mapgen = new MapgenV6(0, (MapgenV6Params *)params);
 		}
 	}
 	return mapgen;
 }
 
 
-void EmergeManager::setMapgenParams() {
-	if (params)
-		delete params;
-
-	switch (mg_version) {
-		case 6:
-			params = new MapgenV6Params();
-			break;
-		case 7:
-			params = new MapgenV7Params();
-			break;
-		default: //////do something here!
-			;
-	}
-}
-
-
 void EmergeManager::addBlockToQueue() {
-
+	//STUB
 }
 
 
-Biome *EmergeManager::getBiomeAtPoint(v3s16 p) {
-	float bgroup   = NoisePerlin2D(np_bgroup,   p.X, p.Y, seed);
-	float heat     = NoisePerlin2D(np_heat,     p.X, p.Y, seed);
-	float humidity = NoisePerlin2D(np_humidity, p.X, p.Y, seed);
-	return biomedef->getBiome(bgroup, heat, humidity);
-}
-
-
-//FIXME:  This assumes y == 0, that is, always in a non-hell/non-sky biome
 int EmergeManager::getGroundLevelAtPoint(v2s16 p) {
-	float terrain = NoisePerlin2D(np_terrain, p.X, p.Y, seed);
-	Biome *biome = getBiomeAtPoint(v3s16(p.X, p.Y, 0));
-	return biome->getSurfaceHeight(terrain);
+	if (!mapgen)
+		return 0;
+	return mapgen->getGroundLevelAtPoint(p);
 }
 
 
@@ -283,18 +287,93 @@ bool EmergeManager::isBlockUnderground(v3s16 blockpos) {
 
 	//yuck, but then again, should i bother being accurate?
 	//the height of the nodes in a single block is quite variable
-	return blockpos.Y * (MAP_BLOCKSIZE + 1) <= water_level;
+	return blockpos.Y * (MAP_BLOCKSIZE + 1) <= params->water_level;
 }
 
 
 u32 EmergeManager::getBlockSeed(v3s16 p) {
-	return (u32)(seed & 0xFFFFFFFF) +
+	return (u32)(params->seed & 0xFFFFFFFF) +
 		p.Z * 38134234 +
 		p.Y * 42123 +
 		p.Y * 23;
 }
 
 
+MapgenParams *MapgenParams::createMapgenParams(int mgver) {
+	switch (mgver) {
+		case 6:
+			return new MapgenV6Params();
+		case 7:
+			return new MapgenV7Params();
+		default: //instead of complaining, default to 6
+			return new MapgenV6Params();
+	}
+}
+
+
+MapgenParams *MapgenParams::getParamsFromSettings(Settings *settings) {
+	int mg_version = settings->getS16("mg_version");
+	MapgenParams *mgparams = MapgenParams::createMapgenParams(mg_version);
+	mgparams->mg_version  = mg_version;
+	mgparams->seed        = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed");
+	mgparams->water_level = settings->getS16("water_level");
+	mgparams->chunksize   = settings->getS16("chunksize");
+	mgparams->flags       = settings->getS32("mg_flags");
+
+	switch (mg_version) {
+		case 6:
+		{
+			MapgenV6Params *v6params = (MapgenV6Params *)mgparams;
+
+			v6params->freq_desert = settings->getFloat("mgv6_freq_desert");
+			v6params->freq_beach  = settings->getFloat("mgv6_freq_beach");
+			v6params->np_terrain_base   = settings->getNoiseParams("mgv6_np_terrain_base");
+			v6params->np_terrain_higher = settings->getNoiseParams("mgv6_np_terrain_higher");
+			v6params->np_steepness      = settings->getNoiseParams("mgv6_np_steepness");
+			v6params->np_height_select  = settings->getNoiseParams("mgv6_np_height_select");
+			v6params->np_trees          = settings->getNoiseParams("mgv6_np_trees");
+			v6params->np_mud            = settings->getNoiseParams("mgv6_np_mud");
+			v6params->np_beach          = settings->getNoiseParams("mgv6_np_beach");
+			v6params->np_biome          = settings->getNoiseParams("mgv6_np_biome");
+			v6params->np_cave           = settings->getNoiseParams("mgv6_np_cave");
+
+			if (!v6params->np_terrain_base || !v6params->np_terrain_higher ||
+				!v6params->np_steepness    || !v6params->np_height_select  ||
+				!v6params->np_trees        || !v6params->np_mud            ||
+				!v6params->np_beach || !v6params->np_biome || !v6params->np_cave) {
+				delete mgparams;
+				return NULL;
+			}
+
+			break;
+		}
+		case 7:
+		{
+			MapgenV7Params *v7params = (MapgenV7Params *)mgparams;
+
+			v7params->np_terrain  = settings->getNoiseParams("mgv7_np_terrain");
+			v7params->np_bgroup   = settings->getNoiseParams("mgv7_np_bgroup");
+			v7params->np_heat     = settings->getNoiseParams("mgv7_np_heat");
+			v7params->np_humidity = settings->getNoiseParams("mgv7_np_humidity");
+			
+			if (!v7params->np_terrain || !v7params->np_bgroup ||
+				!v7params->np_heat    || !v7params->np_humidity) {
+				delete mgparams;
+				return NULL;
+			}
+			
+			break;
+		}
+		default:
+			delete mgparams;
+			return NULL;
+	}
+
+	return mgparams;
+
+}
+
+
 /////////////////////////////////// legacy static functions for farmesh
 
 
diff --git a/src/mapgen.h b/src/mapgen.h
index 81de0d176..ba1ea86c3 100644
--- a/src/mapgen.h
+++ b/src/mapgen.h
@@ -25,6 +25,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gamedef.h"
 #include "mapnode.h"
 #include "noise.h"
+#include "settings.h"
+
+/////////////////// Mapgen flags
+#define MG_TREES         0x01
+#define MG_CAVES         0x02
+#define MG_DUNGEONS      0x04
+#define MGV6_FORESTS     0x08
+#define MGV6_BIOME_BLEND 0x10
+
+#define AVERAGE_MUD_AMOUNT 4
 
 class BiomeDefManager;
 class Biome;
@@ -35,6 +45,20 @@ class ManualMapVoxelManipulator;
 class VoxelManipulator;
 class INodeDefManager;
 
+extern NoiseParams nparams_v6_def_terrain_base;
+extern NoiseParams nparams_v6_def_terrain_higher;
+extern NoiseParams nparams_v6_def_steepness;
+extern NoiseParams nparams_v6_def_height_select;
+extern NoiseParams nparams_v6_def_trees;
+extern NoiseParams nparams_v6_def_mud;
+extern NoiseParams nparams_v6_def_beach;
+extern NoiseParams nparams_v6_def_biome;
+extern NoiseParams nparams_v6_def_cave;
+
+extern NoiseParams nparams_v7_def_terrain;
+extern NoiseParams nparams_v7_def_bgroup;
+extern NoiseParams nparams_v7_def_heat;
+extern NoiseParams nparams_v7_def_humidity;
 
 enum BiomeType
 {
@@ -58,58 +82,24 @@ struct BlockMakeData {
 };
 
 
-/////////////////// Mapgen flags
-#define MG_TREES         0x01
-#define MG_CAVES         0x02
-#define MG_DUNGEONS      0x04
-#define MGV6_FORESTS     0x08
-#define MGV6_BIOME_BLEND 0x10
-
-#define AVERAGE_MUD_AMOUNT 4
-
-/////////////////// Mapgen V6 perlin noise default values
-NoiseParams nparams_v6_def_terrain_base =
-	{-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6};
-NoiseParams nparams_v6_def_terrain_higher =
-	{20.0, 16.0, v3f(500.0, 500.0, 500.0), 85309, 5, 0.6};
-NoiseParams nparams_v6_def_steepness =
-	{0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7};
-NoiseParams nparams_v6_def_height_select =
-	{0.5, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69};
-NoiseParams nparams_v6_def_trees =
-	{0.0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66};
-NoiseParams nparams_v6_def_mud =
-	{AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55};
-NoiseParams nparams_v6_def_beach =
-	{0.0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50};
-NoiseParams nparams_v6_def_biome =
-	{0.0, 1.0, v3f(250.0, 250.0, 250.0), 9130, 3, 0.50};
-NoiseParams nparams_v6_def_cave =
-	{6.0, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50};
-
-/////////////////// Mapgen V7 perlin noise default values
-NoiseParams nparams_v7_def_terrain =
-	{10.0, 12.0, v3f(350., 350., 350.), 82341, 5, 0.6}; //terrain
-NoiseParams nparams_v7_def_bgroup =
-	{0.5, 1/(2*1.6), v3f(350., 350., 350.), 5923, 2, 0.60}; //0 to 1
-NoiseParams nparams_v7_def_heat =
-	{25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75
-NoiseParams nparams_v7_def_humidity =
-	{50, 100/(2*1.6), v3f(750., 750., 750.), 12094, 2, 0.60}; //0 to 100
-
 struct MapgenParams {
-	int seed;
-	int water_level;
+	int mg_version;
 	int chunksize;
+	u64 seed;
+	int water_level;
 	u32 flags;
 
 	MapgenParams() {
+		mg_version  = 6;
 		seed        = 0;
 		water_level = 1;
 		chunksize   = 5;
 		flags       = MG_TREES | MG_CAVES | MGV6_BIOME_BLEND;
 	}
 
+	static MapgenParams *createMapgenParams(int mgver);
+	static MapgenParams *getParamsFromSettings(Settings *settings);
+
 };
 
 struct MapgenV6Params : public MapgenParams {
@@ -163,6 +153,7 @@ class Mapgen {
 	int id;
 
 	virtual void makeChunk(BlockMakeData *data) {};
+	virtual int getGroundLevelAtPoint(v2s16 p) = 0;
 
 	//Legacy functions for Farmesh (pending removal)
 	static bool get_have_beach(u64 seed, v2s16 p2d);
@@ -189,7 +180,6 @@ class MapgenV6 : public Mapgen {
 	Noise *noise_mud;
 	Noise *noise_beach;
 	Noise *noise_biome;
-	Noise *noise_cave;
 
 	float *map_terrain_base;
 	float *map_terrain_higher;
@@ -199,7 +189,8 @@ class MapgenV6 : public Mapgen {
 	float *map_mud;
 	float *map_beach;
 	float *map_biome;
-	float *map_cave;
+
+	NoiseParams *np_cave;
 
 	u32 flags;
 	float freq_desert;
@@ -209,6 +200,7 @@ class MapgenV6 : public Mapgen {
 	~MapgenV6();
 
 	void makeChunk(BlockMakeData *data);
+	int getGroundLevelAtPoint(v2s16 p);
 
 
 	static s16 find_ground_level(VoxelManipulator &vmanip, v2s16 p2d, INodeDefManager *ndef);
@@ -254,12 +246,6 @@ class MapgenV7 : public Mapgen {
 	int id;
 	u32 flags;
 
-/*
-	NoiseParams *np_terrain;
-	NoiseParams *np_bgroup;
-	NoiseParams *np_heat;
-	NoiseParams *np_humidity;*/
-
 	//should these be broken off into a "commonly used nodes" class?
 	MapNode n_air;
 	MapNode n_water;
@@ -269,6 +255,9 @@ class MapgenV7 : public Mapgen {
 	~MapgenV7();
 
 	void makeChunk(BlockMakeData *data);
+	int getGroundLevelAtPoint(v2s16 p);
+
+	Biome *getBiomeAtPoint(v3s16 p);
 	void updateLiquid(v3s16 node_min, v3s16 node_max);
 	void updateLighting(v3s16 node_min, v3s16 node_max);
 
@@ -281,7 +270,6 @@ class MapgenV7 : public Mapgen {
 class EmergeManager {
 public:
 	//settings
-	int mg_version;
 	MapgenParams *params;
 
 	//mapgen objects here
@@ -290,11 +278,10 @@ class EmergeManager {
 	//biome manager
 	BiomeDefManager *biomedef;
 
-	EmergeManager(IGameDef *gamedef, int mg_version=6);
+	EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef, MapgenParams *mgparams);
 	~EmergeManager();
 
 	Mapgen *getMapgen();
-	void setMapgenParams();
 	void addBlockToQueue();
 
 	//mapgen helper methods
@@ -304,43 +291,5 @@ class EmergeManager {
 	u32 getBlockSeed(v3s16 p);
 };
 
-
-/*
-namespace mapgen
-{
-	// Finds precise ground level at any position
-	s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
-
-	// Find out if block is completely underground
-	bool block_is_underground(u64 seed, v3s16 blockpos);
-
-	// Get a pseudorandom seed for a position on the map
-	u32 get_blockseed(u64 seed, v3s16 p);
-
-	// Main map generation routine
-	void make_block(BlockMakeData *data);
-
-
-	//These are used by FarMesh
-	bool get_have_beach(u64 seed, v2s16 p2d);
-	double tree_amount_2d(u64 seed, v2s16 p);
-
-	struct BlockMakeData
-	{
-		bool no_op;
-		ManualMapVoxelManipulator *vmanip; // Destructor deletes
-		u64 seed;
-		v3s16 blockpos_min;
-		v3s16 blockpos_max;
-		v3s16 blockpos_requested;
-		UniqueQueue<v3s16> transforming_liquid;
-		INodeDefManager *nodedef;
-
-		BlockMakeData();
-		~BlockMakeData();
-	};
-
-}; // namespace mapgen
-*/
 #endif
 
diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp
index f31a754d6..fc6ef89e8 100644
--- a/src/mapgen_v6.cpp
+++ b/src/mapgen_v6.cpp
@@ -32,47 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h" // For g_settings
 #include "main.h" // For g_profiler
 
-/*
-#define AVERAGE_MUD_AMOUNT 4
-
-NoiseParams nparams_v6_def_terrain_base =
-	{-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6};
-NoiseParams nparams_v6_def_terrain_higher =
-	{20.0, 16.0, v3f(500.0, 500.0, 500.0), 85309, 5, 0.6};
-NoiseParams nparams_v6_def_steepness =
-	{0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7};
-NoiseParams nparams_v6_def_height_select =
-	{0.5, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69};
-NoiseParams nparams_v6_def_trees =
-	{0.0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66};
-NoiseParams nparams_v6_def_mud =
-	{AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55};
-NoiseParams nparams_v6_def_beach =
-	{0.0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50};
-NoiseParams nparams_v6_def_biome =
-	{0.0, 1.0, v3f(250.0, 250.0, 250.0), 9130, 3, 0.50};
-NoiseParams nparams_v6_def_cave =
-	{6.0, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50};
-
-
-MapgenV6Params mg_def_params_v6 = {
-	0,
-	1,
-	5,
-	MG_TREES | MG_CAVES | MGV6_BIOME_BLEND,
-	0.45,
-	0.15,
-	&nparams_v6_def_terrain_base,
-	&nparams_v6_def_terrain_higher,
-	&nparams_v6_def_steepness,
-	&nparams_v6_def_height_select,
-	&nparams_v6_def_trees,
-	&nparams_v6_def_mud,
-	&nparams_v6_def_beach,
-	&nparams_v6_def_biome,
-	&nparams_v6_def_cave
-};
-*/
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -81,9 +40,9 @@ MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params) {
 	this->generating  = false;
 	this->id       = mapgenid;
 
-	this->seed     = params->seed;
+	this->seed     = (int)params->seed;
 	this->water_level = params->water_level;
-	this->flags   = flags;
+	this->flags   = params->flags;
 	this->csize   = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
 
 	this->freq_desert = params->freq_desert;
@@ -91,6 +50,8 @@ MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params) {
 
 	this->ystride = csize.X; //////fix this
 
+	np_cave = params->np_cave;
+
 	noise_terrain_base   = new Noise(params->np_terrain_base,   seed, csize.X, csize.Y);
 	noise_terrain_higher = new Noise(params->np_terrain_higher, seed, csize.X, csize.Y);
 	noise_steepness      = new Noise(params->np_steepness,      seed, csize.X, csize.Y);
@@ -120,7 +81,6 @@ MapgenV6::~MapgenV6() {
 	delete noise_mud;
 	delete noise_beach;
 	delete noise_biome;
-	delete noise_cave;
 }
 
 
@@ -401,6 +361,12 @@ u32 MapgenV6::get_blockseed(u64 seed, v3s16 p)
 	return (u32)(seed%0x100000000ULL) + z*38134234 + y*42123 + x*23;
 }
 
+
+int MapgenV6::getGroundLevelAtPoint(v2s16 p) {
+	return base_rock_level_2d(seed, p) + AVERAGE_MUD_AMOUNT;
+}
+
+
 #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
 
 void MapgenV6::makeChunk(BlockMakeData *data)
@@ -636,10 +602,7 @@ void MapgenV6::makeChunk(BlockMakeData *data)
 			0.5+(double)node_min.X/250, 0.5+(double)node_min.Y/250,
 			data->seed+34329, 3, 0.50);*/
 
-	double cave_amount = np_cave->offset + np_cave->scale * noise2d_perlin(
-			0.5 + (double)node_min.X / np_cave->spread.X,
-			0.5 + (double)node_min.Y / np_cave->spread.Y,
-			data->seed + np_cave->seed, np_cave->octaves, np_cave->persist);
+	double cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, data->seed);
 
 	const u32 age_loops = 2;
 	for(u32 i_age=0; i_age<age_loops; i_age++)
@@ -669,11 +632,15 @@ void MapgenV6::makeChunk(BlockMakeData *data)
 	}
 	for(u32 jj=0; jj<caves_count+bruises_count; jj++)
 	{
-		int avg_height = (int)
+		if (!(flags & MG_CAVES))
+			continue;
+
+		/*int avg_height = (int)
 			  ((base_rock_level_2d(data->seed, v2s16(node_min.X, node_min.Z)) +
 				base_rock_level_2d(data->seed, v2s16(node_max.X, node_max.Z))) / 2);
 		if ((node_max.Y + node_min.Y) / 2 > avg_height)
-			break;
+			break;*/
+
 		bool large_cave = (jj >= caves_count);
 		s16 min_tunnel_diameter = 2;
 		s16 max_tunnel_diameter = ps.range(2,6);
@@ -1316,7 +1283,7 @@ void MapgenV6::makeChunk(BlockMakeData *data)
 		Generate some trees
 	*/
 	assert(central_area_size.X == central_area_size.Z);
-	{
+	if (flags & MG_TREES) {
 		// Divide area into parts
 		s16 div = 8;
 		s16 sidelen = central_area_size.X / div;
diff --git a/src/noise.cpp b/src/noise.cpp
index 17b5df018..de9d48808 100644
--- a/src/noise.cpp
+++ b/src/noise.cpp
@@ -317,7 +317,7 @@ void Noise::setSize(int sx, int sy, int sz) {
 	delete[] buf;
 	delete[] result;
 	this->buf    = new float[sx * sy * sz];
-	this->result = new float[sx * sy * sz];	
+	this->result = new float[sx * sy * sz];
 }
 
 
diff --git a/src/noise.h b/src/noise.h
index 15df5c25b..9fb6d48a1 100644
--- a/src/noise.h
+++ b/src/noise.h
@@ -70,6 +70,10 @@ struct NoiseParams {
 };
 
 
+// Convenience macros for getting/setting NoiseParams in Settings
+#define getNoiseParams(x) getStruct<NoiseParams>((x), "f,f,v3,s32,s32,f")
+#define setNoiseParams(x, y) setStruct((x), "f,f,v3,s32,s32,f", (y))
+
 class Noise {
 public:
 	NoiseParams *np;
@@ -129,8 +133,12 @@ inline float easeCurve(float t) {
 }
 
 #define NoisePerlin2D(np, x, y, s) ((np)->offset + (np)->scale * \
-		noise2d_perlin((float)(x) * (np)->spread.X, (float)(y) * (np)->spread.Y, \
+		noise2d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
 		(s) + (np)->seed, (np)->octaves, (np)->persist))
 
+#define NoisePerlin3D(np, x, y, z, s) ((np)->offset + (np)->scale * \
+		noise2d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
+		(float)(z) / (np)->spread.Z, (s) + (np)->seed, (np)->octaves, (np)->persist))
+
 #endif
 
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 8238ced26..ec3d34676 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -4463,7 +4463,7 @@ static int l_register_biome_groups(lua_State *L)
 	if (!lua_istable(L, index))
 		throw LuaError(L, "register_biome_groups: parameter is not a table");
 
-	BiomeDefManager *bmgr = get_server(L)->getEmergeManager()->biomedef;
+	BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
 	if (!bmgr) {
 		verbosestream << "register_biome_groups: BiomeDefManager not active" << std::endl;
 		return 0;
@@ -4487,7 +4487,7 @@ static int l_register_biome(lua_State *L)
 	std::string nodename;
 
 	IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager();
-	BiomeDefManager *bmgr = get_server(L)->getEmergeManager()->biomedef;
+	BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
 	if (!bmgr) {
 		verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
 		return 0;
diff --git a/src/server.cpp b/src/server.cpp
index 03faace07..70f71e3fb 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -945,6 +945,7 @@ Server::Server(
 	m_rollback_sink_enabled(true),
 	m_enable_rollback_recording(false),
 	m_emerge(NULL),
+	m_biomedef(NULL),
 	m_lua(NULL),
 	m_itemdef(createItemDefManager()),
 	m_nodedef(createNodeDefManager()),
@@ -984,8 +985,8 @@ Server::Server(
 	infostream<<"- config: "<<m_path_config<<std::endl;
 	infostream<<"- game:   "<<m_gamespec.path<<std::endl;
 
-	// Create emerge manager
-	m_emerge = new EmergeManager(this, g_settings->getS16("use_mapgen_version"));
+	// Create biome definition manager
+	m_biomedef = new BiomeDefManager(this);
 
 	// Create rollback manager
 	std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
@@ -1094,19 +1095,23 @@ Server::Server(
 	m_nodedef->updateAliases(m_itemdef);
 
 	// Add default biomes after nodedef had its aliases added
-	if (m_emerge->biomedef)
-		m_emerge->biomedef->addDefaultBiomes();
+	m_biomedef->addDefaultBiomes();
 
 	// Initialize Environment
+	ServerMap *servermap = new ServerMap(path_world, this);
+	m_env = new ServerEnvironment(servermap, m_lua, this, this);
+
+	// Create emerge manager
+	m_emerge = new EmergeManager(this, m_biomedef, servermap->getMapgenParams());
 
-	m_env = new ServerEnvironment(new ServerMap(path_world, this, m_emerge), m_lua,
-			this, this);
+	// Give map pointer to the emerge manager
+	servermap->setEmerge(m_emerge);
 
 	// Give environment reference to scripting api
 	scriptapi_add_environment(m_lua, m_env);
 
 	// Register us to receive map edit events
-	m_env->getMap().addEventReceiver(this);
+	servermap->addEventReceiver(this);
 
 	// If file exists, load environment metadata
 	if(fs::PathExists(m_path_world+DIR_DELIM+"env_meta.txt"))
@@ -4849,7 +4854,7 @@ v3f findSpawnPos(ServerMap &map)
 #endif
 
 #if 1
-	s16 water_level = map.m_emerge->water_level; //g_settings->getS16("default_water_level");
+	s16 water_level = map.m_mgparams->water_level;
 
 	// Try to find a good place a few times
 	for(s32 i=0; i<1000; i++)
@@ -4874,7 +4879,7 @@ v3f findSpawnPos(ServerMap &map)
 			continue;
 		}
 
-		nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
+		nodepos = v3s16(nodepos2d.X, groundheight+1, nodepos2d.Y);
 		bool is_good = false;
 		s32 air_count = 0;
 		for(s32 i=0; i<10; i++){
diff --git a/src/server.h b/src/server.h
index 34515faf7..86d5513d8 100644
--- a/src/server.h
+++ b/src/server.h
@@ -553,6 +553,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	//TODO:  determine what should be locked when accessing the emerge manager
 	EmergeManager *getEmergeManager(){ return m_emerge; }
 
+	BiomeDefManager *getBiomeDef(){ return m_biomedef; }
+
 	// actions: time-reversed list
 	// Return value: success/failure
 	bool rollbackRevertActions(const std::list<RollbackAction> &actions,
@@ -746,6 +748,9 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	// Emerge manager
 	EmergeManager *m_emerge;
 
+	// Biome Definition Manager
+	BiomeDefManager *m_biomedef;
+
 	// Scripting
 	// Envlock and conlock should be locked when using Lua
 	lua_State *m_lua;
diff --git a/src/settings.h b/src/settings.h
index 57325ebe5..18d6ade72 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -566,23 +566,39 @@ class Settings
 		return value;
 	}
 
-template<typename T> struct alignment_trick { char c; T member; };
-#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
+//template<typename T> struct alignment_trick { char c; T member; };
+//#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
+#ifdef _WIN32
+	#define ALIGNOF(x) __alignof(x)
+#else
+	#define ALIGNOF(x) __alignof__(x)
+#endif
 #define PADDING(x, y) ((ALIGNOF(y) - ((uintptr_t)(x) & (ALIGNOF(y) - 1))) & (ALIGNOF(y) - 1))
-typedef int64_t s64;
+#ifdef _WIN32
+	#define strtok_r(x, y, z) strtok_s(x, y, z)
+	#define strtof(x, y) (float)strtod(x, y)
+	#define strtoll(x, y, z) _strtoi64(x, y, z)
+	#define strtoull(x, y, z) _strtoui64(x, y, z)
+#endif
 
-	void *getStruct(std::string &name, std::string format, size_t len)
+typedef long long int s64; //to be added to src/irrlichttypes.h later
+
+	template <class T> T *getStruct(std::string name, std::string format)
 	{
+		size_t len = sizeof(T);
 		std::vector<std::string *> strs_alloced;
 		std::string *str;
-		char *s = &(get(name))[0];
-		char *buf = new char[len];
-		char *bufpos = buf;
+		std::string valstr = get(name);
+		char *s = &valstr[0];
+		T *buf = new T;
+		char *bufpos = (char *)buf;
 		char *f, *snext;
 		size_t pos;
 
-		char *fmt = &format[0];
-		while ((f = strsep(&fmt, ",")) && s) {
+		char *fmtpos, *fmt = &format[0];
+		while ((f = strtok_r(fmt, ",", &fmtpos)) && s) {
+			fmt = NULL;
+
 			bool is_unsigned = false;
 			int width = 0;
 			char valtype = *f;
@@ -591,14 +607,14 @@ typedef int64_t s64;
 			if (width && valtype == 's')
 				valtype = 'i';
 
-			switch (*f) {
+			switch (valtype) {
 				case 'u':
 					is_unsigned = true;
 					/* FALLTHROUGH */
 				case 'i':
 					if (width == 16) {
 						bufpos += PADDING(bufpos, u16);
-						if ((bufpos - buf) + sizeof(u16) <= len) {
+						if ((bufpos - (char *)buf) + sizeof(u16) <= len) {
 							if (is_unsigned)
 								*(u16 *)bufpos = (u16)strtoul(s, &s, 10);
 							else
@@ -607,7 +623,7 @@ typedef int64_t s64;
 						bufpos += sizeof(u16);
 					} else if (width == 32) {
 						bufpos += PADDING(bufpos, u32);
-						if ((bufpos - buf) + sizeof(u32) <= len) {
+						if ((bufpos - (char *)buf) + sizeof(u32) <= len) {
 							if (is_unsigned)
 								*(u32 *)bufpos = (u32)strtoul(s, &s, 10);
 							else
@@ -616,7 +632,7 @@ typedef int64_t s64;
 						bufpos += sizeof(u32);
 					} else if (width == 64) {
 						bufpos += PADDING(bufpos, u64);
-						if ((bufpos - buf) + sizeof(u64) <= len) {
+						if ((bufpos - (char *)buf) + sizeof(u64) <= len) {
 							if (is_unsigned)
 								*(u64 *)bufpos = (u64)strtoull(s, &s, 10);
 							else
@@ -632,7 +648,7 @@ typedef int64_t s64;
 						*snext++ = 0;
 
 					bufpos += PADDING(bufpos, bool);
-					if ((bufpos - buf) + sizeof(bool) <= len)
+					if ((bufpos - (char *)buf) + sizeof(bool) <= len)
 						*(bool *)bufpos = is_yes(std::string(s));
 					bufpos += sizeof(bool);
 
@@ -640,7 +656,7 @@ typedef int64_t s64;
 					break;
 				case 'f':
 					bufpos += PADDING(bufpos, float);
-					if ((bufpos - buf) + sizeof(float) <= len)
+					if ((bufpos - (char *)buf) + sizeof(float) <= len)
 						*(float *)bufpos = strtof(s, &s);
 					bufpos += sizeof(float);
 
@@ -664,7 +680,7 @@ typedef int64_t s64;
 					while ((pos = str->find("\\\"", pos)) != std::string::npos)
 						str->erase(pos, 1);
 
-					if ((bufpos - buf) + sizeof(std::string *) <= len)
+					if ((bufpos - (char *)buf) + sizeof(std::string *) <= len)
 						*(std::string **)bufpos = str;
 					bufpos += sizeof(std::string *);
 					strs_alloced.push_back(str);
@@ -680,7 +696,7 @@ typedef int64_t s64;
 					if (width == 2) {
 						bufpos += PADDING(bufpos, v2f);
 
-						if ((bufpos - buf) + sizeof(v2f) <= len) {
+						if ((bufpos - (char *)buf) + sizeof(v2f) <= len) {
 						v2f *v = (v2f *)bufpos;
 							v->X = strtof(s, &s);
 							s++;
@@ -690,7 +706,7 @@ typedef int64_t s64;
 						bufpos += sizeof(v2f);
 					} else if (width == 3) {
 						bufpos += PADDING(bufpos, v3f);
-						if ((bufpos - buf) + sizeof(v3f) <= len) {
+						if ((bufpos - (char *)buf) + sizeof(v3f) <= len) {
 							v3f *v = (v3f *)bufpos;
 							v->X = strtof(s, &s);
 							s++;
@@ -710,15 +726,16 @@ typedef int64_t s64;
 			if (s && *s == ',')
 				s++;
 
-			if ((bufpos - buf) > len) //error, buffer too small
+			if ((size_t)(bufpos - (char *)buf) > len) //error, buffer too small
 				goto fail;
 		}
 
 		if (f && *f) { //error, mismatched number of fields and values
 fail:
-			for (int i = 0; i != strs_alloced.size(); i++)
+			for (unsigned int i = 0; i != strs_alloced.size(); i++)
 				delete strs_alloced[i];
-			delete[] buf;
+			delete buf;
+			//delete[] buf;
 			buf = NULL;
 		}
 
@@ -735,13 +752,12 @@ typedef int64_t s64;
 		size_t fpos;
 		char *f;
 
-		int nprinted;
 		char *bufpos = (char *)value;
-		char *fmt = &format[0];
-
-		while ((f = strsep(&fmt, ","))) {
+		char *fmtpos, *fmt = &format[0];
+		while ((f = strtok_r(fmt, ",", &fmtpos))) {
+			fmt = NULL;
 			bool is_unsigned = false;
-			int width = 0;
+			int width = 0, nprinted = 0;
 			char valtype = *f;
 
 			width = (int)strtol(f + 1, &f, 10);
@@ -769,7 +785,7 @@ typedef int64_t s64;
 						bufpos += PADDING(bufpos, u64);
 						nprinted = snprintf(sbuf + pos, sbuflen,
 									is_unsigned ? "%llu, " : "%lli, ",
-												 *((u64 *)bufpos));
+									(unsigned long long)*((u64 *)bufpos));
 						bufpos += sizeof(u64);
 					}
 					break;
-- 
GitLab