Project

General

Profile

Feature #716 ยป 0043-Drop-FREECIV_DEV_SAVE_COMPAT_3_2.patch

Marko Lindqvist, 06/09/2024 11:42 PM

View differences:

configure.ac
[AC_DEFINE([FREECIV_DEV_SAVE_COMPAT], [1],
[Development version save game compatibility])
AC_DEFINE([FREECIV_DEV_SAVE_COMPAT_3_3], [1],
[Development version save game compatibility - 3.3 development])
AC_DEFINE([FREECIV_DEV_SAVE_COMPAT_3_2], [1],
[Development version save game compatibility - 3.2 development])])
[Development version save game compatibility - 3.3 development])])
AC_ARG_ENABLE([patient-connect],
AS_HELP_STRING([--enable-patient-connect=yes/no],
gen_headers/meson_fc_config.h.in
#ifdef FREECIV_DEV_SAVE_COMPAT
/* Current development versions */
#define FREECIV_DEV_SAVE_COMPAT_3_3
#define FREECIV_DEV_SAVE_COMPAT_3_2
#endif /* FREECIV_DEV_SAVE_COMPAT */
/* Have magickwand mapimg toolkit */
server/savegame/savecompat.c
sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
"No save version found");
#ifdef FREECIV_DEV_SAVE_COMPAT_3_2
if (game_version < 3019100) {
/* Before version number bump to 3.1.91 */
int i;
int count;
/* Older savegames had a bug that got_tech_multi was not saved.
* Insert the entry to such savegames */
/* May be unsaved (e.g. scenario case). */
count = secfile_lookup_int_default(loading->file, 0, "research.count");
for (i = 0; i < count; i++) {
if (secfile_entry_lookup(loading->file,
"research.r%d.got_tech_multi", i) == NULL) {
/* Default to FALSE */
secfile_insert_bool(loading->file, FALSE,
"research.r%d.got_tech_multi", i);
}
}
} /* Version < 3.1.91 */
if (game_version < 3019200) {
/* Before version number bump to 3.1.92, August 2022 */
int set_count;
bool gamestart_valid = FALSE;
bool al_set_already = FALSE;
bool wrap_set_already = FALSE;
const char *level;
bool count_changed = FALSE;
bool topo_defined = FALSE;
char wrap[100];
char wrap_gs[100];
if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
int i;
gamestart_valid
= secfile_lookup_bool_default(loading->file, FALSE,
"settings.gamestart_valid");
for (i = 0; i < set_count; i++) {
const char *old_name
= secfile_lookup_str(loading->file, "settings.set%d.name", i);
const char *name;
if (!old_name) {
continue;
}
name = setcompat_S3_2_name_from_S3_1(old_name);
if (fc_strcasecmp(old_name, name)) {
/* Setting's name changed */
secfile_replace_str(loading->file, name, "settings.set%d.name", i);
}
if (!fc_strcasecmp("compresstype", name)) {
const char *val = secfile_lookup_str(loading->file,
"settings.set%d.value", i);
if (!fc_strcasecmp(val, "BZIP2")) {
#ifdef FREECIV_HAVE_LIBZSTD
secfile_replace_str(loading->file, "ZSTD",
"settings.set%d.value", i);
#elif FREECIV_HAVE_LIBLZMA
secfile_replace_str(loading->file, "XZ",
"settings.set%d.value", i);
#elif FREECIV_HAVE_LIBZ
secfile_replace_str(loading->file, "LIBZ",
"settings.set%d.value", i);
#else
secfile_replace_str(loading->file, "PLAIN",
"settings.set%d.value", i);
#endif
}
if (gamestart_valid) {
val = secfile_lookup_str(loading->file,
"settings.set%d.gamestart", i);
if (!fc_strcasecmp(val, "BZIP2")) {
#ifdef FREECIV_HAVE_LIBZSTD
secfile_replace_str(loading->file, "ZSTD",
"settings.set%d.gamestart", i);
#elif FREECIV_HAVE_LIBLZMA
secfile_replace_str(loading->file, "XZ",
"settings.set%d.gamestart", i);
#elif FREECIV_HAVE_LIBZ
secfile_replace_str(loading->file, "LIBZ",
"settings.set%d.gamestart", i);
#else
secfile_replace_str(loading->file, "PLAIN",
"settings.set%d.gamestart", i);
#endif
}
}
} else if (!fc_strcasecmp("ailevel", name)) {
al_set_already = TRUE;
} else if (!fc_strcasecmp("topology", name)) {
struct setting *pset = setting_by_name(name);
struct sf_cb_data info = { pset, TRUE };
int val;
if (secfile_lookup_enum_data(loading->file, &val, TRUE,
setting_bitwise_secfile_str, &info,
"settings.set%d.value", i)) {
bool topo_changed = TRUE;
if (val & TF_OLD_WRAPX) {
if (val & TF_OLD_WRAPY) {
fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
} else {
fc_strlcpy(wrap, "WrapX", sizeof(wrap));
}
} else if (val & TF_OLD_WRAPY) {
fc_strlcpy(wrap, "WrapY", sizeof(wrap));
} else {
fc_strlcpy(wrap, "", sizeof(wrap));
topo_changed = FALSE;
}
if (topo_changed) {
char buf[100];
if (val & TF_ISO) {
if (val & TF_HEX) {
setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
} else {
setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
}
} else if (val & TF_HEX) {
setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
} else {
setting_bitwise_set(pset, "", NULL, NULL, 0);
}
setting_value_name(pset, FALSE, buf, sizeof(buf));
secfile_replace_str(loading->file, buf,
"settings.set%d.value", i);
}
if (gamestart_valid) {
if (secfile_lookup_enum_data(loading->file, &val, TRUE,
setting_bitwise_secfile_str, &info,
"settings.set%d.gamestart", i)) {
topo_changed = TRUE;
if (val & TF_OLD_WRAPX) {
if (val & TF_OLD_WRAPY) {
fc_strlcpy(wrap_gs, "WrapX|WrapY", sizeof(wrap));
} else {
fc_strlcpy(wrap_gs, "WrapX", sizeof(wrap));
}
} else if (val & TF_OLD_WRAPY) {
fc_strlcpy(wrap_gs, "WrapY", sizeof(wrap));
} else {
fc_strlcpy(wrap_gs, "", sizeof(wrap));
topo_changed = FALSE;
}
if (topo_changed) {
char buf[100];
if (val & TF_ISO) {
if (val & TF_HEX) {
setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
} else {
setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
}
} else if (val & TF_HEX) {
setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
} else {
setting_bitwise_set(pset, "", NULL, NULL, 0);
}
setting_value_name(pset, FALSE, buf, sizeof(buf));
secfile_replace_str(loading->file, buf,
"settings.set%d.gamestart", i);
}
}
}
topo_defined = TRUE;
}
} else if (!fc_strcasecmp("wrap", name)) {
wrap_set_already = TRUE;
}
}
}
if (!al_set_already) {
level = secfile_lookup_str_default(loading->file, NULL, "game.level");
if (level == NULL) {
/* Assume that this was a new format savegame after all,
* setting just has not been explicitly saved for containing default value. */
al_set_already = TRUE;
}
}
if (!al_set_already) {
/* Turn old AI level field to a setting. */
enum ai_level lvl;
if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
/* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
lvl = AI_LEVEL_RESTRICTED;
} else {
lvl = ai_level_by_name(level, fc_strcasecmp);
}
if (!ai_level_is_valid(lvl)) {
log_sg("Invalid AI level \"%s\". "
"Changed to \"%s\".", level,
ai_level_name(GAME_HARDCODED_DEFAULT_SKILL_LEVEL));
lvl = GAME_HARDCODED_DEFAULT_SKILL_LEVEL;
}
secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
if (gamestart_valid) {
secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
set_count);
}
set_count++;
count_changed = TRUE;
}
if (!wrap_set_already && topo_defined) {
secfile_insert_str(loading->file, "wrap", "settings.set%d.name", set_count);
secfile_insert_str(loading->file, wrap, "settings.set%d.value", set_count);
if (gamestart_valid) {
secfile_insert_str(loading->file, wrap_gs, "settings.set%d.value", set_count);
}
set_count++;
count_changed = TRUE;
}
if (count_changed) {
secfile_replace_int(loading->file, set_count, "settings.set_count");
}
{
int action_count;
action_count = secfile_lookup_int_default(loading->file, 0,
"savefile.action_size");
if (action_count > 0) {
const char **modname;
const char **savemod;
int j;
const char *dur_name = "Disband Unit Recover";
modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
"savefile.action_vector");
savemod = fc_calloc(action_count, sizeof(*savemod));
for (j = 0; j < action_count; j++) {
if (!fc_strcasecmp("Recycle Unit", modname[j])) {
savemod[j] = dur_name;
} else {
savemod[j] = modname[j];
}
}
secfile_replace_str_vec(loading->file, savemod, action_count,
"savefile.action_vector");
free(savemod);
}
}
player_slots_iterate(pslot) {
int plrno = player_slot_index(pslot);
int wonder_city = secfile_lookup_int_default(loading->file, -1,
"player%d.adv.wonder_city",
plrno);
if (wonder_city < 0) {
/* No wonder_city saved with the new name. Check for the old name */
wonder_city = secfile_lookup_int_default(loading->file, -1,
"player%d.wonder_city",
plrno);
if (wonder_city >= 0) {
secfile_replace_int(loading->file, wonder_city,
"player%d.adv.wonder_city", plrno);
}
}
} player_slots_iterate_end;
} /* Version < 3.1.92 */
if (game_version < 3019300) {
/* Before version number bump to 3.1.93 */
/* Older savegames unnecessarily saved diplstate type order.
* Silence "unused entry" warnings about those. */
{
int dscount = secfile_lookup_int_default(loading->file, 0,
"savefile.diplstate_type_size");
int i;
for (i = 0; i < dscount; i++) {
(void) secfile_entry_lookup(loading->file,
"savefile.diplstate_type_vector,%d", i);
}
}
(void) secfile_entry_lookup(loading->file, "game.hardcoded_counters");
/* Add wl_max_length entries for players */
{
player_slots_iterate(pslot) {
int plrno = player_slot_index(pslot);
int ncities;
int cnro;
int wlist_max_length = 0;
if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
continue;
}
ncities = secfile_lookup_int_default(loading->file, 0,
"player%d.ncities", plrno);
for (cnro = 0; cnro < ncities; cnro++) {
int wl_length = secfile_lookup_int_default(loading->file, 0,
"player%d.c%d.wl_length",
plrno, cnro);
wlist_max_length = MAX(wlist_max_length, wl_length);
}
secfile_insert_int(loading->file, wlist_max_length,
"player%d.wl_max_length", plrno);
secfile_insert_int(loading->file, MAX_TRADE_ROUTES_OLD,
"player%d.routes_max_length", plrno);
} player_slots_iterate_end;
}
/* Replace got_tech[_multi] bools on free_bulbs integers. */
{
int count = secfile_lookup_int_default(loading->file, 0, "research.count");
for (int i = 0; i < count; i++) {
bool got_tech = FALSE;
int bulbs = 0;
bool got_tech_multi
= secfile_lookup_bool_default(loading->file, FALSE,
"research.r%d.got_tech_multi", i);
if (secfile_lookup_bool(loading->file, &got_tech,
"research.r%d.got_tech", i)
&& secfile_lookup_int(loading->file, &bulbs,
"research.r%d.bulbs", i)) {
secfile_insert_int(loading->file,
got_tech || got_tech_multi ? bulbs : 0,
"research.r%d.free_bulbs", i);
}
}
}
/* Convert 'alltemperate' and 'singlepole' into 'northlatitude' and
* 'southlatitude' server settings */
{
int i;
int set_count = secfile_lookup_int_default(loading->file, 0,
"settings.set_count");
int alltemperate_idx = -1, singlepole_idx = -1;
for (i = 0; i < set_count; i++) {
const char *name
= secfile_lookup_str(loading->file, "settings.set%d.name", i);
if (!name) {
continue;
}
if (!fc_strcasecmp("northlatitude", name)
|| !fc_strcasecmp("southlatitude", name)) {
/* this savegame is recent enough to already have latitude
* settings ~> no change necessary */
alltemperate_idx = singlepole_idx = -1;
break;
}
if (!fc_strcasecmp("alltemperate", name)) {
alltemperate_idx = i;
} else if (!fc_strcasecmp("singlepole", name)) {
singlepole_idx = i;
}
}
if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
int north_latitude, south_latitude;
int north_idx, south_idx;
bool alltemperate, singlepole;
if (alltemperate_idx < 0
|| !secfile_lookup_bool(loading->file, &alltemperate,
"settings.set%d.value",
alltemperate_idx)) {
/* infer what would've been the ruleset default */
alltemperate = (wld.map.north_latitude == wld.map.south_latitude);
}
if (singlepole_idx < 0
|| !secfile_lookup_bool(loading->file, &singlepole,
"settings.set%d.value",
singlepole_idx)) {
/* infer what would've been the ruleset default */
singlepole = (wld.map.south_latitude >= 0);
}
/* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
* changes, that'll have to be handled in later migrations anyway */
north_latitude = alltemperate ? 500 : 1000;
south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
/* Replace alltemperate with northlatitude, and singlepole with
* southlatitude. If only one of the two was given, add the other
* at the end. */
north_idx = (alltemperate_idx < 0) ? set_count : alltemperate_idx;
south_idx = (singlepole_idx < 0) ? set_count : singlepole_idx;
secfile_replace_str(loading->file, "northlatitude",
"settings.set%d.name", north_idx);
secfile_replace_int(loading->file, north_latitude,
"settings.set%d.value", north_idx);
secfile_replace_str(loading->file, "southlatitude",
"settings.set%d.name", south_idx);
secfile_replace_int(loading->file, south_latitude,
"settings.set%d.value", south_idx);
if (secfile_lookup_bool_default(loading->file, FALSE,
"settings.gamestart_valid")) {
if (alltemperate_idx < 0
|| !secfile_lookup_bool(loading->file, &alltemperate,
"settings.set%d.gamestart",
alltemperate_idx)) {
alltemperate =
(wld.map.north_latitude == wld.map.south_latitude);
}
if (singlepole_idx < 0
|| !secfile_lookup_bool(loading->file, &singlepole,
"settings.set%d.gamestart",
singlepole_idx)) {
singlepole = (wld.map.south_latitude >= 0);
}
north_latitude = alltemperate ? 500 : 1000;
south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
secfile_replace_int(loading->file, north_latitude,
"settings.set%d.gamestart", north_idx);
secfile_replace_int(loading->file, south_latitude,
"settings.set%d.gamestart", south_idx);
}
if (alltemperate_idx < 0 || singlepole_idx < 0) {
/* only one was given and replaced ~> we added one new entry */
set_count++;
secfile_replace_int(loading->file, set_count,
"settings.set_count");
}
}
}
{
int action_count;
action_count = secfile_lookup_int_default(loading->file, 0,
"savefile.action_size");
if (action_count > 0) {
const char **modname;
const char **savemod;
int j;
const char *dur_name = "Transport Deboard";
modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
"savefile.action_vector");
savemod = fc_calloc(action_count, sizeof(*savemod));
for (j = 0; j < action_count; j++) {
if (!fc_strcasecmp("Transport Alight", modname[j])) {
savemod[j] = dur_name;
} else {
savemod[j] = modname[j];
}
}
secfile_replace_str_vec(loading->file, savemod, action_count,
"savefile.action_vector");
free(savemod);
}
}
} /* Version < 3.1.93 */
#endif /* FREECIV_DEV_SAVE_COMPAT_3_2 */
#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
if (game_version < 3029100) {
    (1-1/1)