diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/biome.cpp | 6 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 26 | ||||
-rw-r--r-- | src/map.cpp | 95 | ||||
-rw-r--r-- | src/map.h | 88 | ||||
-rw-r--r-- | src/mapgen.cpp | 213 | ||||
-rw-r--r-- | src/mapgen.h | 129 | ||||
-rw-r--r-- | src/mapgen_v6.cpp | 69 | ||||
-rw-r--r-- | src/noise.cpp | 2 | ||||
-rw-r--r-- | src/noise.h | 10 | ||||
-rw-r--r-- | src/scriptapi.cpp | 4 | ||||
-rw-r--r-- | src/server.cpp | 23 | ||||
-rw-r--r-- | src/server.h | 5 | ||||
-rw-r--r-- | 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(¶ms); + 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; } @@ -81,7 +81,7 @@ struct MapEditEvent already_known_by_peer(0) { } - + MapEditEvent * clone() { MapEditEvent *event = new MapEditEvent(); @@ -155,7 +155,7 @@ public: { return MAPTYPE_BASE; } - + /* Drop (client) or delete (server) the map. */ @@ -168,7 +168,7 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: */ bool addNodeWithEvent(v3s16 p, MapNode n); bool removeNodeWithEvent(v3s16 p); - + /* Takes the blocks at the edges into account */ @@ -267,9 +267,9 @@ public: // 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 @@ public: */ 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 @@ public: // 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 @@ public: 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 @@ public: /* Variables */ - + protected: std::ostream &m_dout; // A bit deprecated, could be removed @@ -338,7 +338,7 @@ protected: 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 @@ public: /* 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 @@ public: 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 @@ public: - 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 @@ public: 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 @@ public: 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 @@ private: 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 @@ public: 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 @@ public: 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 @@ public: Noise *noise_mud; Noise *noise_beach; Noise *noise_biome; - Noise *noise_cave; float *map_terrain_base; float *map_terrain_higher; @@ -199,7 +189,8 @@ public: float *map_mud; float *map_beach; float *map_biome; - float *map_cave; + + NoiseParams *np_cave; u32 flags; float freq_desert; @@ -209,6 +200,7 @@ public: ~MapgenV6(); void makeChunk(BlockMakeData *data); + int getGroundLevelAtPoint(v2s16 p); static s16 find_ground_level(VoxelManipulator &vmanip, v2s16 p2d, INodeDefManager *ndef); @@ -254,12 +246,6 @@ public: 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 @@ public: ~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 @@ public: class EmergeManager { public: //settings - int mg_version; MapgenParams *params; //mapgen objects here @@ -290,11 +278,10 @@ public: //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 @@ public: 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 @@ public: //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 @@ private: // 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 @@ public: 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 @@ fail: 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 @@ fail: bufpos += PADDING(bufpos, u64); nprinted = snprintf(sbuf + pos, sbuflen, is_unsigned ? "%llu, " : "%lli, ", - *((u64 *)bufpos)); + (unsigned long long)*((u64 *)bufpos)); bufpos += sizeof(u64); } break; |