1
0
Fork 0

Change: [Script] Save exact version selected in savegames

pull/13565/head
SamuXarick 2025-02-17 22:03:18 +00:00
parent dfa5a7eb80
commit 6ee9712d49
5 changed files with 89 additions and 41 deletions

View File

@ -27,18 +27,21 @@ static std::string _ai_saveload_name;
static int _ai_saveload_version; static int _ai_saveload_version;
static std::string _ai_saveload_settings; static std::string _ai_saveload_settings;
static bool _ai_saveload_is_random; static bool _ai_saveload_is_random;
static bool _ai_saveload_force_exact_match;
static const SaveLoad _ai_company_desc[] = { static const SaveLoad _ai_company_desc[] = {
SLEG_SSTR("name", _ai_saveload_name, SLE_STR), SLEG_SSTR("name", _ai_saveload_name, SLE_STR),
SLEG_SSTR("settings", _ai_saveload_settings, SLE_STR), SLEG_SSTR("settings", _ai_saveload_settings, SLE_STR),
SLEG_CONDVAR("version", _ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION), SLEG_CONDVAR("version", _ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION),
SLEG_CONDVAR("is_random", _ai_saveload_is_random, SLE_BOOL, SLV_136, SLV_AI_LOCAL_CONFIG), SLEG_CONDVAR("is_random", _ai_saveload_is_random, SLE_BOOL, SLV_136, SLV_AI_LOCAL_CONFIG),
SLEG_CONDVAR("force_exact_match", _ai_saveload_force_exact_match, SLE_BOOL, SLV_SCRIPT_FORCE_EXACT_MATCH, SL_MAX_VERSION),
}; };
static const SaveLoad _ai_running_desc[] = { static const SaveLoad _ai_running_desc[] = {
SLEG_CONDSSTR("running_name", _ai_saveload_name, SLE_STR, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION), SLEG_CONDSSTR("running_name", _ai_saveload_name, SLE_STR, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION),
SLEG_CONDSSTR("running_settings", _ai_saveload_settings, SLE_STR, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION), SLEG_CONDSSTR("running_settings", _ai_saveload_settings, SLE_STR, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION),
SLEG_CONDVAR("running_version", _ai_saveload_version, SLE_UINT32, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION), SLEG_CONDVAR("running_version", _ai_saveload_version, SLE_UINT32, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION),
SLEG_CONDVAR("running_force_exact_match", _ai_saveload_force_exact_match, SLE_BOOL, SLV_SCRIPT_FORCE_EXACT_MATCH, SL_MAX_VERSION),
}; };
static void SaveReal_AIPL(int arg) static void SaveReal_AIPL(int arg)
@ -56,6 +59,7 @@ static void SaveReal_AIPL(int arg)
} }
_ai_saveload_settings = config->SettingsToString(); _ai_saveload_settings = config->SettingsToString();
_ai_saveload_force_exact_match = config->GetForceExactMatch();
SlObject(nullptr, _ai_company_desc); SlObject(nullptr, _ai_company_desc);
@ -66,10 +70,10 @@ static void SaveReal_AIPL(int arg)
_ai_saveload_name = config->GetName(); _ai_saveload_name = config->GetName();
_ai_saveload_version = config->GetVersion(); _ai_saveload_version = config->GetVersion();
_ai_saveload_settings = config->SettingsToString(); _ai_saveload_settings = config->SettingsToString();
_ai_saveload_force_exact_match = config->GetForceExactMatch();
SlObject(nullptr, _ai_running_desc); SlObject(nullptr, _ai_running_desc);
AI::Save(index); AI::Save(index);
} }
struct AIPLChunkHandler : ChunkHandler { struct AIPLChunkHandler : ChunkHandler {
@ -90,6 +94,7 @@ struct AIPLChunkHandler : ChunkHandler {
_ai_saveload_is_random = false; _ai_saveload_is_random = false;
_ai_saveload_version = -1; _ai_saveload_version = -1;
_ai_saveload_force_exact_match = false;
SlObject(nullptr, slt); SlObject(nullptr, slt);
if (_game_mode == GM_MENU || (_networking && !_network_server)) { if (_game_mode == GM_MENU || (_networking && !_network_server)) {
@ -105,6 +110,10 @@ struct AIPLChunkHandler : ChunkHandler {
/* A random AI. */ /* A random AI. */
config->Change(std::nullopt, -1, false); config->Change(std::nullopt, -1, false);
} else { } else {
if (_ai_saveload_force_exact_match) config->Change(_ai_saveload_name, _ai_saveload_version, true);
if (!config->HasScript()) {
/* Exact version of the AI is not available. Try to
* configure the highest compatible version. */
config->Change(_ai_saveload_name, _ai_saveload_version, false); config->Change(_ai_saveload_name, _ai_saveload_version, false);
if (!config->HasScript()) { if (!config->HasScript()) {
/* No version of the AI available. Try to configure the /* No version of the AI available. Try to configure the
@ -112,12 +121,16 @@ struct AIPLChunkHandler : ChunkHandler {
config->Change(_ai_saveload_name, -1, false); config->Change(_ai_saveload_name, -1, false);
if (!config->HasScript()) { if (!config->HasScript()) {
if (_ai_saveload_name.compare("%_dummy") != 0) { if (_ai_saveload_name.compare("%_dummy") != 0) {
Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); Debug(script, 0, "The savegame has an AI by the name '{}', {}version {} which is no longer available.", _ai_saveload_name, _ai_saveload_force_exact_match ? "forcing " : "", _ai_saveload_version);
Debug(script, 0, "Configuration switched to Random AI."); Debug(script, 0, "Configuration switched to Random AI.");
} }
} else { } else {
Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); Debug(script, 0, "The savegame has an AI by the name '{}', {}version {} which is no longer available.", _ai_saveload_name, _ai_saveload_force_exact_match ? "forcing " : "", _ai_saveload_version);
Debug(script, 0, "The latest version of that AI has been configured instead"); Debug(script, 0, "The latest version of that AI has been configured instead.");
}
} else if (_ai_saveload_force_exact_match) {
Debug(script, 0, "The savegame has an AI by the name '{}', forcing version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
Debug(script, 0, "The highest compatible version of that AI has been configured instead.");
} }
} }
} }
@ -130,6 +143,10 @@ struct AIPLChunkHandler : ChunkHandler {
Company::Get(index)->ai_config = std::make_unique<AIConfig>(); Company::Get(index)->ai_config = std::make_unique<AIConfig>();
config = Company::Get(index)->ai_config.get(); config = Company::Get(index)->ai_config.get();
if (_ai_saveload_force_exact_match) config->Change(_ai_saveload_name, _ai_saveload_version, true);
if (!config->HasScript()) {
/* Exact version of the AI is not available. Try to load the highest
* compatible version of the AI instead that can load the data. */
config->Change(_ai_saveload_name, _ai_saveload_version, false); config->Change(_ai_saveload_name, _ai_saveload_version, false);
if (!config->HasScript()) { if (!config->HasScript()) {
/* No version of the AI available that can load the data. Try to load the /* No version of the AI available that can load the data. Try to load the
@ -137,19 +154,23 @@ struct AIPLChunkHandler : ChunkHandler {
config->Change(_ai_saveload_name, -1, false); config->Change(_ai_saveload_name, -1, false);
if (!config->HasScript()) { if (!config->HasScript()) {
if (_ai_saveload_name.compare("%_dummy") != 0) { if (_ai_saveload_name.compare("%_dummy") != 0) {
Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); Debug(script, 0, "The savegame has an AI by the name '{}', {}version {} which is no longer available.", _ai_saveload_name, _ai_saveload_force_exact_match ? "forcing " : "", _ai_saveload_version);
Debug(script, 0, "A random other AI will be loaded in its place."); Debug(script, 0, "A random other AI will be loaded in its place.");
} else { } else {
Debug(script, 0, "The savegame had no AIs available at the time of saving."); Debug(script, 0, "The savegame had no AIs available at the time of saving.");
Debug(script, 0, "A random available AI will be loaded now."); Debug(script, 0, "A random available AI will be loaded now.");
} }
} else { } else {
Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); Debug(script, 0, "The savegame has an AI by the name '{}', {}version {} which is no longer available.", _ai_saveload_name, _ai_saveload_force_exact_match ? "forcing " : "", _ai_saveload_version);
Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible."); Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
} }
/* Make sure the AI doesn't get the saveload data, as it was not the /* Make sure the AI doesn't get the saveload data, as it was not the
* writer of the saveload data in the first place */ * writer of the saveload data in the first place */
_ai_saveload_version = -1; _ai_saveload_version = -1;
} else if (_ai_saveload_force_exact_match) {
Debug(script, 0, "The savegame has an AI by the name '{}', forcing version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
Debug(script, 0, "The highest compatible version of that AI has been loaded instead.");
}
} }
config->StringToSettings(_ai_saveload_settings); config->StringToSettings(_ai_saveload_settings);
config->SetToLoadData(AIInstance::Load(_ai_saveload_version)); config->SetToLoadData(AIInstance::Load(_ai_saveload_version));

View File

@ -25,11 +25,13 @@
static std::string _game_saveload_name; static std::string _game_saveload_name;
static int _game_saveload_version; static int _game_saveload_version;
static std::string _game_saveload_settings; static std::string _game_saveload_settings;
static bool _game_saveload_force_exact_match;
static const SaveLoad _game_script_desc[] = { static const SaveLoad _game_script_desc[] = {
SLEG_SSTR("name", _game_saveload_name, SLE_STR), SLEG_SSTR("name", _game_saveload_name, SLE_STR),
SLEG_SSTR("settings", _game_saveload_settings, SLE_STR), SLEG_SSTR("settings", _game_saveload_settings, SLE_STR),
SLEG_VAR("version", _game_saveload_version, SLE_UINT32), SLEG_VAR("version", _game_saveload_version, SLE_UINT32),
SLEG_CONDVAR("force_exact_match", _game_saveload_force_exact_match, SLE_BOOL, SLV_SCRIPT_FORCE_EXACT_MATCH, SL_MAX_VERSION),
}; };
static void SaveReal_GSDT(int) static void SaveReal_GSDT(int)
@ -46,6 +48,7 @@ static void SaveReal_GSDT(int)
} }
_game_saveload_settings = config->SettingsToString(); _game_saveload_settings = config->SettingsToString();
_game_saveload_force_exact_match = config->GetForceExactMatch();
SlObject(nullptr, _game_script_desc); SlObject(nullptr, _game_script_desc);
Game::Save(); Game::Save();
@ -64,6 +67,7 @@ struct GSDTChunkHandler : ChunkHandler {
if (SlIterateArray() == -1) return; if (SlIterateArray() == -1) return;
_game_saveload_version = -1; _game_saveload_version = -1;
_game_saveload_force_exact_match = false;
SlObject(nullptr, slt); SlObject(nullptr, slt);
if (_game_mode == GM_MENU || (_networking && !_network_server)) { if (_game_mode == GM_MENU || (_networking && !_network_server)) {
@ -74,6 +78,10 @@ struct GSDTChunkHandler : ChunkHandler {
GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME); GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
if (!_game_saveload_name.empty()) { if (!_game_saveload_name.empty()) {
if (_game_saveload_force_exact_match) config->Change(_game_saveload_name, _game_saveload_version, true);
if (!config->HasScript()) {
/* Exact version of the GameScript is not available. Try to load the highest
* compatible version of the AI instead that can load the data. */
config->Change(_game_saveload_name, _game_saveload_version, false); config->Change(_game_saveload_name, _game_saveload_version, false);
if (!config->HasScript()) { if (!config->HasScript()) {
/* No version of the GameScript available that can load the data. Try to load the /* No version of the GameScript available that can load the data. Try to load the
@ -81,19 +89,23 @@ struct GSDTChunkHandler : ChunkHandler {
config->Change(_game_saveload_name, -1, false); config->Change(_game_saveload_name, -1, false);
if (!config->HasScript()) { if (!config->HasScript()) {
if (_game_saveload_name.compare("%_dummy") != 0) { 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, "The savegame has a GameScript by the name '{}', {}version {} which is no longer available.", _game_saveload_name, _game_saveload_force_exact_match ? "forcing " : "", _game_saveload_version);
Debug(script, 0, "This game will continue to run without GameScript."); Debug(script, 0, "This game will continue to run without GameScript.");
} else { } else {
Debug(script, 0, "The savegame had no GameScript available at the time of saving."); 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."); Debug(script, 0, "This game will continue to run without GameScript.");
} }
} else { } else {
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 savegame has a GameScript by the name '{}', {}version {} which is no longer available.", _game_saveload_name, _game_saveload_force_exact_match ? "forcing " : "", _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."); 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 it was not the /* Make sure the GameScript doesn't get the saveload data, as it was not the
* writer of the saveload data in the first place */ * writer of the saveload data in the first place */
_game_saveload_version = -1; _game_saveload_version = -1;
} else if (_game_saveload_force_exact_match) {
Debug(script, 0, "The savegame has a GameScript by the name '{}', forcing version {} which is no longer available.", _game_saveload_name, _game_saveload_version);
Debug(script, 0, "The highest compatible version of that GameScript has been loaded instead.");
}
} }
} }

View File

@ -403,6 +403,8 @@ enum SaveLoadVersion : uint16_t {
SLV_FIX_SCC_ENCODED_NEGATIVE, ///< 353 PR#14049 Fix encoding of negative parameters. SLV_FIX_SCC_ENCODED_NEGATIVE, ///< 353 PR#14049 Fix encoding of negative parameters.
SLV_ORDERS_OWNED_BY_ORDERLIST, ///< 354 PR#13948 Orders stored in OrderList, pool removed. SLV_ORDERS_OWNED_BY_ORDERLIST, ///< 354 PR#13948 Orders stored in OrderList, pool removed.
SLV_SCRIPT_FORCE_EXACT_MATCH, ///< 355 PR#13565 Store script force exact match in savegames.
SL_MAX_VERSION, ///< Highest possible saveload version SL_MAX_VERSION, ///< Highest possible saveload version
}; };

View File

@ -29,6 +29,7 @@ void ScriptConfig::Change(std::optional<std::string_view> name, int version, boo
this->info = nullptr; this->info = nullptr;
} }
this->version = (info == nullptr) ? -1 : info->GetVersion(); this->version = (info == nullptr) ? -1 : info->GetVersion();
this->force_exact_match = (info == nullptr) ? false : force_exact_match;
this->config_list.reset(); this->config_list.reset();
this->to_load_data.reset(); this->to_load_data.reset();
@ -40,6 +41,7 @@ ScriptConfig::ScriptConfig(const ScriptConfig &config)
this->name = config.name; this->name = config.name;
this->info = config.info; this->info = config.info;
this->version = config.version; this->version = config.version;
this->force_exact_match = config.force_exact_match;
this->to_load_data.reset(); this->to_load_data.reset();
for (const auto &item : config.settings) { for (const auto &item : config.settings) {
@ -140,6 +142,11 @@ int ScriptConfig::GetVersion() const
return this->version; return this->version;
} }
bool ScriptConfig::GetForceExactMatch() const
{
return this->force_exact_match;
}
void ScriptConfig::StringToSettings(std::string_view value) void ScriptConfig::StringToSettings(std::string_view value)
{ {
std::string_view to_process = value; std::string_view to_process = value;

View File

@ -150,6 +150,11 @@ public:
*/ */
int GetVersion() const; int GetVersion() const;
/**
* Whether the config is forcing the exact version of the Script?
*/
bool GetForceExactMatch() const;
/** /**
* Convert a string which is stored in the config file or savegames to * Convert a string which is stored in the config file or savegames to
* custom settings of this Script. * custom settings of this Script.
@ -176,6 +181,7 @@ public:
protected: protected:
std::string name; ///< Name of the Script std::string name; ///< Name of the Script
int version; ///< Version of the Script int version; ///< Version of the Script
bool force_exact_match; ///< Force exact match for the version
class ScriptInfo *info; ///< ScriptInfo object for related to this Script version class ScriptInfo *info; ///< ScriptInfo object for related to this Script version
SettingValueList settings; ///< List with all setting=>value pairs that are configure for this Script SettingValueList settings; ///< List with all setting=>value pairs that are configure for this Script
std::unique_ptr<ScriptConfigItemList> config_list; ///< List with all settings defined by this Script std::unique_ptr<ScriptConfigItemList> config_list; ///< List with all settings defined by this Script