Skip to content

Commit

Permalink
Fix OpenTTD#12147: reset all saved settings to their default before l…
Browse files Browse the repository at this point in the history
…oading a game (OpenTTD#12210)
  • Loading branch information
TrueBrain authored Mar 2, 2024
1 parent aff0930 commit 8f22066
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/saveload/settings_sl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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. */
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions src/settings_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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. */
Expand All @@ -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;
Expand Down

0 comments on commit 8f22066

Please sign in to comment.