Feature #2233 ยป 0043-Remove-DEV_SAVE_COMPAT.patch
| 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
|
||
|
****************************************************************************/
|
||