Settings: Add get_flags API for mapgen flags (mg_flags, mgv6_spflags, ...) (#9284)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Sat, 25 Jan 2020 15:56:54 +0000 (16:56 +0100)
committerGitHub <noreply@github.com>
Sat, 25 Jan 2020 15:56:54 +0000 (16:56 +0100)
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 <wuzzy2@mail.ru>
23 files changed:
doc/lua_api.txt
src/defaultsettings.cpp
src/mapgen/mapgen.cpp
src/mapgen/mapgen.h
src/mapgen/mapgen_carpathian.cpp
src/mapgen/mapgen_carpathian.h
src/mapgen/mapgen_flat.cpp
src/mapgen/mapgen_flat.h
src/mapgen/mapgen_fractal.cpp
src/mapgen/mapgen_fractal.h
src/mapgen/mapgen_v5.cpp
src/mapgen/mapgen_v5.h
src/mapgen/mapgen_v6.cpp
src/mapgen/mapgen_v6.h
src/mapgen/mapgen_v7.cpp
src/mapgen/mapgen_v7.h
src/mapgen/mapgen_valleys.cpp
src/mapgen/mapgen_valleys.h
src/script/lua_api/l_settings.cpp
src/script/lua_api/l_settings.h
src/settings.cpp
src/settings.h
src/unittest/test_settings.cpp

index 551aa50b5b72043b580b04c47738699f28591441..1857ce541e063b0767fdb11c87340b70ff2a9705 100644 (file)
@@ -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"""`.
index 1ab4a333ee22fff50a45851a21e0c322730ba7f1..754ce3547e2c97586040b3fb226e0fbac3667921 100644 (file)
@@ -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");
index 81ccf1f8d80abcadcba2dd87ef02891d0b12f628..79c429ff6a782d9f8b8aeeba53e66b33e205d039 100644 (file)
@@ -215,6 +215,17 @@ void Mapgen::getMapgenNames(std::vector<const char *> *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);
index 1473d41a685647945685412d6544b17e6bda9854..dc325c7916fca071bd3092ab1ac84b616b4c315e 100644 (file)
@@ -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<const char *> *mgnames, bool include_hidden);
+       static void setDefaultSettings(Settings *settings);
 
 private:
        // isLiquidHorizontallyFlowable() is a helper function for updateLiquid()
index 67f542c0dd519d218af5d5d62a829a22ddfe79c5..0dc1d33be6edd216e434f25c081679f943bab9f5 100644 (file)
@@ -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);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 
index ef49df213c24947065a2f73a51deca4a191a9026..acd379958d9b1a4ff27813d8b301ace3128eb71b 100644 (file)
@@ -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
index 656e7d72c71c46b87e5e7a7839fa19f912035cde..879435948d2fbd9e94d12ca9b3f13d664bc6c6f9 100644 (file)
@@ -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);
+}
+
+
 /////////////////////////////////////////////////////////////////
 
 
index 2ff87c0db2f5192730ee1bc31ddeea4a53281f58..c314c76056cc1c3efc5251df3eb2be09b858acb5 100644 (file)
@@ -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
index 1ac57cedec60bd691d437a35b9575fd63463c3cd..cabe0b850e87cde79092919f1e6ceaa6ec135911 100644 (file)
@@ -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);
+}
+
+
 /////////////////////////////////////////////////////////////////
 
 
index 0654d036047c47a4fd2213cd4e1c29b0ee727002..971dfd822f3618039fd851c9be85f3973fad86cd 100644 (file)
@@ -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);
 };
 
 
index c003c27d66ba1895e3817751c9c881cf60bbdb01..447fe8c5083027229f322cbc9a2b9465cde16e33 100644 (file)
@@ -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)
 {
 
index ecdcdaf4107bc5a6114b30d2daa690c59502ae48..17bc466f0acf040c2ee51ca28ac404c558c12d17 100644 (file)
@@ -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
index 4e876fc53a978ca69d94426702652435f9a433ec..653adc8ec550bd0b30c3d0ecc6503adf2514623e 100644 (file)
@@ -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)
 {
index 7d522955929744c68c12a89424b04fe1e3c04094..d8cdcb26ff965cc5af67457626ea66079fe6afa4 100644 (file)
@@ -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);
 };
 
 
index 23cbd4e0acb04ecd0619ff308d2a03788b41199e..325c4957a97250f775f119c640e392f25a57c290 100644 (file)
@@ -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);
+}
+
+
 ////////////////////////////////////////////////////////////////////////////////
 
 
index 6ca39f16490db0d920f958307a5f953892ad1aff..0605c5c9789e4fbdc013d8dd70a2533aa9edb0c2 100644 (file)
@@ -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);
 };
 
 
index 3c6045105074ae2a6ebe787bd765fc6121ebb2dc..2b8703fa5ddc386a195743b8091d521854395e0e 100644 (file)
@@ -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
index be97f07638861051c8f15ce4c3dcf4333f3c3228..1aec68842d73b43de4f959817a42429ced0702a9 100644 (file)
@@ -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);
 };
 
 
index cc2c737899a9ea9dc98c87f6e3ca337e29b55e67..33eb023926138182ebc1edc95e4caed2c39966ab 100644 (file)
@@ -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),
index dcf39a89e1c5f07b943a048fd6f6ba664c2dd54f..67d7b342b39e2fecc713fe22e0b3098513945a9b 100644 (file)
@@ -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);
 
index c1fe41fa33f4bf26ca7b11cb2277121deccdbd32..3728fabf23007287bf225046124f1c9f81499e2e 100644 (file)
@@ -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)
index 329a611408cc54800dcd2b147704958e27bde51b..b42e36d109bbe5026a208f563d974385bf853074 100644 (file)
@@ -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<std::string, const FlagDesc *> m_flags;
 
        SettingsCallbackMap m_callbacks;
 
index b2666559e5f930f61fa60f6c5ed82b703c00fed0..aa56f3e06b8deadefbdf3ec327cde5e9759961a8 100644 (file)
@@ -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);
+}