changeset 18761:4dd550271df9 draft

(svn r23609) -Add: save/load all GameScript related material
author truebrain <truebrain@openttd.org>
date Mon, 19 Dec 2011 20:56:34 +0000
parents 09d980ab252e
children c426221fa1a3
files projects/openttd_vs100.vcxproj projects/openttd_vs100.vcxproj.filters projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/game/game.hpp src/game/game_core.cpp src/genworld.cpp src/saveload/game_sl.cpp src/saveload/saveload.cpp src/settings.cpp
diffstat 11 files changed, 243 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -779,6 +779,7 @@
     <ClCompile Include="..\src\saveload\depot_sl.cpp" />
     <ClCompile Include="..\src\saveload\economy_sl.cpp" />
     <ClCompile Include="..\src\saveload\engine_sl.cpp" />
+    <ClCompile Include="..\src\saveload\game_sl.cpp" />
     <ClCompile Include="..\src\saveload\gamelog_sl.cpp" />
     <ClCompile Include="..\src\saveload\group_sl.cpp" />
     <ClCompile Include="..\src\saveload\industry_sl.cpp" />
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -1563,6 +1563,9 @@
     <ClCompile Include="..\src\saveload\engine_sl.cpp">
       <Filter>Save/Load handlers</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\saveload\game_sl.cpp">
+      <Filter>Save/Load handlers</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\saveload\gamelog_sl.cpp">
       <Filter>Save/Load handlers</Filter>
     </ClCompile>
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -2411,6 +2411,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\saveload\game_sl.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\saveload\gamelog_sl.cpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -2408,6 +2408,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\saveload\game_sl.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\saveload\gamelog_sl.cpp"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -537,6 +537,7 @@
 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
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -34,6 +34,11 @@
 	static void Initialize();
 
 	/**
+	 * Start up a new GameScript.
+	 */
+	static void StartNew();
+
+	/**
 	 * Uninitialize the Game system.
 	 */
 	static void Uninitialize(bool keepConfig);
@@ -51,6 +56,16 @@
 	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 */
--- 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<CompanyByte> cur_company(_current_company, FILE_LINE);
-		cur_company.Change(OWNER_DEITY);
+	GameConfig *config = GameConfig::GetConfig();
+	GameInfo *info = config->GetInfo();
+	if (info == NULL) return;
+
+	Backup<CompanyByte> 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<CompanyByte> 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<CompanyByte> 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);
--- 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 @@
 				RunTileLoop();
 				IncreaseGeneratingWorldProgress(GWP_RUNTILELOOP);
 			}
+
+			if (_game_mode != GM_EDITOR) {
+				Game::StartNew();
+			}
 		}
 
 		ResetObjectToPlace();
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 <http://www.gnu.org/licenses/>.
+ */
+
+/** @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},
+};
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -403,6 +403,7 @@
 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 @@
 	_station_chunk_handlers,
 	_company_chunk_handlers,
 	_ai_chunk_handlers,
+	_game_chunk_handlers,
 	_animated_tile_chunk_handlers,
 	_newgrf_chunk_handlers,
 	_group_chunk_handlers,
--- 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 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 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 @@
 		_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 @@
 	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;