Project

General

Profile

Feature #2233 ยป 0043-Remove-DEV_SAVE_COMPAT.patch

Marko Lindqvist, 09/09/2026 07:11 AM

View differences:

bootstrap/freeciv.fcproj
# Uncomment if you want extended/testmatic logging
# FREECIV_TESTMATIC yes
# Uncomment to be able load recent development (unstable) savegame formats
# FREECIV_DEV_SAVE_COMPAT yes
# Project homepage URL
FREECIV_HOMEPAGE https://www.freeciv.org/
configure.ac
[ METAINFODIR=${withval} ], [ METAINFODIR="\$(prefix)/share/metainfo" ])
AC_SUBST([METAINFODIR])
dnl try to support this development version's previous save games formats
AC_ARG_ENABLE([dev-save-compat],
AS_HELP_STRING([--enable-dev-save-compat=yes/no],
[enable development version save game compatibility]),
[case "${enableval}" in
yes) dev_save_compat=1 ;;
no) dev_save_compat=0 ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-dev-save-compat]) ;;
esac],
[dev_save_compat=$IS_DEVEL_VERSION])
AS_IF([test $dev_save_compat != 0],
[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_ARG_ENABLE([patient-connect],
AS_HELP_STRING([--enable-patient-connect=yes/no],
[enable client to be very patient in connecting spawned server]),
meson.build
storage_dir = ''
default_port = ''
testmatic = ''
dev_save_compat = ''
homepage_url = '"https://www.freeciv.org/"'
proj_def = get_option('project-definition')
......
default_port = item.substring(21)
elif item.startswith('FREECIV_TESTMATIC')
testmatic = item.substring(18)
elif item.startswith('FREECIV_DEV_SAVE_COMPAT')
dev_save_compat = item.substring(24)
elif item.startswith('FREECIV_HOMEPAGE')
homepage_url = '"' + item.substring(17) + '"'
elif not item.startswith('#') and item != ''
......
error('Unknown testmatic value ' + testmatic)
endif
if dev_save_compat == 'yes'
priv_conf_data.set('FREECIV_DEV_SAVE_COMPAT', 1)
elif dev_save_compat != '' and dev_save_compat != 'no'
error('Unknown dev_save_compat value ' + dev_save_compat)
endif
priv_conf_data.set('BINDIR',
join_paths(get_option('prefix'), get_option('bindir')))
server/savegame/savecompat.c
static void compat_post_load_030300(struct loaddata *loading,
enum sgf_version format_class);
#ifdef FREECIV_DEV_SAVE_COMPAT
static void compat_load_dev(struct loaddata *loading);
static void compat_post_load_dev(struct loaddata *loading);
#endif /* FREECIV_DEV_SAVE_COMPAT */
typedef void (*load_version_func_t) (struct loaddata *loading, enum sgf_version format_class);
struct compatibility {
......
compat[i].load(loading, format_class);
}
}
#ifdef FREECIV_DEV_SAVE_COMPAT
if (loading->version == compat[compat_current].version) {
compat_load_dev(loading);
}
#endif /* FREECIV_DEV_SAVE_COMPAT */
}
/************************************************************************//**
......
compat[i].post_load(loading, format_class);
}
}
#ifdef FREECIV_DEV_SAVE_COMPAT
if (loading->version == compat[compat_current].version) {
compat_post_load_dev(loading);
}
#endif /* FREECIV_DEV_SAVE_COMPAT */
}
/************************************************************************//**
......
} players_iterate_alive_end;
}
/************************************************************************//**
Translate savegame secfile data from earlier development version format
to current one.
****************************************************************************/
#ifdef FREECIV_DEV_SAVE_COMPAT
static void compat_load_dev(struct loaddata *loading)
{
int game_version;
/* Check status and return if not OK (sg_success FALSE). */
sg_check_ret();
log_verbose("Upgrading data between development revisions");
sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
"No save version found");
#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
if (game_version < 3029100) {
/* Before version number bump to 3.2.91, September 2023 */
{
const char *str = secfile_lookup_str_default(loading->file, NULL,
"savefile.orig_version");
if (str == NULL) {
/* Make sure CURRENTLY running version does not
* end as orig_version when we resave. */
secfile_insert_str(loading->file, "old savegame3, or older",
"savefile.orig_version");
}
}
/* Add acquire_t entries for cities */
{
player_slots_iterate(pslot) {
int plrno = player_slot_index(pslot);
int ncities;
int cnro;
bool first_city;
if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
continue;
}
first_city = secfile_lookup_bool_default(loading->file, FALSE,
"player%d.got_first_city",
plrno);
if (first_city) {
const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
int flagcount = 0;
const char **flags_sg;
size_t nval;
int i;
flag_names[flagcount++] = plr_flag_id_name(PLRF_FIRST_CITY);
flags_sg = secfile_lookup_str_vec(loading->file, &nval,
"player%d.flags", plrno);
for (i = 0; i < nval; i++) {
enum plr_flag_id fid = plr_flag_id_by_name(flags_sg[i],
fc_strcasecmp);
flag_names[flagcount++] = plr_flag_id_name(fid);
}
secfile_replace_str_vec(loading->file, flag_names, flagcount,
"player%d.flags", plrno);
free(flag_names);
}
ncities = secfile_lookup_int_default(loading->file, 0,
"player%d.ncities", plrno);
for (cnro = 0; cnro < ncities; cnro++) {
if (secfile_entry_lookup(loading->file,
"player%d.c%d.acquire_t",
plrno, cnro) == NULL) {
if (secfile_lookup_int_default(loading->file, plrno,
"player%d.c%d.original",
plrno, cnro) != plrno) {
secfile_insert_int(loading->file, CACQ_CONQUEST,
"player%d.c%d.acquire_t",
plrno, cnro);
} else {
secfile_insert_int(loading->file, CACQ_FOUNDED,
"player%d.c%d.acquire_t",
plrno, cnro);
}
}
if (secfile_entry_lookup(loading->file,
"player%d.c%d.wlcb",
plrno, cnro) == NULL) {
secfile_insert_int(loading->file, WLCB_SMART,
"player%d.c%d.wlcb",
plrno, cnro);
}
}
} player_slots_iterate_end;
}
/* Add orders_max_length entries for players */
{
player_slots_iterate(pslot) {
int plrno = player_slot_index(pslot);
if (secfile_section_lookup(loading->file, "player%d", plrno) != NULL
&& secfile_entry_lookup(loading->file,
"player%d.orders_max_length", plrno)
== NULL) {
size_t nunits;
int unro;
size_t olist_max_length = 0;
nunits = secfile_lookup_int_default(loading->file, 0,
"player%d.nunits", plrno);
for (unro = 0; unro < nunits; unro++) {
int ol_length
= secfile_lookup_int_default(loading->file, 0,
"player%d.u%d.orders_length",
plrno, unro);
olist_max_length = MAX(olist_max_length, ol_length);
}
secfile_insert_int(loading->file, olist_max_length,
"player%d.orders_max_length", plrno);
}
} player_slots_iterate_end;
}
{
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 *clean_name = "Clean";
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("Clean Pollution", modname[j])
|| !fc_strcasecmp("Clean Fallout", modname[j])) {
savemod[j] = clean_name;
} else {
savemod[j] = modname[j];
}
}
secfile_replace_str_vec(loading->file, savemod, action_count,
"savefile.action_vector");
free(savemod);
}
}
{
int activities_count;
activities_count = secfile_lookup_int_default(loading->file, 0,
"savefile.activities_size");
if (activities_count > 0) {
const char **modname;
const char **savemod;
int j;
const char *clean_name = "Clean";
modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
"savefile.activities_vector");
savemod = fc_calloc(activities_count, sizeof(*savemod));
for (j = 0; j < activities_count; j++) {
if (!fc_strcasecmp("Pollution", modname[j])
|| !fc_strcasecmp("Fallout", modname[j])) {
savemod[j] = clean_name;
} else {
savemod[j] = modname[j];
}
}
secfile_replace_str_vec(loading->file, savemod, activities_count,
"savefile.activities_vector");
free(savemod);
}
}
/* Server setting migration. */
{
int set_count;
if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
bool gamestart_valid = FALSE;
gamestart_valid
= secfile_lookup_bool_default(loading->file, FALSE,
"settings.gamestart_valid");
if (!gamestart_valid) {
int i;
/* Older savegames saved gamestart values even when they were not valid.
* Silence warnings caused by them. */
for (i = 0; i < set_count; i++) {
secfile_entry_ignore(loading->file, "settings.set%d.gamestart", i);
secfile_entry_ignore(loading->file, "settings.set%d.gamesetdef", i);
}
}
}
}
{
int ssa_count;
ssa_count = secfile_lookup_int_default(loading->file, 0,
"savefile.server_side_agent_size");
if (ssa_count > 0) {
const char **modname;
const char **savemod;
int j;
const char *aw_name = "AutoWorker";
modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
"savefile.server_side_agent_list");
savemod = fc_calloc(ssa_count, sizeof(*savemod));
for (j = 0; j < ssa_count; j++) {
if (!fc_strcasecmp("Autosettlers", modname[j])) {
savemod[j] = aw_name;
} else {
savemod[j] = modname[j];
}
}
secfile_replace_str_vec(loading->file, savemod, ssa_count,
"savefile.server_side_agent_list");
free(savemod);
}
}
} /* Version < 3.2.91 */
if (game_version < 3029200) {
/* Before version number bump to 3.2.92, June 2024 */
secfile_insert_bool(loading->file, FALSE, "map.altitude");
/* World Peace has never started in the old savegame. */
game.info.turn
= secfile_lookup_int_default(loading->file, 0, "game.turn");
game.server.world_peace_start
= secfile_lookup_int_default(loading->file, game.info.turn,
"game.world_peace_start");
secfile_replace_int(loading->file, game.server.world_peace_start,
"game.world_peace_start");
/* Last turn change time as a float, not integer multiplied by 100 */
{
float tct = secfile_lookup_int_default(loading->file, 0,
"game.last_turn_change_time") / 100.0;
secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
}
/* Add actions for unit activities */
loading->activities.size
= secfile_lookup_int_default(loading->file, 0,
"savefile.activities_size");
if (loading->activities.size) {
loading->activities.order
= secfile_lookup_str_vec(loading->file, &loading->activities.size,
"savefile.activities_vector");
sg_failure_ret(loading->activities.size != 0,
"Failed to load activity order: %s",
secfile_error());
}
loading->action.size = secfile_lookup_int_default(loading->file, 0,
"savefile.action_size");
sg_failure_ret(loading->action.size > 0,
"Failed to load action order: %s",
secfile_error());
if (loading->action.size) {
const char **modname;
int j;
modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
"savefile.action_vector");
loading->action.order = fc_calloc(loading->action.size,
sizeof(*loading->action.order));
for (j = 0; j < loading->action.size; j++) {
struct action *real_action = action_by_rule_name(modname[j]);
if (real_action) {
loading->action.order[j] = real_action->id;
} else {
log_sg("Unknown action \'%s\'", modname[j]);
loading->action.order[j] = ACTION_NONE;
}
}
free(modname);
}
player_slots_iterate(pslot) {
int plrno = player_slot_index(pslot);
int nunits;
int unro;
if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
continue;
}
nunits = secfile_lookup_int_default(loading->file, 0,
"player%d.nunits", plrno);
for (unro = 0; unro < nunits; unro++) {
int ei;
int i;
enum unit_activity activity;
enum gen_action act;
ei = secfile_lookup_int_default(loading->file, -1,
"player%d.u%d.activity", plrno, unro);
if (ei >= 0 && ei < loading->activities.size) {
bool found = FALSE;
activity = unit_activity_by_name(loading->activities.order[ei],
fc_strcasecmp);
act = activity_default_action(activity);
for (i = 0; i < loading->action.size; i++) {
if (act == loading->action.order[i]) {
secfile_insert_int(loading->file, i, "player%d.u%d.action",
plrno, unro);
found = TRUE;
break;
}
}
if (!found) {
secfile_insert_int(loading->file, -1, "player%d.u%d.action",
plrno, unro);
}
}
}
} player_slots_iterate_end;
/* Researches */
{
int count = secfile_lookup_int_default(loading->file, 0, "research.count");
int i;
for (i = 0; i < count; i++) {
/* It's ok for old savegames to have these entries. */
secfile_entry_ignore(loading->file, "research.r%d.techs", i);
}
}
} /* Version < 3.2.92 */
if (game_version < 3029300) {
/* Before version number bump to 3.2.93, May 2025 */
{
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 *cc1_name = "Conquer City Shrink";
const char *cc2_name = "Conquer City Shrink 2";
const char *cc3_name = "Conquer City Shrink 3";
const char *cc4_name = "Conquer City Shrink 4";
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("Conquer City", modname[j])) {
savemod[j] = cc1_name;
} else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
savemod[j] = cc2_name;
} else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
savemod[j] = cc3_name;
} else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
savemod[j] = cc4_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 ncities;
int cnro;
if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
continue;
}
ncities = secfile_lookup_int_default(loading->file, 0,
"player%d.dc_total", plrno);
for (cnro = 0; cnro < ncities; cnro++) {
if (!secfile_entry_lookup(loading->file, "player%d.dc%d.original",
plrno, cnro)) {
secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
plrno, cnro);
}
}
} player_slots_iterate_end;
} /* Version < 3.2.93 */
if (game_version < 3029400) {
/* Before version number bump to 3.2.94 */
} /* Version < 3.2.94 */
#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
}
/************************************************************************//**
Update loaded game data from earlier development version to something
usable by current Freeciv.
****************************************************************************/
static void compat_post_load_dev(struct loaddata *loading)
{
int game_version;
/* Check status and return if not OK (sg_success FALSE). */
sg_check_ret();
if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
game_version = 2060000;
}
#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
if (game_version < 3029100) {
/* Before version number bump to 3.2.91 */
} /* Version < 3.2.91 */
#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
}
#endif /* FREECIV_DEV_SAVE_COMPAT */
/************************************************************************//**
Convert old ai level value to ai_level
****************************************************************************/
    (1-1/1)