OpenTTD Source  20240917-master-g9ab0a47812
settings_sl.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "../stdafx.h"
11 
12 #include "saveload.h"
14 
15 #include "../settings_type.h"
16 #include "../settings_table.h"
17 #include "../network/network.h"
18 #include "../fios.h"
19 
20 #include "../safeguards.h"
21 
26 {
27  memset(_old_diff_custom, 0, sizeof(_old_diff_custom));
28 }
29 
36 void HandleOldDiffCustom(bool savegame)
37 {
38  /* Savegames before v4 didn't have "town_council_tolerance" in savegame yet. */
39  bool has_no_town_council_tolerance = savegame && IsSavegameVersionBefore(SLV_4);
40  uint options_to_load = GAME_DIFFICULTY_NUM - (has_no_town_council_tolerance ? 1 : 0);
41 
42  if (!savegame) {
43  /* If we did read to old_diff_custom, then at least one value must be non 0. */
44  bool old_diff_custom_used = false;
45  for (uint i = 0; i < options_to_load && !old_diff_custom_used; i++) {
46  old_diff_custom_used = (_old_diff_custom[i] != 0);
47  }
48 
49  if (!old_diff_custom_used) return;
50  }
51 
52  /* Iterate over all the old difficulty settings, and convert the list-value to the new setting. */
53  uint i = 0;
54  for (const auto &name : _old_diff_settings) {
55  if (has_no_town_council_tolerance && name == "town_council_tolerance") continue;
56 
57  std::string fullname = "difficulty." + name;
58  const SettingDesc *sd = GetSettingFromName(fullname);
59 
60  /* Some settings are no longer in use; skip reading those. */
61  if (sd == nullptr) {
62  i++;
63  continue;
64  }
65 
66  int32_t value = (int32_t)((name == "max_loan" ? 1000 : 1) * _old_diff_custom[i++]);
68  }
69 }
70 
77 static std::vector<SaveLoad> GetSettingsDesc(const SettingTable &settings, bool is_loading)
78 {
79  std::vector<SaveLoad> saveloads;
80  for (auto &desc : settings) {
81  const SettingDesc *sd = GetSettingDesc(desc);
82  if (sd->flags & SF_NOT_IN_SAVE) continue;
83 
84  if (is_loading && (sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) {
86  /* We don't want to read this setting, so we do need to skip over it. */
87  saveloads.push_back({sd->GetName(), sd->save.cmd, GetVarFileType(sd->save.conv) | SLE_VAR_NULL, sd->save.length, sd->save.version_from, sd->save.version_to, nullptr, 0, nullptr});
88  }
89  continue;
90  }
91 
92  saveloads.push_back(sd->save);
93  }
94 
95  return saveloads;
96 }
97 
104 static void LoadSettings(const SettingTable &settings, void *object, const SaveLoadCompatTable &slct)
105 {
106  const std::vector<SaveLoad> slt = SlCompatTableHeader(GetSettingsDesc(settings, true), slct);
107 
109  SlObject(object, slt);
110  if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many settings entries");
111 
112  /* Ensure all IntSettings are valid (min/max could have changed between versions etc). */
113  for (auto &desc : settings) {
114  const SettingDesc *sd = GetSettingDesc(desc);
115  if (sd->flags & SF_NOT_IN_SAVE) continue;
116  if ((sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) continue;
117  if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
118 
119  if (sd->IsIntSetting()) {
120  const IntSettingDesc *int_setting = sd->AsIntSetting();
121  int_setting->MakeValueValidAndWrite(object, int_setting->Read(object));
122  }
123  }
124 }
125 
132 static void SaveSettings(const SettingTable &settings, void *object)
133 {
134  const std::vector<SaveLoad> slt = GetSettingsDesc(settings, false);
135 
136  SlTableHeader(slt);
137 
138  SlSetArrayIndex(0);
139  SlObject(object, slt);
140 }
141 
144 
145  void Load() const override
146  {
147  /* Copy over default setting since some might not get loaded in
148  * a networking environment. This ensures for example that the local
149  * autosave-frequency stays when joining a network-server */
151  LoadSettings(_old_gameopt_settings, &_settings_game, _gameopt_sl_compat);
152  HandleOldDiffCustom(true);
153  }
154 };
155 
157  PATSChunkHandler() : ChunkHandler('PATS', CH_TABLE) {}
158 
163  SettingTable GetSettingTable() const
164  {
165  static const SettingTable saveload_settings_tables[] = {
166  _difficulty_settings,
167  _economy_settings,
168  _game_settings,
169  _linkgraph_settings,
170  _locale_settings,
171  _pathfinding_settings,
172  _script_settings,
173  _world_settings,
174  };
175  static std::vector<SettingVariant> settings_table;
176 
177  if (settings_table.empty()) {
178  for (auto &saveload_settings_table : saveload_settings_tables) {
179  for (auto &saveload_setting : saveload_settings_table) {
180  settings_table.push_back(saveload_setting);
181  }
182  }
183  }
184 
185  return settings_table;
186  }
187 
188  void Load() const override
189  {
190  const auto settings_table = this->GetSettingTable();
191 
192  /* Reset all settings to their default, so any settings missing in the savegame
193  * are their default, and not "value of last game". AfterLoad might still fix
194  * up values to become non-default, depending on the saveload version. */
195  for (auto &desc : settings_table) {
196  const SettingDesc *sd = GetSettingDesc(desc);
197  if (sd->flags & SF_NOT_IN_SAVE) continue;
198  if ((sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) continue;
199 
201  }
202 
204  }
205 
206  void LoadCheck(size_t) const override
207  {
209  }
210 
211  void Save() const override
212  {
214  }
215 };
216 
217 static const OPTSChunkHandler OPTS;
218 static const PATSChunkHandler PATS;
219 static const ChunkHandlerRef setting_chunk_handlers[] = {
220  OPTS,
221  PATS,
222 };
223 
224 extern const ChunkHandlerTable _setting_chunk_handlers(setting_chunk_handlers);
SaveLoad::version_to
SaveLoadVersion version_to
Save/load the variable before this savegame version.
Definition: saveload.h:713
PrepareOldDiffCustom
void PrepareOldDiffCustom()
Prepare for reading and old diff_custom by zero-ing the memory.
Definition: settings_sl.cpp:25
GetSettingFromName
static const SettingDesc * GetSettingFromName(const std::string_view name, const SettingTable &settings)
Given a name of setting, return a setting description from the table.
Definition: settings.cpp:1616
ChunkHandlerRef
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition: saveload.h:501
_network_server
bool _network_server
network-server is active
Definition: network.cpp:66
SettingDesc::save
SaveLoad save
Internal structure (going to savegame, parts to config).
Definition: settings_internal.h:78
_load_check_data
LoadCheckData _load_check_data
Data loaded from save during SL_LOAD_CHECK.
Definition: fios_gui.cpp:41
GetSettingsDesc
static std::vector< SaveLoad > GetSettingsDesc(const SettingTable &settings, bool is_loading)
Get the SaveLoad description for the SettingTable.
Definition: settings_sl.cpp:77
SlErrorCorrupt
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:351
SLE_VAR_NULL
@ SLE_VAR_NULL
useful to write zeros in savegame.
Definition: saveload.h:645
saveload.h
SaveLoadCompatTable
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition: saveload.h:510
SettingDesc::flags
SettingFlag flags
Handles how a setting would show up in the GUI (text/currency, etc.).
Definition: settings_internal.h:76
ChunkHandler
Handlers and description of chunk.
Definition: saveload.h:455
SaveLoad::conv
VarType conv
Type of the variable to be saved; this field combines both FileVarType and MemVarType.
Definition: saveload.h:710
PATSChunkHandler::Save
void Save() const override
Save the chunk.
Definition: settings_sl.cpp:211
IntSettingDesc::MakeValueValidAndWrite
void MakeValueValidAndWrite(const void *object, int32_t value) const
Make the value valid and then write it to the setting.
Definition: settings.cpp:482
CH_READONLY
@ CH_READONLY
Chunk is never saved.
Definition: saveload.h:451
IntSettingDesc
Base integer type, including boolean, settings.
Definition: settings_internal.h:148
SettingDesc::GetName
constexpr const std::string & GetName() const
Get the name of this setting.
Definition: settings_internal.h:87
SaveLoad::cmd
SaveLoadType cmd
The action to take with the saved/loaded type, All types need different action.
Definition: saveload.h:709
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
SF_NO_NETWORK_SYNC
@ SF_NO_NETWORK_SYNC
Do not synchronize over network (but it is saved if SF_NOT_IN_SAVE is not set).
Definition: settings_internal.h:29
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:65
SLV_RIFF_TO_ARRAY
@ SLV_RIFF_TO_ARRAY
294 PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks.
Definition: saveload.h:332
GetSettingDesc
static constexpr const SettingDesc * GetSettingDesc(const SettingVariant &desc)
Helper to convert the type of the iterated settings description to a pointer to it.
Definition: settings_internal.h:392
OPTSChunkHandler::Load
void Load() const override
Load the chunk.
Definition: settings_sl.cpp:145
PATSChunkHandler::Load
void Load() const override
Load the chunk.
Definition: settings_sl.cpp:188
SLV_4
@ SLV_4
4.0 1 4.1 122 0.3.3, 0.3.4 4.2 1222 0.3.5 4.3 1417 4.4 1426
Definition: saveload.h:37
SettingDesc::ResetToDefault
virtual void ResetToDefault(void *object) const =0
Reset the setting to its default value.
_settings_sl_compat
const SaveLoadCompat _settings_sl_compat[]
Original field order for _settings.
Definition: settings_sl_compat.h:30
settings_sl_compat.h
SlIsObjectCurrentlyValid
bool SlIsObjectCurrentlyValid(SaveLoadVersion version_from, SaveLoadVersion version_to)
Checks if some version from/to combination falls within the range of the active savegame version.
Definition: saveload.h:1261
PATSChunkHandler::LoadCheck
void LoadCheck(size_t) const override
Load the chunk for game preview.
Definition: settings_sl.cpp:206
SettingDesc
Properties of config file settings.
Definition: settings_internal.h:71
IntSettingDesc::Read
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition: settings.cpp:561
ChunkHandlerTable
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition: saveload.h:504
SaveLoad::version_from
SaveLoadVersion version_from
Save/load the variable starting from this savegame version.
Definition: saveload.h:712
PATSChunkHandler::GetSettingTable
SettingTable GetSettingTable() const
Create a single table with all settings that should be stored/loaded in the savegame.
Definition: settings_sl.cpp:163
HandleOldDiffCustom
void HandleOldDiffCustom(bool savegame)
Reading of the old diff_custom array and transforming it to the new format.
Definition: settings_sl.cpp:36
SF_NOT_IN_SAVE
@ SF_NOT_IN_SAVE
Do not save with savegame, basically client-based.
Definition: settings_internal.h:27
SlCompatTableHeader
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
Definition: saveload.cpp:1888
SaveLoad::length
uint16_t length
(Conditional) length of the variable (eg. arrays) (max array size is 65536 elements).
Definition: saveload.h:711
SaveSettings
static void SaveSettings(const SettingTable &settings, void *object)
Save and load handler for settings.
Definition: settings_sl.cpp:132
SlObject
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
Definition: saveload.cpp:1697
SettingDesc::IsIntSetting
virtual bool IsIntSetting() const
Check whether this setting is an integer type setting.
Definition: settings_internal.h:96
IsSavegameVersionBefore
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:1234
SlTableHeader
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Definition: saveload.cpp:1750
_gameopt_sl_compat
const SaveLoadCompat _gameopt_sl_compat[]
Original field order for _gameopt.
Definition: settings_sl_compat.h:16
PATSChunkHandler
Definition: settings_sl.cpp:156
OPTSChunkHandler
Definition: settings_sl.cpp:142
SLV_TABLE_CHUNKS
@ SLV_TABLE_CHUNKS
295 PR#9322 Introduction of CH_TABLE and CH_SPARSE_TABLE.
Definition: saveload.h:334
SlIterateArray
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:658
_settings_newgame
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:58
LoadSettings
static void LoadSettings(const SettingTable &settings, void *object, const SaveLoadCompatTable &slct)
Save and load handler for settings.
Definition: settings_sl.cpp:104
SettingDesc::AsIntSetting
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition: settings.cpp:910
GetVarFileType
constexpr VarType GetVarFileType(VarType type)
Get the FileType of a setting.
Definition: saveload.h:752