diff --git a/src/saveload/settings_sl.cpp b/src/saveload/settings_sl.cpp index ab8f5cec28691..987344f952b95 100644 --- a/src/saveload/settings_sl.cpp +++ b/src/saveload/settings_sl.cpp @@ -187,10 +187,20 @@ struct PATSChunkHandler : ChunkHandler { void Load() const override { - /* Copy over default setting since some might not get loaded in - * a networking environment. This ensures for example that the local - * currency setting stays when joining a network-server */ - LoadSettings(this->GetSettingTable(), &_settings_game, _settings_sl_compat); + const auto settings_table = this->GetSettingTable(); + + /* Reset all settings to their default, so any settings missing in the savegame + * are their default, and not "value of last game". AfterLoad might still fix + * up values to become non-default, depending on the saveload version. */ + for (auto &desc : settings_table) { + const SettingDesc *sd = GetSettingDesc(desc); + if (sd->flags & SF_NOT_IN_SAVE) continue; + if ((sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) continue; + + sd->ResetToDefault(&_settings_game); + } + + LoadSettings(settings_table, &_settings_game, _settings_sl_compat); } void LoadCheck(size_t) const override diff --git a/src/settings.cpp b/src/settings.cpp index 5200b2394c6a8..0fc581443eff9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -768,6 +768,11 @@ bool IntSettingDesc::IsDefaultValue(void *object) const return this->def == object_value; } +void IntSettingDesc::ResetToDefault(void *object) const +{ + this->Write(object, this->def); +} + std::string StringSettingDesc::FormatValue(const void *object) const { const std::string &str = this->Read(object); @@ -800,6 +805,11 @@ bool StringSettingDesc::IsDefaultValue(void *object) const return this->def == str; } +void StringSettingDesc::ResetToDefault(void *object) const +{ + this->Write(object, this->def); +} + bool ListSettingDesc::IsSameValue(const IniItem *, void *) const { /* Checking for equality is way more expensive than just writing the value. */ @@ -812,6 +822,12 @@ bool ListSettingDesc::IsDefaultValue(void *) const return false; } +void ListSettingDesc::ResetToDefault(void *) const +{ + /* Resetting a list to default is not supported. */ + NOT_REACHED(); +} + /** * Loads all items from a 'grpname' section into a list * The list parameter can be a nullptr pointer, in this case nothing will be diff --git a/src/settings_internal.h b/src/settings_internal.h index f74127a8aedf9..177d00a324484 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -137,6 +137,11 @@ struct SettingDesc { * @return true iff the value is the default value. */ virtual bool IsDefaultValue(void *object) const = 0; + + /** + * Reset the setting to its default value. + */ + virtual void ResetToDefault(void *object) const = 0; }; /** Base integer type, including boolean, settings. Only these are shown in the settings UI. */ @@ -236,6 +241,7 @@ struct IntSettingDesc : SettingDesc { void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; bool IsDefaultValue(void *object) const override; + void ResetToDefault(void *object) const override; int32_t Read(const void *object) const; private: @@ -332,6 +338,7 @@ struct StringSettingDesc : SettingDesc { void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; bool IsDefaultValue(void *object) const override; + void ResetToDefault(void *object) const override; const std::string &Read(const void *object) const; private: @@ -350,6 +357,7 @@ struct ListSettingDesc : SettingDesc { void ParseValue(const IniItem *item, void *object) const override; bool IsSameValue(const IniItem *item, void *object) const override; bool IsDefaultValue(void *object) const override; + void ResetToDefault(void *object) const override; }; /** Placeholder for settings that have been removed, but might still linger in the savegame. */ @@ -361,6 +369,7 @@ struct NullSettingDesc : SettingDesc { void ParseValue(const IniItem *, void *) const override { NOT_REACHED(); } bool IsSameValue(const IniItem *, void *) const override { NOT_REACHED(); } bool IsDefaultValue(void *) const override { NOT_REACHED(); } + void ResetToDefault(void *) const override { NOT_REACHED(); } }; typedef std::variant SettingVariant;