Author: jtn Date: Tue May 12 09:25:18 2015 New Revision: 29062 URL: http://svn.gna.org/viewcvs/freeciv?rev=29062&view=rev Log: Make save file format for multipliers robust against ruleset changes.
See gna patch #6073. Modified: branches/S2_6/server/savecompat.h branches/S2_6/server/savegame.c branches/S2_6/server/savegame2.c Modified: branches/S2_6/server/savecompat.h URL: http://svn.gna.org/viewcvs/freeciv/branches/S2_6/server/savecompat.h?rev=29062&r1=29061&r2=29062&view=diff ============================================================================== --- branches/S2_6/server/savecompat.h (original) +++ branches/S2_6/server/savecompat.h Tue May 12 09:25:18 2015 @@ -67,6 +67,11 @@ struct extra_type **order; size_t size; } extra; + /* loaded in sg_load_savefile(); needed in sg_load_players_basic() */ + struct { + struct multiplier **order; + size_t size; + } multiplier; /* loaded in sg_load_savefile(); needed in sg_load_map(), ... */ struct { enum tile_special_type *order; Modified: branches/S2_6/server/savegame.c URL: http://svn.gna.org/viewcvs/freeciv/branches/S2_6/server/savegame.c?rev=29062&r1=29061&r2=29062&view=diff ============================================================================== --- branches/S2_6/server/savegame.c (original) +++ branches/S2_6/server/savegame.c Tue May 12 09:25:18 2015 @@ -1753,6 +1753,11 @@ plr->target_government = government_of_player(plr); } + /* Multipliers: post-date version 1 savefiles, so use ruleset defaults */ + multipliers_iterate(pmul) { + plr->multipliers[multiplier_index(pmul)] = pmul->def; + } multipliers_iterate_end; + p = secfile_lookup_str(file, "player%d.city_style_by_name", plrno); if (!p) { char* old_order[4] = {"European", "Classical", "Tropical", "Asian"}; Modified: branches/S2_6/server/savegame2.c URL: http://svn.gna.org/viewcvs/freeciv/branches/S2_6/server/savegame2.c?rev=29062&r1=29061&r2=29062&view=diff ============================================================================== --- branches/S2_6/server/savegame2.c (original) +++ branches/S2_6/server/savegame2.c Tue May 12 09:25:18 2015 @@ -655,6 +655,8 @@ loading->trait.size = -1; loading->extra.order = NULL; loading->extra.size = -1; + loading->multiplier.order = NULL; + loading->multiplier.size = -1; loading->special.order = NULL; loading->special.size = -1; loading->base.order = NULL; @@ -690,6 +692,10 @@ if (loading->extra.order != NULL) { free(loading->extra.order); + } + + if (loading->multiplier.order != NULL) { + free(loading->multiplier.order); } if (loading->special.order != NULL) { @@ -1562,6 +1568,33 @@ } } + /* Load multipliers. */ + loading->multiplier.size + = secfile_lookup_int_default(loading->file, 0, + "savefile.multipliers_size"); + if (loading->multiplier.size) { + const char **modname; + int j; + + modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size, + "savefile.multipliers_vector"); + sg_failure_ret(loading->multiplier.size != 0, + "Failed to load multipliers order: %s", + secfile_error()); + /* It's OK for the set of multipliers in the savefile to differ + * from those in the ruleset. */ + loading->multiplier.order = fc_calloc(loading->multiplier.size, + sizeof(*loading->multiplier.order)); + for (j = 0; j < loading->multiplier.size; j++) { + loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]); + if (!loading->multiplier.order[j]) { + log_verbose("Multiplier \"%s\" in savegame but not in ruleset, " + "discarding", modname[j]); + } + } + free(modname); + } + /* Load specials. */ loading->special.size = secfile_lookup_int_default(loading->file, 0, @@ -1842,6 +1875,25 @@ free(modname); } + /* Save multipliers order in the savegame. */ + secfile_insert_int(saving->file, multiplier_count(), + "savefile.multipliers_size"); + if (multiplier_count() > 0) { + const char **modname; + + i = 0; + modname = fc_calloc(multiplier_count(), sizeof(*modname)); + + multipliers_iterate(pmul) { + modname[multiplier_index(pmul)] = multiplier_rule_name(pmul); + } multipliers_iterate_end; + + secfile_insert_str_vec(saving->file, modname, + multiplier_count(), + "savefile.multipliers_vector"); + free(modname); + } + /* Save diplstate type order in the savegame. */ secfile_insert_int(saving->file, DS_LAST, "savefile.diplstate_type_size"); @@ -3377,14 +3429,33 @@ /* Free the color definition. */ rgbcolor_destroy(prgbcolor); - /* multipliers (policies) */ - i = multiplier_count(); - - for (k = 0; k < i; k++) { - pplayer->multipliers[k] = secfile_lookup_int_default(loading->file, - multiplier_by_number(k)->def, - "player%d.multiplier%d.val", - player_slot_index(pslot), k); + /* Multipliers (policies) */ + + /* First initialise player values with ruleset defaults; this will + * cover any in the ruleset not known when the savefile was created. */ + multipliers_iterate(pmul) { + pplayer->multipliers[multiplier_index(pmul)] = pmul->def; + } multipliers_iterate_end; + + /* Now override with any values from the savefile. */ + for (k = 0; k < loading->multiplier.size; k++) { + const struct multiplier *pmul = loading->multiplier.order[k]; + + if (pmul) { + int val = + secfile_lookup_int_default(loading->file, pmul->def, + "player%d.multiplier%d.val", + player_slot_index(pslot), k); + int rval = (((CLIP(pmul->start, val, pmul->stop) + - pmul->start) / pmul->step) * pmul->step) + pmul->start; + + if (rval != val) { + log_verbose("Player %d had illegal value for multiplier \"%s\": " + "was %d, clamped to %d", pslot_id, + multiplier_rule_name(pmul), val, rval); + } + pplayer->multipliers[multiplier_index(pmul)] = rval; + } /* else silently discard multiplier not in current ruleset */ } } player_slots_iterate_end; _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits