OpenTTD Source  20241120-master-g6d3adc6169
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);
LoadCheckData _load_check_data
Data loaded from save during SL_LOAD_CHECK.
Definition: fios_gui.cpp:41
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
bool _networking
are we in networking mode?
Definition: network.cpp:65
bool _network_server
network-server is active
Definition: network.cpp:66
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:658
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:351
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
Definition: saveload.cpp:1893
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Definition: saveload.cpp:1755
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
Definition: saveload.cpp:1702
Functions/types related to saving and loading games.
@ SLE_VAR_NULL
useful to write zeros in savegame.
Definition: saveload.h:651
@ CH_READONLY
Chunk is never saved.
Definition: saveload.h:457
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition: saveload.h:507
constexpr VarType GetVarFileType(VarType type)
Get the FileType of a setting.
Definition: saveload.h:758
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition: saveload.h:510
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:1266
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition: saveload.h:516
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:1239
@ 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
@ SLV_RIFF_TO_ARRAY
294 PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks.
Definition: saveload.h:332
@ SLV_TABLE_CHUNKS
295 PR#9322 Introduction of CH_TABLE and CH_SPARSE_TABLE.
Definition: saveload.h:334
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
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:58
static constexpr const SettingDesc * GetSettingDesc(const SettingVariant &desc)
Helper to convert the type of the iterated settings description to a pointer to it.
@ SF_NOT_IN_SAVE
Do not save with savegame, basically client-based.
@ SF_NO_NETWORK_SYNC
Do not synchronize over network (but it is saved if SF_NOT_IN_SAVE is not set).
void HandleOldDiffCustom(bool savegame)
Reading of the old diff_custom array and transforming it to the new format.
Definition: settings_sl.cpp:36
static void LoadSettings(const SettingTable &settings, void *object, const SaveLoadCompatTable &slct)
Save and load handler for settings.
void PrepareOldDiffCustom()
Prepare for reading and old diff_custom by zero-ing the memory.
Definition: settings_sl.cpp:25
static void SaveSettings(const SettingTable &settings, void *object)
Save and load handler for settings.
static std::vector< SaveLoad > GetSettingsDesc(const SettingTable &settings, bool is_loading)
Get the SaveLoad description for the SettingTable.
Definition: settings_sl.cpp:77
Loading of settings chunks before table headers were added.
const SaveLoadCompat _gameopt_sl_compat[]
Original field order for _gameopt.
const SaveLoadCompat _settings_sl_compat[]
Original field order for _settings.
Handlers and description of chunk.
Definition: saveload.h:461
Base integer type, including boolean, settings.
void MakeValueValidAndWrite(const void *object, int32_t value) const
Make the value valid and then write it to the setting.
Definition: settings.cpp:482
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition: settings.cpp:561
void Load() const override
Load the chunk.
void Load() const override
Load the chunk.
void LoadCheck(size_t) const override
Load the chunk for game preview.
SettingTable GetSettingTable() const
Create a single table with all settings that should be stored/loaded in the savegame.
void Save() const override
Save the chunk.
uint16_t length
(Conditional) length of the variable (eg. arrays) (max array size is 65536 elements).
Definition: saveload.h:717
SaveLoadVersion version_to
Save/load the variable before this savegame version.
Definition: saveload.h:719
SaveLoadType cmd
The action to take with the saved/loaded type, All types need different action.
Definition: saveload.h:715
VarType conv
Type of the variable to be saved; this field combines both FileVarType and MemVarType.
Definition: saveload.h:716
SaveLoadVersion version_from
Save/load the variable starting from this savegame version.
Definition: saveload.h:718
Properties of config file settings.
virtual void ResetToDefault(void *object) const =0
Reset the setting to its default value.
constexpr const std::string & GetName() const
Get the name of this setting.
SaveLoad save
Internal structure (going to savegame, parts to config).
virtual bool IsIntSetting() const
Check whether this setting is an integer type setting.
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition: settings.cpp:910
SettingFlag flags
Handles how a setting would show up in the GUI (text/currency, etc.).