Author: jtn
Date: Tue May 12 09:22:46 2015
New Revision: 29050

URL: http://svn.gna.org/viewcvs/freeciv?rev=29050&view=rev
Log:
Make save file format for multipliers robust against ruleset changes.

See gna patch #6073.

Modified:
    trunk/server/savecompat.h
    trunk/server/savegame.c
    trunk/server/savegame2.c
    trunk/server/savegame3.c

Modified: trunk/server/savecompat.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savecompat.h?rev=29050&r1=29049&r2=29050&view=diff
==============================================================================
--- trunk/server/savecompat.h   (original)
+++ trunk/server/savecompat.h   Tue May 12 09:22:46 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(), ...
    * Deprecated in 3.0 (savegame3.c) */
   struct {

Modified: trunk/server/savegame.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savegame.c?rev=29050&r1=29049&r2=29050&view=diff
==============================================================================
--- trunk/server/savegame.c     (original)
+++ trunk/server/savegame.c     Tue May 12 09:22:46 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: trunk/server/savegame2.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savegame2.c?rev=29050&r1=29049&r2=29050&view=diff
==============================================================================
--- trunk/server/savegame2.c    (original)
+++ trunk/server/savegame2.c    Tue May 12 09:22:46 2015
@@ -486,6 +486,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;
@@ -521,6 +523,10 @@
 
   if (loading->extra.order != NULL) {
     free(loading->extra.order);
+  }
+
+  if (loading->multiplier.order != NULL) {
+    free(loading->multiplier.order);
   }
 
   if (loading->special.order != NULL) {
@@ -1129,6 +1135,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,
@@ -2193,14 +2226,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;
 

Modified: trunk/server/savegame3.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savegame3.c?rev=29050&r1=29049&r2=29050&view=diff
==============================================================================
--- trunk/server/savegame3.c    (original)
+++ trunk/server/savegame3.c    Tue May 12 09:22:46 2015
@@ -611,6 +611,8 @@
   loading->trait.size = -1;
   loading->extra.order = NULL;
   loading->extra.size = -1;
+  loading->multiplier.order = NULL;
+  loading->multiplier.size = -1;
   loading->specialist.order = NULL;
   loading->specialist.size = -1;
 
@@ -640,6 +642,10 @@
 
   if (loading->extra.order != NULL) {
     free(loading->extra.order);
+  }
+
+  if (loading->multiplier.order != NULL) {
+    free(loading->multiplier.order);
   }
 
   if (loading->specialist.order != NULL) {
@@ -1377,6 +1383,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 specialists. */
   loading->specialist.size
     = secfile_lookup_int_default(loading->file, 0,
@@ -1552,6 +1585,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");
@@ -3000,14 +3052,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

Reply via email to