Feature #716 ยป 0043-Drop-FREECIV_DEV_SAVE_COMPAT_3_2.patch
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) {
|