# HG changeset patch # User truebrain # Date 2011-12-19 20:56:34 # Node ID 3a554214098dbbb3790296359f08b8d68a790eea # Parent f99c3a48f01347d7a4246de638c7b67ec6187635 (svn r23609) -Add: save/load all GameScript related material diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -779,6 +779,7 @@ + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -1563,6 +1563,9 @@ Save/Load handlers + + Save/Load handlers + Save/Load handlers diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -2411,6 +2411,10 @@ > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -2408,6 +2408,10 @@ > + + diff --git a/source.list b/source.list --- a/source.list +++ b/source.list @@ -537,6 +537,7 @@ saveload/company_sl.cpp saveload/depot_sl.cpp saveload/economy_sl.cpp saveload/engine_sl.cpp +saveload/game_sl.cpp saveload/gamelog_sl.cpp saveload/group_sl.cpp saveload/industry_sl.cpp diff --git a/src/game/game.hpp b/src/game/game.hpp --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -34,6 +34,11 @@ public: static void Initialize(); /** + * Start up a new GameScript. + */ + static void StartNew(); + + /** * Uninitialize the Game system. */ static void Uninitialize(bool keepConfig); @@ -51,6 +56,16 @@ public: static void Rescan(); static void ResetConfig(); + /** + * Save data from a GameScript to a savegame. + */ + static void Save(); + + /** + * Load data for a GameScript from a savegame. + */ + static void Load(int version); + /** Wrapper function for GameScanner::GetConsoleList */ static char *GetConsoleList(char *p, const char *last, bool newest_only = false); /** Wrapper function for GameScanner::GetInfoList */ diff --git a/src/game/game_core.cpp b/src/game/game_core.cpp --- a/src/game/game_core.cpp +++ b/src/game/game_core.cpp @@ -57,26 +57,29 @@ Game::scanner = new GameScannerInfo(); Game::scanner->Initialize(); } +} - if (Game::instance == NULL) { - /* Clients shouldn't start GameScripts */ - if (_networking && !_network_server) return; +/* static */ void Game::StartNew() +{ + if (Game::instance != NULL) return; - GameConfig *config = GameConfig::GetConfig(); - GameInfo *info = config->GetInfo(); - if (info == NULL) return; + /* Clients shouldn't start GameScripts */ + if (_networking && !_network_server) return; - Backup cur_company(_current_company, FILE_LINE); - cur_company.Change(OWNER_DEITY); + GameConfig *config = GameConfig::GetConfig(); + GameInfo *info = config->GetInfo(); + if (info == NULL) return; + + Backup cur_company(_current_company, FILE_LINE); + cur_company.Change(OWNER_DEITY); - Game::info = info; - Game::instance = new GameInstance(); - Game::instance->Initialize(info); + Game::info = info; + Game::instance = new GameInstance(); + Game::instance->Initialize(info); - cur_company.Restore(); + cur_company.Restore(); - InvalidateWindowData(WC_AI_DEBUG, 0, -1); - } + InvalidateWindowData(WC_AI_DEBUG, 0, -1); } /* static */ void Game::Uninitialize(bool keepConfig) @@ -138,6 +141,29 @@ } +/* static */ void Game::Save() +{ + if (Game::instance != NULL && (!_networking || _network_server)) { + Backup cur_company(_current_company, OWNER_DEITY, FILE_LINE); + Game::instance->Save(); + cur_company.Restore(); + } else { + GameInstance::SaveEmpty(); + } +} + +/* static */ void Game::Load(int version) +{ + if (Game::instance != NULL && (!_networking || _network_server)) { + Backup cur_company(_current_company, OWNER_DEITY, FILE_LINE); + Game::instance->Load(version); + cur_company.Restore(); + } else { + /* Read, but ignore, the load data */ + GameInstance::LoadEmpty(); + } +} + /* static */ char *Game::GetConsoleList(char *p, const char *last, bool newest_only) { return Game::scanner->GetConsoleList(p, last, newest_only); diff --git a/src/genworld.cpp b/src/genworld.cpp --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -33,6 +33,7 @@ #include "core/backup_type.hpp" #include "progress.h" #include "error.h" +#include "game/game.hpp" #include "table/sprites.h" @@ -162,6 +163,10 @@ static void _GenerateWorld(void *) RunTileLoop(); IncreaseGeneratingWorldProgress(GWP_RUNTILELOOP); } + + if (_game_mode != GM_EDITOR) { + Game::StartNew(); + } } ResetObjectToPlace(); diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp new file mode 100644 --- /dev/null +++ b/src/saveload/game_sl.cpp @@ -0,0 +1,116 @@ +/* $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 "../company_base.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" + +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()) { + ttd_strlcpy(_game_saveload_name, config->GetName(), lengthof(_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, lengthof(_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 wil 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 wil 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 const ChunkHandler _game_chunk_handlers[] = { + { 'GSDT', Save_GSDT, Load_GSDT, NULL, NULL, CH_ARRAY | CH_LAST}, +}; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -403,6 +403,7 @@ extern const ChunkHandler _industry_chun extern const ChunkHandler _economy_chunk_handlers[]; extern const ChunkHandler _subsidy_chunk_handlers[]; extern const ChunkHandler _ai_chunk_handlers[]; +extern const ChunkHandler _game_chunk_handlers[]; extern const ChunkHandler _animated_tile_chunk_handlers[]; extern const ChunkHandler _newgrf_chunk_handlers[]; extern const ChunkHandler _group_chunk_handlers[]; @@ -434,6 +435,7 @@ static const ChunkHandler * const _chunk _station_chunk_handlers, _company_chunk_handlers, _ai_chunk_handlers, + _game_chunk_handlers, _animated_tile_chunk_handlers, _newgrf_chunk_handlers, _group_chunk_handlers, diff --git a/src/settings.cpp b/src/settings.cpp --- a/src/settings.cpp +++ b/src/settings.cpp @@ -57,6 +57,8 @@ #include "ini_type.h" #include "ai/ai_config.hpp" #include "ai/ai.hpp" +#include "game/game_config.hpp" +#include "game/game.hpp" #include "ship.h" #include "smallmap_gui.h" #include "roadveh.h" @@ -1362,6 +1364,32 @@ static void AILoadConfig(IniFile *ini, c } } +static void GameLoadConfig(IniFile *ini, const char *grpname) +{ + IniGroup *group = ini->GetGroup(grpname); + IniItem *item; + + /* Clean any configured GameScript */ + GameConfig::GetConfig(GameConfig::SSS_FORCE_NEWGAME)->Change(NULL); + + /* If no group exists, return */ + if (group == NULL) return; + + item = group->item; + if (item == NULL) return; + + GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME); + + config->Change(item->name); + if (!config->HasScript()) { + if (strcmp(item->name, "none") != 0) { + DEBUG(script, 0, "The GameScript by the name '%s' was no longer found, and removed from the list.", item->name); + return; + } + } + if (item->value != NULL) config->StringToSettings(item->value); +} + /** * Load a GRF configuration * @param ini The configuration to read from. @@ -1480,6 +1508,28 @@ static void AISaveConfig(IniFile *ini, c } } +static void GameSaveConfig(IniFile *ini, const char *grpname) +{ + IniGroup *group = ini->GetGroup(grpname); + + if (group == NULL) return; + group->Clear(); + + GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME); + const char *name; + char value[1024]; + config->SettingsToString(value, lengthof(value)); + + if (config->HasScript()) { + name = config->GetName(); + } else { + name = "none"; + } + + IniItem *item = new IniItem(group, name, strlen(name)); + item->SetValue(value); +} + /** * Save the version of OpenTTD to the ini file. * @param ini the ini to write to @@ -1563,6 +1613,7 @@ void LoadFromConfig(bool minimal) _grfconfig_static = GRFLoadConfig(ini, "newgrf-static", true); NewsDisplayLoadConfig(ini, "news_display"); AILoadConfig(ini, "ai_players"); + GameLoadConfig(ini, "game_scripts"); PrepareOldDiffCustom(); IniLoadSettings(ini, _gameopt_settings, "gameopt", &_settings_newgame); @@ -1589,6 +1640,7 @@ void SaveToConfig() GRFSaveConfig(ini, "newgrf-static", _grfconfig_static); NewsDisplaySaveConfig(ini, "news_display"); AISaveConfig(ini, "ai_players"); + GameSaveConfig(ini, "game_scripts"); SaveVersionInConfig(ini); ini->SaveToDisk(_config_file); delete ini;