Fix #12147: reset all saved settings to their default before loading a game (#12210)

This commit is contained in:
Patric Stout 2024-03-02 16:05:43 +01:00 committed by GitHub
parent aff09306de
commit 8f22066b9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 4 deletions

View File

@ -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

View File

@ -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

View File

@ -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<IntSettingDesc, BoolSettingDesc, OneOfManySettingDesc, ManyOfManySettingDesc, StringSettingDesc, ListSettingDesc, NullSettingDesc> SettingVariant;