/* $Id$ */ /* * 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 . */ /** @file game_sl.cpp Handles the saveload part of the GameScripts */ #include "../stdafx.h" #include "../debug.h" #include "saveload.h" #include "../string_func.h" #include "../game/game.hpp" #include "../game/game_config.hpp" #include "../network/network.h" #include "../game/game_instance.hpp" #include "../game/game_text.hpp" #include "../safeguards.h" static char _game_saveload_name[64]; static int _game_saveload_version; static char _game_saveload_settings[1024]; static bool _game_saveload_is_random; static const SaveLoad _game_script[] = { SLEG_STR(_game_saveload_name, SLE_STRB), SLEG_STR(_game_saveload_settings, SLE_STRB), SLEG_VAR(_game_saveload_version, SLE_UINT32), SLEG_VAR(_game_saveload_is_random, SLE_BOOL), SLE_END() }; static void SaveReal_GSDT(int *index_ptr) { GameConfig *config = GameConfig::GetConfig(); if (config->HasScript()) { strecpy(_game_saveload_name, config->GetName(), lastof(_game_saveload_name)); _game_saveload_version = config->GetVersion(); } else { /* No GameScript is configured for this so store an empty string as name. */ _game_saveload_name[0] = '\0'; _game_saveload_version = -1; } _game_saveload_is_random = config->IsRandom(); _game_saveload_settings[0] = '\0'; config->SettingsToString(_game_saveload_settings, lastof(_game_saveload_settings)); SlObject(NULL, _game_script); Game::Save(); } static void Load_GSDT() { /* Free all current data */ GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(NULL); if ((CompanyID)SlIterateArray() == (CompanyID)-1) return; _game_saveload_version = -1; SlObject(NULL, _game_script); if (_networking && !_network_server) { GameInstance::LoadEmpty(); if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs"); return; } GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME); if (StrEmpty(_game_saveload_name)) { } else { config->Change(_game_saveload_name, _game_saveload_version, false, _game_saveload_is_random); if (!config->HasScript()) { /* No version of the GameScript available that can load the data. Try to load the * latest version of the GameScript instead. */ config->Change(_game_saveload_name, -1, false, _game_saveload_is_random); if (!config->HasScript()) { if (strcmp(_game_saveload_name, "%_dummy") != 0) { 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); 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."); } } else { 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); 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."); } /* Make sure the GameScript doesn't get the saveload data, as he was not the * writer of the saveload data in the first place */ _game_saveload_version = -1; } } config->StringToSettings(_game_saveload_settings); /* Start the GameScript directly if it was active in the savegame */ Game::StartNew(); Game::Load(_game_saveload_version); if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs"); } static void Save_GSDT() { SlSetArrayIndex(0); SlAutolength((AutolengthProc *)SaveReal_GSDT, NULL); } extern GameStrings *_current_data; static const char *_game_saveload_string; static uint _game_saveload_strings; static const SaveLoad _game_language_header[] = { SLEG_STR(_game_saveload_string, SLE_STR), SLEG_VAR(_game_saveload_strings, SLE_UINT32), SLE_END() }; static const SaveLoad _game_language_string[] = { SLEG_STR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL), SLE_END() }; static void SaveReal_GSTR(LanguageStrings *ls) { _game_saveload_string = ls->language; _game_saveload_strings = ls->lines.Length(); SlObject(NULL, _game_language_header); for (uint i = 0; i < _game_saveload_strings; i++) { _game_saveload_string = ls->lines[i]; SlObject(NULL, _game_language_string); } } static void Load_GSTR() { delete _current_data; _current_data = new GameStrings(); while (SlIterateArray() != -1) { _game_saveload_string = NULL; SlObject(NULL, _game_language_header); LanguageStrings *ls = new LanguageStrings(_game_saveload_string != NULL ? _game_saveload_string : ""); for (uint i = 0; i < _game_saveload_strings; i++) { SlObject(NULL, _game_language_string); *ls->lines.Append() = stredup(_game_saveload_string != NULL ? _game_saveload_string : ""); } *_current_data->raw_strings.Append() = ls; } /* If there were no strings in the savegame, set GameStrings to NULL */ if (_current_data->raw_strings.Length() == 0) { delete _current_data; _current_data = NULL; return; } _current_data->Compile(); ReconsiderGameScriptLanguage(); } static void Save_GSTR() { if (_current_data == NULL) return; for (uint i = 0; i < _current_data->raw_strings.Length(); i++) { SlSetArrayIndex(i); SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i]); } } extern const ChunkHandler _game_chunk_handlers[] = { { 'GSTR', Save_GSTR, Load_GSTR, NULL, NULL, CH_ARRAY }, { 'GSDT', Save_GSDT, Load_GSDT, NULL, NULL, CH_ARRAY | CH_LAST}, };