From c49a6aa015f8f4ec3b39f7dbf19928240a5419ae Mon Sep 17 00:00:00 2001 From: Alina Lenk Date: Sat, 26 Mar 2022 21:55:41 +0100 Subject: [PATCH] Remove support for rulesets with mixed format versions Requested by Marko Lindqvist See osdn #43708 and osdn #44203 Signed-off-by: Alina Lenk --- server/rscompat.c | 62 ++++++++++++++++++++++++++++++++++++----------- server/rscompat.h | 16 ++++-------- server/ruleset.c | 52 ++++++++++++++++----------------------- 3 files changed, 74 insertions(+), 56 deletions(-) diff --git a/server/rscompat.c b/server/rscompat.c index 5a18a680ea..c4cf214e62 100644 --- a/server/rscompat.c +++ b/server/rscompat.c @@ -63,7 +63,7 @@ void rscompat_init_info(struct rscompat_info *info) **************************************************************************/ int rscompat_check_capabilities(struct section_file *file, const char *filename, - struct rscompat_info *info) + const struct rscompat_info *info) { const char *datafile_options; bool ok = FALSE; @@ -120,6 +120,40 @@ int rscompat_check_capabilities(struct section_file *file, return format; } +/**********************************************************************//** + Different ruleset files within a ruleset directory should all have + identical datafile.format_version + This checks the file version against the expected version. + + See also rscompat_check_capabilities +**************************************************************************/ +bool rscompat_check_cap_and_version(struct section_file *file, + const char *filename, + const struct rscompat_info *info) +{ + int format_version; + + fc_assert_ret_val(info->version > 0, FALSE); + + format_version = rscompat_check_capabilities(file, filename, info); + if (format_version <= 0) { + /* Already logged in rscompat_check_capabilities */ + return FALSE; + } + + if (format_version != info->version) { + log_fatal("\"%s\": ruleset datafile format version differs from" + " other ruleset datafile(s):", filename); + log_fatal(" datafile format version: %d", format_version); + log_fatal(" expected format version: %d", info->version); + ruleset_error(LOG_ERROR, "Inconsistent format versions"); + + return FALSE; + } + + return TRUE; +} + /**********************************************************************//** Add all hard obligatory requirements to an action enabler or disable it. @param ae the action enabler to add requirements to. @@ -349,7 +383,7 @@ static int first_free_terrain_user_flag(void) **************************************************************************/ bool rscompat_names(struct rscompat_info *info) { - if (info->ver_units < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { /* Some unit type flags moved to the ruleset between 3.0 and 3.1. * Add them back as user flags. * XXX: ruleset might not need all of these, and may have enough @@ -440,7 +474,7 @@ bool rscompat_names(struct rscompat_info *info) } } - if (info->ver_terrain < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { /* Some terrain flags moved to the ruleset between 3.0 and 3.1. * Add them back as user flags. * XXX: ruleset might not need all of these, and may have enough @@ -535,7 +569,7 @@ static bool effect_list_compat_cb(struct effect *peffect, void *data) { struct rscompat_info *info = (struct rscompat_info *)data; - if (info->ver_effects < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { /* Attack has been split in regular "Attack" and "Suicide Attack". */ effect_handle_split_universal(peffect, universal_by_number(VUT_ACTION, ACTION_ATTACK), @@ -770,7 +804,7 @@ static void effect_to_enabler(action_id action, struct section_file *file, bool rscompat_old_effect_3_1(const char *type, struct section_file *file, const char *sec_name, struct rscompat_info *compat) { - if (compat->ver_effects < RSFORMAT_3_1) { + if (compat->version < RSFORMAT_3_1) { if (!fc_strcasecmp(type, "Transform_Possible")) { effect_to_enabler(ACTION_TRANSFORM_TERRAIN, file, sec_name, compat, type); return TRUE; @@ -808,7 +842,7 @@ void rscompat_adjust_pre_sanity(struct rscompat_info *info) return; } - if (info->ver_buildings < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { improvement_iterate(pimprove) { if (pimprove->upkeep != 0 && is_wonder(pimprove)) { pimprove->upkeep = 0; @@ -832,7 +866,7 @@ void rscompat_postprocess(struct rscompat_info *info) * the new effects from being upgraded by accident. */ iterate_effect_cache(effect_list_compat_cb, info); - if (info->ver_effects < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { struct effect *peffect; /* Post successful action move fragment loss for "Bombard" @@ -1079,7 +1113,7 @@ void rscompat_postprocess(struct rscompat_info *info) FALSE, FALSE, FALSE, "HutNothing")); } - if (info->ver_game < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { /* New enablers */ struct action_enabler *enabler; struct requirement e_req; @@ -1659,7 +1693,7 @@ void rscompat_postprocess(struct rscompat_info *info) } action_enablers_iterate_end; } - if (info->ver_units < RSFORMAT_3_1) { + if (info->version < RSFORMAT_3_1) { enum unit_class_flag_id nothing = unit_class_flag_id_by_name("HutNothing", fc_strcasecmp); @@ -1695,7 +1729,7 @@ bool rscompat_auto_attack_3_1(struct rscompat_info *compat, { int i; - if (compat->ver_game < RSFORMAT_3_1) { + if (compat->version < RSFORMAT_3_1) { /* Auto attack happens during war. */ requirement_vector_append(&auto_perf->reqs, req_from_values(VUT_DIPLREL, @@ -1850,7 +1884,7 @@ static bool slow_invasion_effects(const char *action_rule_name) bool rscompat_old_slow_invasions_3_1(struct rscompat_info *compat, bool slow_invasions) { - if (compat->ver_effects < RSFORMAT_3_1 && compat->ver_game < RSFORMAT_3_1) { + if (compat->version < RSFORMAT_3_1 && compat->version < RSFORMAT_3_1) { /* BeachLander and slow_invasions has moved to the ruleset. Use a "fake * generalized" Transport Disembark, Conquer City, Enter Hut and * Frighten Hut to handle it. */ @@ -2032,7 +2066,7 @@ const char *rscompat_utype_flag_name_3_1(struct rscompat_info *compat, const char *rscompat_combat_bonus_name_3_1(struct rscompat_info *compat, const char *old_type) { - if (compat->compat_mode && compat->ver_units < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { if (!fc_strcasecmp("Firepower1", old_type)) { return combat_bonus_type_name(CBONUS_LOW_FIREPOWER); } @@ -2047,7 +2081,7 @@ const char *rscompat_combat_bonus_name_3_1(struct rscompat_info *compat, void rscompat_uclass_flags_3_1(struct rscompat_info *compat, struct unit_class *pclass) { - if (compat->compat_mode && compat->ver_units < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { /* Old hardcoded behavior was like all units having NonNatBombardTgt */ BV_SET(pclass->flags, UCF_NONNAT_BOMBARD_TGT); } @@ -2059,7 +2093,7 @@ void rscompat_uclass_flags_3_1(struct rscompat_info *compat, void rscompat_extra_adjust_3_1(struct rscompat_info *compat, struct extra_type *pextra) { - if (compat->compat_mode && compat->ver_terrain < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { /* Give remove cause ERM_ENTER for huts */ if (is_extra_caused_by(pextra, EC_HUT)) { diff --git a/server/rscompat.h b/server/rscompat.h index c4448e1458..82354acc33 100644 --- a/server/rscompat.h +++ b/server/rscompat.h @@ -29,22 +29,16 @@ struct rscompat_info { bool compat_mode; rs_conversion_logger log_cb; - int ver_buildings; - int ver_cities; - int ver_effects; - int ver_game; - int ver_governments; - int ver_nations; - int ver_styles; - int ver_techs; - int ver_terrain; - int ver_units; + int version; }; void rscompat_init_info(struct rscompat_info *info); int rscompat_check_capabilities(struct section_file *file, const char *filename, - struct rscompat_info *info); + const struct rscompat_info *info); +bool rscompat_check_cap_and_version(struct section_file *file, + const char *filename, + const struct rscompat_info *info); bool rscompat_names(struct rscompat_info *info); diff --git a/server/ruleset.c b/server/ruleset.c index aeeabf05d7..16022d6823 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -1352,8 +1352,8 @@ static bool load_game_names(struct section_file *file, bool ok = TRUE; /* section: datafile */ - compat->ver_game = rscompat_check_capabilities(file, filename, compat); - if (compat->ver_game <= 0) { + compat->version = rscompat_check_capabilities(file, filename, compat); + if (compat->version <= 0) { return FALSE; } @@ -1443,8 +1443,7 @@ static bool load_tech_names(struct section_file *file, bool ok = TRUE; const char *flag; - compat->ver_techs = rscompat_check_capabilities(file, filename, compat); - if (compat->ver_techs <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -1765,8 +1764,7 @@ static bool load_unit_names(struct section_file *file, const char *flag; bool ok = TRUE; - compat->ver_units = rscompat_check_capabilities(file, filename, compat); - if (compat->ver_units <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -2081,7 +2079,7 @@ static bool load_ruleset_units(struct section_file *file, "%s.non_native_def_pct", sec_name); - if (compat->compat_mode && compat->ver_units < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { const char *hut_str; hut_str = secfile_lookup_str_default(file, "Normal", @@ -2473,7 +2471,7 @@ static bool load_ruleset_units(struct section_file *file, u->paratroopers_range = secfile_lookup_int_default(file, 0, "%s.paratroopers_range", sec_name); - if (compat->compat_mode && compat->ver_units < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { u->rscompat_cache.paratroopers_mr_req = SINGLE_MOVE * secfile_lookup_int_default( file, 0, "%s.paratroopers_mr_req", sec_name); @@ -2627,9 +2625,7 @@ static bool load_building_names(struct section_file *file, const char *filename = secfile_name(file); bool ok = TRUE; - compat->ver_buildings = rscompat_check_capabilities(file, filename, - compat); - if (compat->ver_buildings <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -2798,9 +2794,7 @@ static bool load_terrain_names(struct section_file *file, const char *filename = secfile_name(file); bool ok = TRUE; - compat->ver_terrain = rscompat_check_capabilities(file, filename, - compat); - if (compat->ver_terrain <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -3447,7 +3441,7 @@ static bool load_ruleset_terrain(struct section_file *file, ok = FALSE; break; } - if (compat->compat_mode && compat->ver_terrain < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { if (pterrain->transform_time <= 0) { /* Transform time of zero was documented to disable the transform * regardless of given transform result in earlier versions, i.e., @@ -4303,9 +4297,7 @@ static bool load_government_names(struct section_file *file, const char *filename = secfile_name(file); bool ok = TRUE; - compat->ver_governments = rscompat_check_capabilities(file, filename, - compat); - if (compat->ver_governments <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -4627,9 +4619,7 @@ static bool load_nation_names(struct section_file *file, bool ok = TRUE; const char *filename = secfile_name(file); - compat->ver_nations = rscompat_check_capabilities(file, filename, - compat); - if (compat->ver_nations <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -4663,7 +4653,7 @@ static bool load_nation_names(struct section_file *file, if (!strcmp("freeciv-core", domain)) { pl->translation_domain = NULL; - } else if (compat->compat_mode && compat->ver_nations < RSFORMAT_3_1 + } else if (compat->compat_mode && compat->version < RSFORMAT_3_1 && !strcmp("freeciv", domain)) { pl->translation_domain = NULL; } else if (!strcmp("freeciv-nations", domain)) { @@ -5636,8 +5626,7 @@ static bool load_style_names(struct section_file *file, struct section_list *sec; const char *filename = secfile_name(file); - compat->ver_styles = rscompat_check_capabilities(file, filename, compat); - if (compat->ver_styles <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -5877,8 +5866,7 @@ static bool load_ruleset_cities(struct section_file *file, struct section_list *sec; bool ok = TRUE; - compat->ver_cities = rscompat_check_capabilities(file, filename, compat); - if (compat->ver_cities <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } @@ -6084,10 +6072,10 @@ static bool load_ruleset_effects(struct section_file *file, filename = secfile_name(file); - compat->ver_effects = rscompat_check_capabilities(file, filename, compat); - if (compat->ver_effects <= 0) { + if (!rscompat_check_cap_and_version(file, filename, compat)) { return FALSE; } + (void) secfile_entry_by_path(file, "datafile.description"); /* unused */ (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */ @@ -6946,7 +6934,7 @@ static bool load_ruleset_game(struct section_file *file, bool act, /* section: actions */ if (ok) { - if (compat->compat_mode && compat->ver_game < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { int force_capture_units, force_bombard, force_explode_nuclear; if (secfile_lookup_bool_default(file, FALSE, @@ -7323,7 +7311,7 @@ static bool load_ruleset_game(struct section_file *file, bool act, } } - if (compat->compat_mode && compat->ver_game < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { bool slow_invasions = secfile_lookup_bool_default(file, TRUE, "global_unit_options.slow_invasions"); @@ -7354,7 +7342,7 @@ static bool load_ruleset_game(struct section_file *file, bool act, = secfile_lookup_bool_default(file, RS_DEFAULT_COMBAT_ODDS_SCALED_VETERANCY, "combat_rules.combat_odds_scaled_veterancy"); - if (compat->compat_mode && compat->ver_game < RSFORMAT_3_1) { + if (compat->compat_mode && compat->version < RSFORMAT_3_1) { /* Old hardcoded behavior was not to have bombard rate reduced for damage. */ default_drbr = FALSE; } @@ -9268,6 +9256,8 @@ static bool load_rulesetdir(const char *rsdir, bool compat_mode, } if (ok) { + /* Note: Keep load_game_names first so that compat_info.version is + * correctly initialized. */ ok = load_game_names(gamefile, &compat_info) && load_tech_names(techfile, &compat_info) && load_building_names(buildfile, &compat_info) -- 2.17.1