From cde2a7f6f24f638421238ead4e61b155322fefc8 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 25 Jan 2020 16:56:54 +0100 Subject: [PATCH] Settings: Add get_flags API for mapgen flags (mg_flags, mgv6_spflags, ...) (#9284) Unified flags handling in C++ and Lua Settings API -> Reading only, for now. Writing can be implemented later, if needed. API function to read the currently active flags -> was impossible from Lua Co-authored-by: Wuzzy --- doc/lua_api.txt | 4 ++ src/defaultsettings.cpp | 3 +- src/mapgen/mapgen.cpp | 13 ++++++- src/mapgen/mapgen.h | 7 +++- src/mapgen/mapgen_carpathian.cpp | 8 +++- src/mapgen/mapgen_carpathian.h | 2 +- src/mapgen/mapgen_flat.cpp | 8 +++- src/mapgen/mapgen_flat.h | 2 +- src/mapgen/mapgen_fractal.cpp | 9 ++++- src/mapgen/mapgen_fractal.h | 2 +- src/mapgen/mapgen_v5.cpp | 11 +++++- src/mapgen/mapgen_v5.h | 2 +- src/mapgen/mapgen_v6.cpp | 10 ++++- src/mapgen/mapgen_v6.h | 3 +- src/mapgen/mapgen_v7.cpp | 9 ++++- src/mapgen/mapgen_v7.h | 2 +- src/mapgen/mapgen_valleys.cpp | 13 ++++++- src/mapgen/mapgen_valleys.h | 3 +- src/script/lua_api/l_settings.cpp | 25 ++++++++++++ src/script/lua_api/l_settings.h | 3 ++ src/settings.cpp | 65 ++++++++++++++++++++++++------- src/settings.h | 20 +++++++--- src/unittest/test_settings.cpp | 37 ++++++++++++++++++ 23 files changed, 222 insertions(+), 39 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 551aa50b5..1857ce541 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6069,6 +6069,10 @@ It can be created via `Settings(filename)`. * `default` is the value returned if `key` is not found. * Returns `nil` if `key` is not found and `default` not specified. * `get_np_group(key)`: returns a NoiseParams table +* `get_flags(key)`: + * Returns `{flag = true/false, ...}` according to the set flags. + * Is currently limited to mapgen flags `mg_flags` and mapgen-specific + flags like `mgv5_spflags`. * `set(key, value)` * Setting names can't contain whitespace or any of `="{}#`. * Setting values can't contain the sequence `\n"""`. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 1ab4a333e..754ce3547 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "config.h" #include "constants.h" #include "porting.h" +#include "mapgen/mapgen.h" // Mapgen::setDefaultSettings #include "util/string.h" void set_default_settings(Settings *settings) @@ -426,10 +427,10 @@ void set_default_settings(Settings *settings) settings->setDefault("water_level", "1"); settings->setDefault("mapgen_limit", "31000"); settings->setDefault("chunksize", "5"); - settings->setDefault("mg_flags", "caves,dungeons,light,decorations,biomes"); settings->setDefault("fixed_map_seed", ""); settings->setDefault("max_block_generate_distance", "8"); settings->setDefault("enable_mapgen_debug_info", "false"); + Mapgen::setDefaultSettings(settings); // Server list announcing settings->setDefault("server_announce", "false"); diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 81ccf1f8d..79c429ff6 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -215,6 +215,17 @@ void Mapgen::getMapgenNames(std::vector *mgnames, bool include_hid } } +void Mapgen::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mg_flags", flagdesc_mapgen, + MG_CAVES | MG_DUNGEONS | MG_LIGHT | MG_DECORATIONS | MG_BIOMES); + + for (int i = 0; i < (int)MAPGEN_INVALID; ++i) { + MapgenParams *params = createMapgenParams((MapgenType)i); + params->setDefaultSettings(settings); + delete params; + } +} u32 Mapgen::getBlockSeed(v3s16 p, s32 seed) { @@ -1068,7 +1079,7 @@ void MapgenParams::writeParams(Settings *settings) const settings->setS16("water_level", water_level); settings->setS16("mapgen_limit", mapgen_limit); settings->setS16("chunksize", chunksize); - settings->setFlagStr("mg_flags", flags, flagdesc_mapgen, U32_MAX); + settings->setFlagStr("mg_flags", flags, flagdesc_mapgen); if (bparams) bparams->writeParams(settings); diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index 1473d41a6..dc325c791 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -124,7 +124,9 @@ struct MapgenParams { u64 seed = 0; s16 water_level = 1; s16 mapgen_limit = MAX_MAP_GENERATION_LIMIT; - u32 flags = MG_CAVES | MG_LIGHT | MG_DECORATIONS | MG_BIOMES; + // Flags set in readParams + u32 flags = 0; + u32 spflags = 0; BiomeParams *bparams = nullptr; @@ -133,6 +135,8 @@ struct MapgenParams { virtual void readParams(const Settings *settings); virtual void writeParams(Settings *settings) const; + // Default settings for g_settings such as flags + virtual void setDefaultSettings(Settings *settings) {}; s32 getSpawnRangeMax(); @@ -214,6 +218,7 @@ public: EmergeManager *emerge); static MapgenParams *createMapgenParams(MapgenType mgtype); static void getMapgenNames(std::vector *mgnames, bool include_hidden); + static void setDefaultSettings(Settings *settings); private: // isLiquidHorizontallyFlowable() is a helper function for updateLiquid() diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index 67f542c0d..0dc1d33be 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -187,7 +187,7 @@ void MapgenCarpathianParams::readParams(const Settings *settings) void MapgenCarpathianParams::writeParams(Settings *settings) const { - settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX); + settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian); settings->setFloat("mgcarpathian_base_level", base_level); settings->setFloat("mgcarpathian_river_width", river_width); @@ -227,6 +227,12 @@ void MapgenCarpathianParams::writeParams(Settings *settings) const } +void MapgenCarpathianParams::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgcarpathian_spflags", flagdesc_mapgen_carpathian, + MGCARPATHIAN_CAVERNS); +} + //////////////////////////////////////////////////////////////////////////////// diff --git a/src/mapgen/mapgen_carpathian.h b/src/mapgen/mapgen_carpathian.h index ef49df213..acd379958 100644 --- a/src/mapgen/mapgen_carpathian.h +++ b/src/mapgen/mapgen_carpathian.h @@ -37,7 +37,6 @@ struct MapgenCarpathianParams : public MapgenParams float river_depth = 24.0f; float valley_width = 0.25f; - u32 spflags = MGCARPATHIAN_CAVERNS; float cave_width = 0.09f; s16 large_cave_depth = -33; u16 small_cave_num_min = 0; @@ -74,6 +73,7 @@ struct MapgenCarpathianParams : public MapgenParams void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; class MapgenCarpathian : public MapgenBasic diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index 656e7d72c..879435948 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -126,7 +126,7 @@ void MapgenFlatParams::readParams(const Settings *settings) void MapgenFlatParams::writeParams(Settings *settings) const { - settings->setFlagStr("mgflat_spflags", spflags, flagdesc_mapgen_flat, U32_MAX); + settings->setFlagStr("mgflat_spflags", spflags, flagdesc_mapgen_flat); settings->setS16("mgflat_ground_level", ground_level); settings->setS16("mgflat_large_cave_depth", large_cave_depth); settings->setU16("mgflat_small_cave_num_min", small_cave_num_min); @@ -150,6 +150,12 @@ void MapgenFlatParams::writeParams(Settings *settings) const } +void MapgenFlatParams::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgflat_spflags", flagdesc_mapgen_flat, 0); +} + + ///////////////////////////////////////////////////////////////// diff --git a/src/mapgen/mapgen_flat.h b/src/mapgen/mapgen_flat.h index 2ff87c0db..c314c7605 100644 --- a/src/mapgen/mapgen_flat.h +++ b/src/mapgen/mapgen_flat.h @@ -32,7 +32,6 @@ extern FlagDesc flagdesc_mapgen_flat[]; struct MapgenFlatParams : public MapgenParams { - u32 spflags = 0; s16 ground_level = 8; s16 large_cave_depth = -33; u16 small_cave_num_min = 0; @@ -59,6 +58,7 @@ struct MapgenFlatParams : public MapgenParams void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; class MapgenFlat : public MapgenBasic diff --git a/src/mapgen/mapgen_fractal.cpp b/src/mapgen/mapgen_fractal.cpp index 1ac57cede..cabe0b850 100644 --- a/src/mapgen/mapgen_fractal.cpp +++ b/src/mapgen/mapgen_fractal.cpp @@ -139,7 +139,7 @@ void MapgenFractalParams::readParams(const Settings *settings) void MapgenFractalParams::writeParams(Settings *settings) const { - settings->setFlagStr("mgfractal_spflags", spflags, flagdesc_mapgen_fractal, U32_MAX); + settings->setFlagStr("mgfractal_spflags", spflags, flagdesc_mapgen_fractal); settings->setFloat("mgfractal_cave_width", cave_width); settings->setS16("mgfractal_large_cave_depth", large_cave_depth); settings->setU16("mgfractal_small_cave_num_min", small_cave_num_min); @@ -167,6 +167,13 @@ void MapgenFractalParams::writeParams(Settings *settings) const } +void MapgenFractalParams::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgfractal_spflags", flagdesc_mapgen_fractal, + MGFRACTAL_TERRAIN); +} + + ///////////////////////////////////////////////////////////////// diff --git a/src/mapgen/mapgen_fractal.h b/src/mapgen/mapgen_fractal.h index 0654d0360..971dfd822 100644 --- a/src/mapgen/mapgen_fractal.h +++ b/src/mapgen/mapgen_fractal.h @@ -35,7 +35,6 @@ extern FlagDesc flagdesc_mapgen_fractal[]; struct MapgenFractalParams : public MapgenParams { - u32 spflags = MGFRACTAL_TERRAIN; float cave_width = 0.09f; s16 large_cave_depth = -33; u16 small_cave_num_min = 0; @@ -66,6 +65,7 @@ struct MapgenFractalParams : public MapgenParams void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index c003c27d6..447fe8c50 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -129,7 +129,7 @@ void MapgenV5Params::readParams(const Settings *settings) void MapgenV5Params::writeParams(Settings *settings) const { - settings->setFlagStr("mgv5_spflags", spflags, flagdesc_mapgen_v5, U32_MAX); + settings->setFlagStr("mgv5_spflags", spflags, flagdesc_mapgen_v5); settings->setFloat("mgv5_cave_width", cave_width); settings->setS16("mgv5_large_cave_depth", large_cave_depth); settings->setU16("mgv5_small_cave_num_min", small_cave_num_min); @@ -154,6 +154,15 @@ void MapgenV5Params::writeParams(Settings *settings) const } +void MapgenV5Params::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgv5_spflags", flagdesc_mapgen_v5, MGV5_CAVERNS); +} + + +///////////////////////////////////////////////////////////////// + + int MapgenV5::getSpawnLevelAtPoint(v2s16 p) { diff --git a/src/mapgen/mapgen_v5.h b/src/mapgen/mapgen_v5.h index ecdcdaf41..17bc466f0 100644 --- a/src/mapgen/mapgen_v5.h +++ b/src/mapgen/mapgen_v5.h @@ -31,7 +31,6 @@ extern FlagDesc flagdesc_mapgen_v5[]; struct MapgenV5Params : public MapgenParams { - u32 spflags = MGV5_CAVERNS; float cave_width = 0.09f; s16 large_cave_depth = -256; u16 small_cave_num_min = 0; @@ -59,6 +58,7 @@ struct MapgenV5Params : public MapgenParams void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; class MapgenV5 : public MapgenBasic diff --git a/src/mapgen/mapgen_v6.cpp b/src/mapgen/mapgen_v6.cpp index 4e876fc53..653adc8ec 100644 --- a/src/mapgen/mapgen_v6.cpp +++ b/src/mapgen/mapgen_v6.cpp @@ -190,7 +190,7 @@ void MapgenV6Params::readParams(const Settings *settings) void MapgenV6Params::writeParams(Settings *settings) const { - settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6, U32_MAX); + settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6); settings->setFloat("mgv6_freq_desert", freq_desert); settings->setFloat("mgv6_freq_beach", freq_beach); settings->setS16("mgv6_dungeon_ymin", dungeon_ymin); @@ -210,8 +210,16 @@ void MapgenV6Params::writeParams(Settings *settings) const } +void MapgenV6Params::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgv6_spflags", flagdesc_mapgen_v6, MGV6_JUNGLES | + MGV6_SNOWBIOMES | MGV6_TREES | MGV6_BIOMEBLEND | MGV6_MUDFLOW); +} + + //////////////////////// Some helper functions for the map generator + // Returns Y one under area minimum if not found s16 MapgenV6::find_stone_level(v2s16 p2d) { diff --git a/src/mapgen/mapgen_v6.h b/src/mapgen/mapgen_v6.h index 7d5229559..d8cdcb26f 100644 --- a/src/mapgen/mapgen_v6.h +++ b/src/mapgen/mapgen_v6.h @@ -55,8 +55,6 @@ enum BiomeV6Type struct MapgenV6Params : public MapgenParams { - u32 spflags = MGV6_JUNGLES | MGV6_SNOWBIOMES | MGV6_TREES | - MGV6_BIOMEBLEND | MGV6_MUDFLOW; float freq_desert = 0.45f; float freq_beach = 0.15f; s16 dungeon_ymin = -31000; @@ -79,6 +77,7 @@ struct MapgenV6Params : public MapgenParams { void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index 23cbd4e0a..325c4957a 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -183,7 +183,7 @@ void MapgenV7Params::readParams(const Settings *settings) void MapgenV7Params::writeParams(Settings *settings) const { - settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7, U32_MAX); + settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7); settings->setS16("mgv7_mount_zero_level", mount_zero_level); settings->setFloat("mgv7_cave_width", cave_width); settings->setS16("mgv7_large_cave_depth", large_cave_depth); @@ -214,6 +214,13 @@ void MapgenV7Params::writeParams(Settings *settings) const } +void MapgenV7Params::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgv7_spflags", flagdesc_mapgen_v7, + MGV7_MOUNTAINS | MGV7_RIDGES | MGV7_CAVERNS); +} + + //////////////////////////////////////////////////////////////////////////////// diff --git a/src/mapgen/mapgen_v7.h b/src/mapgen/mapgen_v7.h index 6ca39f164..0605c5c97 100644 --- a/src/mapgen/mapgen_v7.h +++ b/src/mapgen/mapgen_v7.h @@ -35,7 +35,6 @@ extern FlagDesc flagdesc_mapgen_v7[]; struct MapgenV7Params : public MapgenParams { - u32 spflags = MGV7_MOUNTAINS | MGV7_RIDGES | MGV7_CAVERNS; s16 mount_zero_level = 0; float cave_width = 0.09f; @@ -70,6 +69,7 @@ struct MapgenV7Params : public MapgenParams { void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; diff --git a/src/mapgen/mapgen_valleys.cpp b/src/mapgen/mapgen_valleys.cpp index 3c6045105..2b8703fa5 100644 --- a/src/mapgen/mapgen_valleys.cpp +++ b/src/mapgen/mapgen_valleys.cpp @@ -162,7 +162,7 @@ void MapgenValleysParams::readParams(const Settings *settings) void MapgenValleysParams::writeParams(Settings *settings) const { - settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX); + settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys); settings->setU16("mgvalleys_altitude_chill", altitude_chill); settings->setS16("mgvalleys_large_cave_depth", large_cave_depth); settings->setU16("mgvalleys_small_cave_num_min", small_cave_num_min); @@ -194,6 +194,17 @@ void MapgenValleysParams::writeParams(Settings *settings) const } +void MapgenValleysParams::setDefaultSettings(Settings *settings) +{ + settings->setDefault("mgvalleys_spflags", flagdesc_mapgen_valleys, + MGVALLEYS_ALT_CHILL | MGVALLEYS_HUMID_RIVERS | + MGVALLEYS_VARY_RIVER_DEPTH | MGVALLEYS_ALT_DRY); +} + + +///////////////////////////////////////////////////////////////// + + void MapgenValleys::makeChunk(BlockMakeData *data) { // Pre-conditions diff --git a/src/mapgen/mapgen_valleys.h b/src/mapgen/mapgen_valleys.h index be97f0763..1aec68842 100644 --- a/src/mapgen/mapgen_valleys.h +++ b/src/mapgen/mapgen_valleys.h @@ -41,8 +41,6 @@ extern FlagDesc flagdesc_mapgen_valleys[]; struct MapgenValleysParams : public MapgenParams { - u32 spflags = MGVALLEYS_ALT_CHILL | MGVALLEYS_HUMID_RIVERS | - MGVALLEYS_VARY_RIVER_DEPTH | MGVALLEYS_ALT_DRY; u16 altitude_chill = 90; u16 river_depth = 4; u16 river_size = 5; @@ -78,6 +76,7 @@ struct MapgenValleysParams : public MapgenParams { void readParams(const Settings *settings); void writeParams(Settings *settings) const; + void setDefaultSettings(Settings *settings); }; diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp index cc2c73789..33eb02392 100644 --- a/src/script/lua_api/l_settings.cpp +++ b/src/script/lua_api/l_settings.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_settings.h" #include "lua_api/l_internal.h" #include "cpp_api/s_security.h" +#include "util/string.h" // FlagDesc #include "settings.h" #include "noise.h" #include "log.h" @@ -128,6 +129,29 @@ int LuaSettings::l_get_np_group(lua_State *L) return 1; } +int LuaSettings::l_get_flags(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings *o = checkobject(L, 1); + std::string key = std::string(luaL_checkstring(L, 2)); + + u32 flags = 0; + auto flagdesc = o->m_settings->getFlagDescFallback(key); + if (o->m_settings->getFlagStrNoEx(key, flags, flagdesc)) { + lua_newtable(L); + int table = lua_gettop(L); + for (size_t i = 0; flagdesc[i].name; ++i) { + lua_pushboolean(L, flags & flagdesc[i].flag); + lua_setfield(L, table, flagdesc[i].name); + } + lua_pushvalue(L, table); + } else { + lua_pushnil(L); + } + + return 1; +} + // set(self, key, value) int LuaSettings::l_set(lua_State* L) { @@ -305,6 +329,7 @@ const luaL_Reg LuaSettings::methods[] = { luamethod(LuaSettings, get), luamethod(LuaSettings, get_bool), luamethod(LuaSettings, get_np_group), + luamethod(LuaSettings, get_flags), luamethod(LuaSettings, set), luamethod(LuaSettings, set_bool), luamethod(LuaSettings, set_np_group), diff --git a/src/script/lua_api/l_settings.h b/src/script/lua_api/l_settings.h index dcf39a89e..67d7b342b 100644 --- a/src/script/lua_api/l_settings.h +++ b/src/script/lua_api/l_settings.h @@ -42,6 +42,9 @@ private: // get_np_group(self, key) -> noiseparam static int l_get_np_group(lua_State *L); + // get_flags(self, key) -> key/value table + static int l_get_flags(lua_State *L); + // set(self, key, value) static int l_set(lua_State *L); diff --git a/src/settings.cpp b/src/settings.cpp index c1fe41fa3..3728fabf2 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -484,12 +484,33 @@ v3f Settings::getV3F(const std::string &name) const u32 Settings::getFlagStr(const std::string &name, const FlagDesc *flagdesc, u32 *flagmask) const { - std::string val = get(name); - return std::isdigit(val[0]) - ? stoi(val) - : readFlagString(val, flagdesc, flagmask); -} + u32 flags = 0; + u32 mask_default = 0; + + std::string value; + // Read default value (if there is any) + if (getDefaultNoEx(name, value)) { + flags = std::isdigit(value[0]) + ? stoi(value) + : readFlagString(value, flagdesc, &mask_default); + } + + // Apply custom flags "on top" + value = get(name); + u32 flags_user; + u32 mask_user = U32_MAX; + flags_user = std::isdigit(value[0]) + ? stoi(value) // Override default + : readFlagString(value, flagdesc, &mask_user); + flags &= ~mask_user; + flags |= flags_user; + + if (flagmask) + *flagmask = mask_default | mask_user; + + return flags; +} // N.B. if getStruct() is used to read a non-POD aggregate type, // the behavior is undefined. @@ -736,19 +757,16 @@ bool Settings::getV3FNoEx(const std::string &name, v3f &val) const } -// N.B. getFlagStrNoEx() does not set val, but merely modifies it. Thus, -// val must be initialized before using getFlagStrNoEx(). The intention of -// this is to simplify modifying a flags field from a default value. bool Settings::getFlagStrNoEx(const std::string &name, u32 &val, - FlagDesc *flagdesc) const + const FlagDesc *flagdesc) const { - try { - u32 flags, flagmask; - - flags = getFlagStr(name, flagdesc, &flagmask); + if (!flagdesc) { + if (!(flagdesc = getFlagDescFallback(name))) + return false; // Not found + } - val &= ~flagmask; - val |= flags; + try { + val = getFlagStr(name, flagdesc, nullptr); return true; } catch (SettingNotFoundException &e) { @@ -873,6 +891,11 @@ bool Settings::setV3F(const std::string &name, v3f value) bool Settings::setFlagStr(const std::string &name, u32 flags, const FlagDesc *flagdesc, u32 flagmask) { + if (!flagdesc) { + if (!(flagdesc = getFlagDescFallback(name))) + return false; // Not found + } + return set(name, writeFlagString(flags, flagdesc, flagmask)); } @@ -1018,6 +1041,18 @@ void Settings::clearDefaultsNoLock() m_defaults.clear(); } +void Settings::setDefault(const std::string &name, const FlagDesc *flagdesc, + u32 flags) +{ + m_flags[name] = flagdesc; + setDefault(name, writeFlagString(flags, flagdesc, U32_MAX)); +} + +const FlagDesc *Settings::getFlagDescFallback(const std::string &name) const +{ + auto it = m_flags.find(name); + return it == m_flags.end() ? nullptr : it->second; +} void Settings::registerChangedCallback(const std::string &name, SettingsChangedCallback cbf, void *userdata) diff --git a/src/settings.h b/src/settings.h index 329a61140..b42e36d10 100644 --- a/src/settings.h +++ b/src/settings.h @@ -174,10 +174,12 @@ public: bool getFloatNoEx(const std::string &name, float &val) const; bool getV2FNoEx(const std::string &name, v2f &val) const; bool getV3FNoEx(const std::string &name, v3f &val) const; - // N.B. getFlagStrNoEx() does not set val, but merely modifies it. Thus, - // val must be initialized before using getFlagStrNoEx(). The intention of - // this is to simplify modifying a flags field from a default value. - bool getFlagStrNoEx(const std::string &name, u32 &val, FlagDesc *flagdesc) const; + + // Like other getters, but handling each flag individualy: + // 1) Read default flags (or 0) + // 2) Override using user-defined flags + bool getFlagStrNoEx(const std::string &name, u32 &val, + const FlagDesc *flagdesc) const; /*********** @@ -201,7 +203,7 @@ public: bool setV2F(const std::string &name, v2f value); bool setV3F(const std::string &name, v3f value); bool setFlagStr(const std::string &name, u32 flags, - const FlagDesc *flagdesc, u32 flagmask); + const FlagDesc *flagdesc = nullptr, u32 flagmask = U32_MAX); bool setNoiseParams(const std::string &name, const NoiseParams &np, bool set_default=false); // N.B. if setStruct() is used to write a non-POD aggregate type, @@ -215,6 +217,13 @@ public: void updateValue(const Settings &other, const std::string &name); void update(const Settings &other); + /************** + * Miscellany * + **************/ + + void setDefault(const std::string &name, const FlagDesc *flagdesc, u32 flags); + const FlagDesc *getFlagDescFallback(const std::string &name) const; + void registerChangedCallback(const std::string &name, SettingsChangedCallback cbf, void *userdata = NULL); void deregisterChangedCallback(const std::string &name, @@ -229,6 +238,7 @@ private: SettingEntries m_settings; SettingEntries m_defaults; + std::unordered_map m_flags; SettingsCallbackMap m_callbacks; diff --git a/src/unittest/test_settings.cpp b/src/unittest/test_settings.cpp index b2666559e..aa56f3e06 100644 --- a/src/unittest/test_settings.cpp +++ b/src/unittest/test_settings.cpp @@ -31,6 +31,7 @@ public: void runTests(IGameDef *gamedef); void testAllSettings(); + void testFlagDesc(); static const char *config_text_before; static const std::string config_text_after; @@ -41,6 +42,7 @@ static TestSettings g_test_instance; void TestSettings::runTests(IGameDef *gamedef) { TEST(testAllSettings); + TEST(testFlagDesc); } //////////////////////////////////////////////////////////////////////////////// @@ -206,3 +208,38 @@ void TestSettings::testAllSettings() UASSERT(!"Setting not found!"); } } + +void TestSettings::testFlagDesc() +{ + Settings s; + FlagDesc flagdesc[] = { + { "biomes", 0x01 }, + { "trees", 0x02 }, + { "jungles", 0x04 }, + { "oranges", 0x08 }, + { "tables", 0x10 }, + { nullptr, 0 } + }; + + // Enabled: biomes, jungles, oranges (default) + s.setDefault("test_desc", flagdesc, readFlagString( + "biomes,notrees,jungles,oranges", flagdesc, nullptr)); + UASSERT(s.getFlagStr("test_desc", flagdesc, nullptr) == (0x01 | 0x04 | 0x08)); + + // Enabled: jungles, oranges, tables + s.set("test_desc", "nobiomes,tables"); + UASSERT(s.getFlagStr("test_desc", flagdesc, nullptr) == (0x04 | 0x08 | 0x10)); + + // Enabled: (nothing) + s.set("test_desc", "nobiomes,nojungles,nooranges,notables"); + UASSERT(s.getFlagStr("test_desc", flagdesc, nullptr) == 0x00); + + // Numeric flag tests (override) + // Enabled: trees, tables + s.setDefault("test_flags", flagdesc, 0x02 | 0x10); + UASSERT(s.getFlagStr("test_flags", flagdesc, nullptr) == (0x02 | 0x10)); + + // Enabled: tables + s.set("test_flags", "16"); + UASSERT(s.getFlagStr("test_flags", flagdesc, nullptr) == 0x10); +} -- 2.25.1