game_sl.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "../stdafx.h"
00013 #include "../company_base.h"
00014 #include "../debug.h"
00015 #include "saveload.h"
00016 #include "../string_func.h"
00017 
00018 #include "../game/game.hpp"
00019 #include "../game/game_config.hpp"
00020 #include "../network/network.h"
00021 #include "../game/game_instance.hpp"
00022 #include "../game/game_text.hpp"
00023 
00024 static char _game_saveload_name[64];
00025 static int  _game_saveload_version;
00026 static char _game_saveload_settings[1024];
00027 static bool _game_saveload_is_random;
00028 
00029 static const SaveLoad _game_script[] = {
00030       SLEG_STR(_game_saveload_name,        SLE_STRB),
00031       SLEG_STR(_game_saveload_settings,    SLE_STRB),
00032       SLEG_VAR(_game_saveload_version,   SLE_UINT32),
00033       SLEG_VAR(_game_saveload_is_random,   SLE_BOOL),
00034        SLE_END()
00035 };
00036 
00037 static void SaveReal_GSDT(int *index_ptr)
00038 {
00039   GameConfig *config = GameConfig::GetConfig();
00040 
00041   if (config->HasScript()) {
00042     ttd_strlcpy(_game_saveload_name, config->GetName(), lengthof(_game_saveload_name));
00043     _game_saveload_version = config->GetVersion();
00044   } else {
00045     /* No GameScript is configured for this so store an empty string as name. */
00046     _game_saveload_name[0] = '\0';
00047     _game_saveload_version = -1;
00048   }
00049 
00050   _game_saveload_is_random = config->IsRandom();
00051   _game_saveload_settings[0] = '\0';
00052   config->SettingsToString(_game_saveload_settings, lengthof(_game_saveload_settings));
00053 
00054   SlObject(NULL, _game_script);
00055   Game::Save();
00056 }
00057 
00058 static void Load_GSDT()
00059 {
00060   /* Free all current data */
00061   GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(NULL);
00062 
00063   if ((CompanyID)SlIterateArray() == (CompanyID)-1) return;
00064 
00065   _game_saveload_version = -1;
00066   SlObject(NULL, _game_script);
00067 
00068   if (_networking && !_network_server) {
00069     GameInstance::LoadEmpty();
00070     if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
00071     return;
00072   }
00073 
00074   GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
00075   if (StrEmpty(_game_saveload_name)) {
00076   } else {
00077     config->Change(_game_saveload_name, _game_saveload_version, false, _game_saveload_is_random);
00078     if (!config->HasScript()) {
00079       /* No version of the GameScript available that can load the data. Try to load the
00080         * latest version of the GameScript instead. */
00081       config->Change(_game_saveload_name, -1, false, _game_saveload_is_random);
00082       if (!config->HasScript()) {
00083         if (strcmp(_game_saveload_name, "%_dummy") != 0) {
00084           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);
00085           DEBUG(script, 0, "This game wil continue to run without GameScript.");
00086         } else {
00087           DEBUG(script, 0, "The savegame had no GameScript available at the time of saving.");
00088           DEBUG(script, 0, "This game wil continue to run without GameScript.");
00089         }
00090       } else {
00091         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);
00092         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.");
00093       }
00094       /* Make sure the GameScript doesn't get the saveload data, as he was not the
00095         *  writer of the saveload data in the first place */
00096       _game_saveload_version = -1;
00097     }
00098   }
00099 
00100   config->StringToSettings(_game_saveload_settings);
00101 
00102   /* Start the GameScript directly if it was active in the savegame */
00103   Game::StartNew();
00104   Game::Load(_game_saveload_version);
00105 
00106   if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
00107 }
00108 
00109 static void Save_GSDT()
00110 {
00111   SlSetArrayIndex(0);
00112   SlAutolength((AutolengthProc *)SaveReal_GSDT, NULL);
00113 }
00114 
00115 extern GameStrings *_current_data;
00116 
00117 static const char *_game_saveload_string;
00118 static uint _game_saveload_strings;
00119 
00120 static const SaveLoad _game_language_header[] = {
00121   SLEG_STR(_game_saveload_string, SLE_STR),
00122   SLEG_VAR(_game_saveload_strings, SLE_UINT32),
00123    SLE_END()
00124 };
00125 
00126 static const SaveLoad _game_language_string[] = {
00127   SLEG_STR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
00128    SLE_END()
00129 };
00130 
00131 static void SaveReal_GSTR(LanguageStrings *ls)
00132 {
00133   _game_saveload_string  = ls->language;
00134   _game_saveload_strings = ls->lines.Length();
00135 
00136   SlObject(NULL, _game_language_header);
00137   for (uint i = 0; i < _game_saveload_strings; i++) {
00138     _game_saveload_string = ls->lines[i];
00139     SlObject(NULL, _game_language_string);
00140   }
00141 }
00142 
00143 static void Load_GSTR()
00144 {
00145   delete _current_data;
00146   _current_data = new GameStrings();
00147 
00148   while (SlIterateArray() != -1) {
00149     _game_saveload_string = NULL;
00150     SlObject(NULL, _game_language_header);
00151 
00152     LanguageStrings *ls = new LanguageStrings(_game_saveload_string);
00153     for (uint i = 0; i < _game_saveload_strings; i++) {
00154       SlObject(NULL, _game_language_string);
00155       *ls->lines.Append() = strdup(_game_saveload_string);
00156     }
00157 
00158     *_current_data->raw_strings.Append() = ls;
00159   }
00160 
00161   /* If there were no strings in the savegame, set GameStrings to NULL */
00162   if (_current_data->raw_strings.Length() == 0) {
00163     delete _current_data;
00164     _current_data = NULL;
00165     return;
00166   }
00167 
00168   _current_data->Compile();
00169   ReconsiderGameScriptLanguage();
00170 }
00171 
00172 static void Save_GSTR()
00173 {
00174   if (_current_data == NULL) return;
00175 
00176   for (uint i = 0; i < _current_data->raw_strings.Length(); i++) {
00177     SlSetArrayIndex(i);
00178     SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i]);
00179   }
00180 }
00181 
00182 extern const ChunkHandler _game_chunk_handlers[] = {
00183   { 'GSTR', Save_GSTR, Load_GSTR, NULL, NULL, CH_ARRAY },
00184   { 'GSDT', Save_GSDT, Load_GSDT, NULL, NULL, CH_ARRAY | CH_LAST},
00185 };