OpenTTD
game_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 #include "../debug.h"
12 #include "saveload.h"
13 #include "../string_func.h"
14 
15 #include "../game/game.hpp"
16 #include "../game/game_config.hpp"
17 #include "../network/network.h"
18 #include "../game/game_instance.hpp"
19 #include "../game/game_text.hpp"
20 
21 #include "../safeguards.h"
22 
23 static char _game_saveload_name[64];
24 static int _game_saveload_version;
25 static char _game_saveload_settings[1024];
26 static bool _game_saveload_is_random;
27 
28 static const SaveLoad _game_script[] = {
29  SLEG_STR(_game_saveload_name, SLE_STRB),
30  SLEG_STR(_game_saveload_settings, SLE_STRB),
31  SLEG_VAR(_game_saveload_version, SLE_UINT32),
32  SLEG_VAR(_game_saveload_is_random, SLE_BOOL),
33  SLE_END()
34 };
35 
36 static void SaveReal_GSDT(int *index_ptr)
37 {
39 
40  if (config->HasScript()) {
41  strecpy(_game_saveload_name, config->GetName(), lastof(_game_saveload_name));
42  _game_saveload_version = config->GetVersion();
43  } else {
44  /* No GameScript is configured for this so store an empty string as name. */
45  _game_saveload_name[0] = '\0';
46  _game_saveload_version = -1;
47  }
48 
49  _game_saveload_is_random = config->IsRandom();
50  _game_saveload_settings[0] = '\0';
51  config->SettingsToString(_game_saveload_settings, lastof(_game_saveload_settings));
52 
53  SlObject(nullptr, _game_script);
54  Game::Save();
55 }
56 
57 static void Load_GSDT()
58 {
59  /* Free all current data */
61 
62  if ((CompanyID)SlIterateArray() == (CompanyID)-1) return;
63 
64  _game_saveload_version = -1;
65  SlObject(nullptr, _game_script);
66 
67  if (_networking && !_network_server) {
69  if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
70  return;
71  }
72 
74  if (StrEmpty(_game_saveload_name)) {
75  } else {
76  config->Change(_game_saveload_name, _game_saveload_version, false, _game_saveload_is_random);
77  if (!config->HasScript()) {
78  /* No version of the GameScript available that can load the data. Try to load the
79  * latest version of the GameScript instead. */
80  config->Change(_game_saveload_name, -1, false, _game_saveload_is_random);
81  if (!config->HasScript()) {
82  if (strcmp(_game_saveload_name, "%_dummy") != 0) {
83  DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version);
84  DEBUG(script, 0, "This game will continue to run without GameScript.");
85  } else {
86  DEBUG(script, 0, "The savegame had no GameScript available at the time of saving.");
87  DEBUG(script, 0, "This game will continue to run without GameScript.");
88  }
89  } else {
90  DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version);
91  DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible.");
92  }
93  /* Make sure the GameScript doesn't get the saveload data, as he was not the
94  * writer of the saveload data in the first place */
95  _game_saveload_version = -1;
96  }
97  }
98 
99  config->StringToSettings(_game_saveload_settings);
100 
101  /* Start the GameScript directly if it was active in the savegame */
102  Game::StartNew();
103  Game::Load(_game_saveload_version);
104 
105  if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
106 }
107 
108 static void Save_GSDT()
109 {
110  SlSetArrayIndex(0);
111  SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr);
112 }
113 
114 extern GameStrings *_current_data;
115 
116 static const char *_game_saveload_string;
117 static uint _game_saveload_strings;
118 
119 static const SaveLoad _game_language_header[] = {
120  SLEG_STR(_game_saveload_string, SLE_STR),
121  SLEG_VAR(_game_saveload_strings, SLE_UINT32),
122  SLE_END()
123 };
124 
125 static const SaveLoad _game_language_string[] = {
126  SLEG_STR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
127  SLE_END()
128 };
129 
130 static void SaveReal_GSTR(const LanguageStrings *ls)
131 {
132  _game_saveload_string = ls->language;
133  _game_saveload_strings = (uint)ls->lines.size();
134 
135  SlObject(nullptr, _game_language_header);
136  for (const auto &i : ls->lines) {
137  _game_saveload_string = i.c_str();
138  SlObject(nullptr, _game_language_string);
139  }
140 }
141 
142 static void Load_GSTR()
143 {
144  delete _current_data;
145  _current_data = new GameStrings();
146 
147  while (SlIterateArray() != -1) {
148  _game_saveload_string = nullptr;
149  SlObject(nullptr, _game_language_header);
150 
151  std::unique_ptr<LanguageStrings> ls(new LanguageStrings(_game_saveload_string != nullptr ? _game_saveload_string : ""));
152  for (uint i = 0; i < _game_saveload_strings; i++) {
153  SlObject(nullptr, _game_language_string);
154  ls->lines.emplace_back(_game_saveload_string != nullptr ? _game_saveload_string : "");
155  }
156 
157  _current_data->raw_strings.push_back(std::move(ls));
158  }
159 
160  /* If there were no strings in the savegame, set GameStrings to nullptr */
161  if (_current_data->raw_strings.size() == 0) {
162  delete _current_data;
163  _current_data = nullptr;
164  return;
165  }
166 
167  _current_data->Compile();
169 }
170 
171 static void Save_GSTR()
172 {
173  if (_current_data == nullptr) return;
174 
175  for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
176  SlSetArrayIndex(i);
177  SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i].get());
178  }
179 }
180 
181 extern const ChunkHandler _game_chunk_handlers[] = {
182  { 'GSTR', Save_GSTR, Load_GSTR, nullptr, nullptr, CH_ARRAY },
183  { 'GSDT', Save_GSDT, Load_GSDT, nullptr, nullptr, CH_ARRAY | CH_LAST},
184 };
Owner
Enum for all companies/owners.
Definition: company_type.h:18
bool _networking
are we in networking mode?
Definition: network.cpp:52
#define SLEG_STR(variable, type)
Storage of a global string in every savegame version.
Definition: saveload.h:737
void NORETURN SlErrorCorrupt(const char *msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:354
Container for all the game strings.
Definition: game_text.hpp:29
void Change(const char *name, int version=-1, bool force_exact_match=false, bool is_random=false)
Set another Script to be loaded in this slot.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
static GameConfig * GetConfig(ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition: game_config.cpp:18
#define SLEG_VAR(variable, type)
Storage of a global variable in every savegame version.
Definition: saveload.h:716
const char * GetName() const
Get the name of the Script.
static void Save()
Save data from a GameScript to a savegame.
Definition: game_core.cpp:205
bool IsRandom() const
Is the current Script a randomly chosen Script?
Functions/types related to saving and loading games.
allow control codes in the strings
Definition: saveload.h:471
bool HasScript() const
Is this config attached to an Script? In other words, is there a Script that is assigned to this slot...
void ReconsiderGameScriptLanguage()
Reconsider the game script language, so we use the right one.
Definition: game_text.cpp:372
void Compile()
Compile the language.
Definition: game_text.cpp:303
Container for the raw (unencoded) language strings of a language.
Definition: game_text.hpp:20
StringList lines
The lines of the file to pass into the parser/encoder.
Definition: game_text.hpp:22
static void StartNew()
Start up a new GameScript.
Definition: game_core.cpp:72
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:637
Handlers and description of chunk.
Definition: saveload.h:356
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
#define SLE_END()
End marker of a struct/class save or load.
Definition: saveload.h:651
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:66
void SlObject(void *object, const SaveLoad *sld)
Main SaveLoad function.
Definition: saveload.cpp:1546
bool _network_server
network-server is active
Definition: network.cpp:53
void SlAutolength(AutolengthProc *proc, void *arg)
Do something of which I have no idea what it is :P.
Definition: saveload.cpp:1574
static void Load(int version)
Load data for a GameScript from a savegame.
Definition: game_core.cpp:216
std::vector< std::unique_ptr< LanguageStrings > > raw_strings
The raw strings per language, first must be English/the master language!.
Definition: game_text.hpp:33
SaveLoad type struct.
Definition: saveload.h:496
#define SLE_STR(base, variable, type, length)
Storage of a string in every savegame version.
Definition: saveload.h:620
const char * language
Name of the language (base filename).
Definition: game_text.hpp:21
static void LoadEmpty()
Load and discard data from a savegame.
void StringToSettings(const char *value)
Convert a string which is stored in the config file or savegames to custom settings of this Script...
void SettingsToString(char *string, const char *last) const
Convert the custom settings to a string that can be stored in the config file or savegames.
Get the Script config from the current game.
Last chunk in this array.
Definition: saveload.h:391
GameStrings * _current_data
The currently loaded game strings.
Definition: game_text.cpp:328
int GetVersion() const
Get the version of the Script.