2011-12-19 21:56:34 +01:00
/*
* This file is part of OpenTTD .
* 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.
* 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 .
* 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/>.
*/
/** @file game_sl.cpp Handles the saveload part of the GameScripts */
# include "../stdafx.h"
# include "../debug.h"
2021-05-30 15:59:40 +02:00
2011-12-19 21:56:34 +01:00
# include "saveload.h"
2021-05-30 15:59:40 +02:00
# include "compat/game_sl_compat.h"
2011-12-19 21:56:34 +01:00
2021-05-30 15:59:40 +02:00
# include "../string_func.h"
2011-12-19 21:56:34 +01:00
# include "../game/game.hpp"
# include "../game/game_config.hpp"
# include "../network/network.h"
# include "../game/game_instance.hpp"
2011-12-19 22:05:46 +01:00
# include "../game/game_text.hpp"
2011-12-19 21:56:34 +01:00
2014-04-23 22:13:33 +02:00
# include "../safeguards.h"
2021-04-29 19:04:27 +02:00
static std : : string _game_saveload_name ;
static int _game_saveload_version ;
static std : : string _game_saveload_settings ;
static bool _game_saveload_is_random ;
2011-12-19 21:56:34 +01:00
2021-05-30 15:59:40 +02:00
static const SaveLoad _game_script_desc [ ] = {
2021-06-14 10:05:30 +02:00
SLEG_SSTR ( " name " , _game_saveload_name , SLE_STR ) ,
SLEG_SSTR ( " settings " , _game_saveload_settings , SLE_STR ) ,
SLEG_VAR ( " version " , _game_saveload_version , SLE_UINT32 ) ,
SLEG_VAR ( " is_random " , _game_saveload_is_random , SLE_BOOL ) ,
2011-12-19 21:56:34 +01:00
} ;
static void SaveReal_GSDT ( int * index_ptr )
{
GameConfig * config = GameConfig : : GetConfig ( ) ;
if ( config - > HasScript ( ) ) {
2021-04-29 19:04:27 +02:00
_game_saveload_name = config - > GetName ( ) ;
2011-12-19 21:56:34 +01:00
_game_saveload_version = config - > GetVersion ( ) ;
} else {
/* No GameScript is configured for this so store an empty string as name. */
2021-04-29 19:04:27 +02:00
_game_saveload_name . clear ( ) ;
2011-12-19 21:56:34 +01:00
_game_saveload_version = - 1 ;
}
_game_saveload_is_random = config - > IsRandom ( ) ;
2021-04-29 19:04:27 +02:00
_game_saveload_settings = config - > SettingsToString ( ) ;
2011-12-19 21:56:34 +01:00
2021-05-30 15:59:40 +02:00
SlObject ( nullptr , _game_script_desc ) ;
2011-12-19 21:56:34 +01:00
Game : : Save ( ) ;
}
2021-06-07 23:24:37 +02:00
struct GSDTChunkHandler : ChunkHandler {
GSDTChunkHandler ( ) : ChunkHandler ( ' GSDT ' , CH_TABLE ) { }
2021-05-30 15:59:40 +02:00
2021-06-07 23:24:37 +02:00
void Load ( ) const override
{
const std : : vector < SaveLoad > slt = SlCompatTableHeader ( _game_script_desc , _game_script_sl_compat ) ;
2011-12-19 21:56:34 +01:00
2021-06-07 23:24:37 +02:00
/* Free all current data */
2023-05-05 21:59:50 +02:00
GameConfig : : GetConfig ( GameConfig : : SSS_FORCE_GAME ) - > Change ( std : : nullopt ) ;
2011-12-19 21:56:34 +01:00
2021-06-07 23:24:37 +02:00
if ( SlIterateArray ( ) = = - 1 ) return ;
2011-12-19 21:56:34 +01:00
2021-06-07 23:24:37 +02:00
_game_saveload_version = - 1 ;
SlObject ( nullptr , slt ) ;
2011-12-19 21:56:34 +01:00
2022-12-15 21:43:07 +01:00
if ( _game_mode = = GM_MENU | | ( _networking & & ! _network_server ) ) {
2021-06-07 23:24:37 +02:00
GameInstance : : LoadEmpty ( ) ;
if ( SlIterateArray ( ) ! = - 1 ) SlErrorCorrupt ( " Too many GameScript configs " ) ;
return ;
}
GameConfig * config = GameConfig : : GetConfig ( GameConfig : : SSS_FORCE_GAME ) ;
if ( ! _game_saveload_name . empty ( ) ) {
2023-05-05 21:59:50 +02:00
config - > Change ( _game_saveload_name , _game_saveload_version , false , _game_saveload_is_random ) ;
2011-12-19 21:56:34 +01:00
if ( ! config - > HasScript ( ) ) {
2021-06-07 23:24:37 +02:00
/* No version of the GameScript available that can load the data. Try to load the
* latest version of the GameScript instead . */
2023-05-05 21:59:50 +02:00
config - > Change ( _game_saveload_name , - 1 , false , _game_saveload_is_random ) ;
2021-06-07 23:24:37 +02:00
if ( ! config - > HasScript ( ) ) {
if ( _game_saveload_name . compare ( " %_dummy " ) ! = 0 ) {
Debug ( script , 0 , " The savegame has an GameScript by the name '{}', version {} which is no longer available. " , _game_saveload_name , _game_saveload_version ) ;
Debug ( script , 0 , " This game will continue to run without GameScript. " ) ;
} else {
Debug ( script , 0 , " The savegame had no GameScript available at the time of saving. " ) ;
Debug ( script , 0 , " This game will continue to run without GameScript. " ) ;
}
2011-12-19 21:56:34 +01:00
} else {
2021-06-07 23:24:37 +02:00
Debug ( script , 0 , " The savegame has an GameScript by the name '{}', version {} which is no longer available. " , _game_saveload_name , _game_saveload_version ) ;
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. " ) ;
2011-12-19 21:56:34 +01:00
}
2021-06-07 23:24:37 +02:00
/* Make sure the GameScript doesn't get the saveload data, as it was not the
* writer of the saveload data in the first place */
_game_saveload_version = - 1 ;
2011-12-19 21:56:34 +01:00
}
}
2021-06-07 23:24:37 +02:00
config - > StringToSettings ( _game_saveload_settings ) ;
2011-12-19 21:56:34 +01:00
2022-12-28 05:02:26 +01:00
/* Load the GameScript saved data */
config - > SetToLoadData ( GameInstance : : Load ( _game_saveload_version ) ) ;
2011-12-19 21:56:34 +01:00
2021-06-07 23:24:37 +02:00
if ( SlIterateArray ( ) ! = - 1 ) SlErrorCorrupt ( " Too many GameScript configs " ) ;
}
2011-12-19 21:56:34 +01:00
2021-06-07 23:24:37 +02:00
void Save ( ) const override
{
SlTableHeader ( _game_script_desc ) ;
SlSetArrayIndex ( 0 ) ;
SlAutolength ( ( AutolengthProc * ) SaveReal_GSDT , nullptr ) ;
}
} ;
2011-12-19 21:56:34 +01:00
2011-12-19 22:05:46 +01:00
extern GameStrings * _current_data ;
2020-05-17 23:31:56 +02:00
static std : : string _game_saveload_string ;
2021-06-14 13:32:12 +02:00
static uint32 _game_saveload_strings ;
class SlGameLanguageString : public DefaultSaveLoadHandler < SlGameLanguageString , LanguageStrings > {
public :
inline static const SaveLoad description [ ] = {
2021-06-14 10:05:30 +02:00
SLEG_SSTR ( " string " , _game_saveload_string , SLE_STR | SLF_ALLOW_CONTROL ) ,
2021-06-14 13:32:12 +02:00
} ;
2021-06-07 11:35:21 +02:00
inline const static SaveLoadCompatTable compat_description = _game_language_string_sl_compat ;
2021-06-14 13:32:12 +02:00
void Save ( LanguageStrings * ls ) const override
{
2021-06-06 23:23:12 +02:00
SlSetStructListLength ( ls - > lines . size ( ) ) ;
2021-06-14 13:32:12 +02:00
for ( const auto & string : ls - > lines ) {
_game_saveload_string = string ;
SlObject ( nullptr , this - > GetDescription ( ) ) ;
}
}
2011-12-19 22:05:46 +01:00
2021-06-14 13:32:12 +02:00
void Load ( LanguageStrings * ls ) const override
{
2021-06-06 23:23:12 +02:00
uint32 length = IsSavegameVersionBefore ( SLV_SAVELOAD_LIST_LENGTH ) ? _game_saveload_strings : ( uint32 ) SlGetStructListLength ( UINT32_MAX ) ;
for ( uint32 i = 0 ; i < length ; i + + ) {
2021-06-07 11:35:21 +02:00
SlObject ( nullptr , this - > GetLoadDescription ( ) ) ;
2021-06-14 13:32:12 +02:00
ls - > lines . emplace_back ( _game_saveload_string ) ;
}
}
2011-12-19 22:05:46 +01:00
} ;
2021-06-14 13:32:12 +02:00
static const SaveLoad _game_language_desc [ ] = {
SLE_SSTR ( LanguageStrings , language , SLE_STR ) ,
2021-06-14 10:05:30 +02:00
SLEG_CONDVAR ( " count " , _game_saveload_strings , SLE_UINT32 , SL_MIN_VERSION , SLV_SAVELOAD_LIST_LENGTH ) ,
SLEG_STRUCTLIST ( " strings " , SlGameLanguageString ) ,
2011-12-19 22:05:46 +01:00
} ;
2021-06-07 23:24:37 +02:00
struct GSTRChunkHandler : ChunkHandler {
GSTRChunkHandler ( ) : ChunkHandler ( ' GSTR ' , CH_TABLE ) { }
2011-12-19 22:05:46 +01:00
2021-06-07 23:24:37 +02:00
void Load ( ) const override
{
const std : : vector < SaveLoad > slt = SlCompatTableHeader ( _game_language_desc , _game_language_sl_compat ) ;
2011-12-19 22:05:46 +01:00
2011-12-21 13:40:29 +01:00
delete _current_data ;
2021-06-07 23:24:37 +02:00
_current_data = new GameStrings ( ) ;
2011-12-21 13:40:29 +01:00
2021-06-07 23:24:37 +02:00
while ( SlIterateArray ( ) ! = - 1 ) {
LanguageStrings ls ;
SlObject ( & ls , slt ) ;
_current_data - > raw_strings . push_back ( std : : move ( ls ) ) ;
}
2011-12-19 22:05:46 +01:00
2021-06-07 23:24:37 +02:00
/* If there were no strings in the savegame, set GameStrings to nullptr */
if ( _current_data - > raw_strings . size ( ) = = 0 ) {
delete _current_data ;
_current_data = nullptr ;
return ;
}
_current_data - > Compile ( ) ;
ReconsiderGameScriptLanguage ( ) ;
}
void Save ( ) const override
{
SlTableHeader ( _game_language_desc ) ;
2021-06-07 11:35:21 +02:00
2021-06-07 23:24:37 +02:00
if ( _current_data = = nullptr ) return ;
2011-12-19 22:05:46 +01:00
2021-06-07 23:24:37 +02:00
for ( uint i = 0 ; i < _current_data - > raw_strings . size ( ) ; i + + ) {
SlSetArrayIndex ( i ) ;
SlObject ( & _current_data - > raw_strings [ i ] , _game_language_desc ) ;
}
2011-12-19 22:05:46 +01:00
}
2021-06-07 23:24:37 +02:00
} ;
2011-12-19 22:05:46 +01:00
2021-06-07 23:24:37 +02:00
static const GSTRChunkHandler GSTR ;
static const GSDTChunkHandler GSDT ;
2021-06-09 16:23:35 +02:00
static const ChunkHandlerRef game_chunk_handlers [ ] = {
GSTR ,
GSDT ,
2011-12-19 21:56:34 +01:00
} ;
2021-05-02 22:41:34 +02:00
extern const ChunkHandlerTable _game_chunk_handlers ( game_chunk_handlers ) ;