OpenTTD Source  1.11.0-beta2
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 std::string _game_saveload_string;
117 static uint _game_saveload_strings;
118 
119 static const SaveLoad _game_language_header[] = {
120  SLEG_SSTR(_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_SSTR(_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.c_str();
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.clear();
149  SlObject(nullptr, _game_language_header);
150 
151  LanguageStrings ls(_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);
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 
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]);
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 };
ScriptConfig::StringToSettings
void StringToSettings(const char *value)
Convert a string which is stored in the config file or savegames to custom settings of this Script.
Definition: script_config.cpp:179
ScriptConfig::SettingsToString
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.
Definition: script_config.cpp:205
ReconsiderGameScriptLanguage
void ReconsiderGameScriptLanguage()
Reconsider the game script language, so we use the right one.
Definition: game_text.cpp:346
_network_server
bool _network_server
network-server is active
Definition: network.cpp:53
Game::Load
static void Load(int version)
Load data for a GameScript from a savegame.
Definition: game_core.cpp:216
SLE_STR
#define SLE_STR(base, variable, type, length)
Storage of a string in every savegame version.
Definition: saveload.h:647
CH_LAST
@ CH_LAST
Last chunk in this array.
Definition: saveload.h:410
saveload.h
SLEG_SSTR
#define SLEG_SSTR(variable, type)
Storage of a global std::string in every savegame version.
Definition: saveload.h:789
ChunkHandler
Handlers and description of chunk.
Definition: saveload.h:379
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
SLF_ALLOW_CONTROL
@ SLF_ALLOW_CONTROL
allow control codes in the strings
Definition: saveload.h:489
DEBUG
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
GameConfig
Definition: game_config.hpp:15
ScriptConfig::GetName
const char * GetName() const
Get the name of the Script.
Definition: script_config.cpp:169
SLE_END
#define SLE_END()
End marker of a struct/class save or load.
Definition: saveload.h:686
ScriptConfig::IsRandom
bool IsRandom() const
Is the current Script a randomly chosen Script?
Definition: script_config.cpp:164
_current_data
GameStrings * _current_data
The currently loaded game strings.
Definition: game_text.cpp:302
StrEmpty
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:60
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:52
GameStrings::raw_strings
std::vector< LanguageStrings > raw_strings
The raw strings per language, first must be English/the master language!.
Definition: game_text.hpp:37
SlObject
void SlObject(void *object, const SaveLoad *sld)
Main SaveLoad function.
Definition: saveload.cpp:1612
ScriptInstance::LoadEmpty
static void LoadEmpty()
Load and discard data from a savegame.
Definition: script_instance.cpp:618
SlAutolength
void SlAutolength(AutolengthProc *proc, void *arg)
Do something of which I have no idea what it is :P.
Definition: saveload.cpp:1640
LanguageStrings
Container for the raw (unencoded) language strings of a language.
Definition: game_text.hpp:20
ScriptConfig::GetVersion
int GetVersion() const
Get the version of the Script.
Definition: script_config.cpp:174
LanguageStrings::language
std::string language
Name of the language (base filename). Empty string if invalid.
Definition: game_text.hpp:21
SLEG_VAR
#define SLEG_VAR(variable, type)
Storage of a global variable in every savegame version.
Definition: saveload.h:761
SLEG_STR
#define SLEG_STR(variable, type)
Storage of a global string in every savegame version.
Definition: saveload.h:782
SlErrorCorrupt
void NORETURN SlErrorCorrupt(const char *msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:358
GameConfig::GetConfig
static GameConfig * GetConfig(ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition: game_config.cpp:18
Game::Save
static void Save()
Save data from a GameScript to a savegame.
Definition: game_core.cpp:205
ScriptConfig::Change
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.
Definition: script_config.cpp:19
LanguageStrings::lines
StringList lines
The lines of the file to pass into the parser/encoder.
Definition: game_text.hpp:22
GameStrings::Compile
void Compile()
Compile the language.
Definition: game_text.cpp:277
strecpy
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: string.cpp:112
SaveLoad
SaveLoad type struct.
Definition: saveload.h:516
ScriptConfig::SSS_FORCE_GAME
@ SSS_FORCE_GAME
Get the Script config from the current game.
Definition: script_config.hpp:105
lastof
#define lastof(x)
Get the last element of an fixed size array.
Definition: stdafx.h:383
Game::StartNew
static void StartNew()
Start up a new GameScript.
Definition: game_core.cpp:72
GameStrings
Container for all the game strings.
Definition: game_text.hpp:33
ScriptConfig::HasScript
bool HasScript() const
Is this config attached to an Script? In other words, is there a Script that is assigned to this slot...
Definition: script_config.cpp:159
SlIterateArray
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:631