OpenTTD Source: src/saveload/game_sl.cpp Source File

OpenTTD Source 1.11.0-RC1

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 {
38 GameConfig *config = GameConfig::GetConfig();
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 */
60 GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr);
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) {
68 GameInstance::LoadEmpty();
69 if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
70 return;
71 }
72
73 GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
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
167 _current_data->Compile();
168 ReconsiderGameScriptLanguage();
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