<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40229 >

2008/5/4 Marko Lindqvist <cazf...@gmail.com>:
>
>  This adds server command for saving current game as scenario (and not
> as regular savegame)

 New version

 Scenario info structure now contains information whether current
players or start positions should be saved to scenario.

 This patch has no client side UI for adjusting scenario parameters. I
have been testing this just by sending hardcoded scenario info packets
from client to server.


 - ML

diff -Nurd -X.diff_ignore freeciv/client/connectdlg_common.c 
freeciv/client/connectdlg_common.c
--- freeciv/client/connectdlg_common.c  2009-01-27 12:17:08.000000000 +0200
+++ freeciv/client/connectdlg_common.c  2009-05-05 22:22:03.000000000 +0300
@@ -230,6 +230,8 @@
     argv[argc++] = "-e";
     argv[argc++] = "--saves";
     argv[argc++] = "~/.freeciv/saves";
+    argv[argc++] = "--scenarios";
+    argv[argc++] = "~/.freeciv/scenarios";
     if (logfile) {
       argv[argc++] = "--debug";
       argv[argc++] = "3";
diff -Nurd -X.diff_ignore freeciv/client/gui-gtk-2.0/menu.c 
freeciv/client/gui-gtk-2.0/menu.c
--- freeciv/client/gui-gtk-2.0/menu.c   2009-02-22 18:03:46.000000000 +0200
+++ freeciv/client/gui-gtk-2.0/menu.c   2009-05-06 00:01:12.000000000 +0300
@@ -179,6 +179,7 @@
   MENU_EDITOR_TOGGLE,
   MENU_EDITOR_RECALCULATE_BORDERS,
   MENU_EDITOR_TOGGLE_FOGOFWAR,
+  MENU_EDITOR_SAVE,
 
   MENU_HELP_LANGUAGES,
   MENU_HELP_CONNECTING,
@@ -249,7 +250,7 @@
     popup_settable_options_dialog();
     break;
   case MENU_GAME_SAVE_GAME:
-    popup_save_dialog();
+    popup_save_dialog(FALSE);
     break;
   case MENU_GAME_SAVE_QUICK:
     send_save_game(NULL);
@@ -669,6 +670,9 @@
   case MENU_EDITOR_TOGGLE_FOGOFWAR:
     key_editor_toggle_fogofwar();
     break;
+  case MENU_EDITOR_SAVE:
+    popup_save_dialog(TRUE);
+    break;
   default:
     break;
   }
@@ -842,6 +846,9 @@
        editor_menu_callback, MENU_EDITOR_RECALCULATE_BORDERS },
   { "/" N_("_Edit") "/" N_("Toggle Fog-of-war"), "<control>f",
        editor_menu_callback, MENU_EDITOR_TOGGLE_FOGOFWAR },
+  { "/" N_("_Edit") "/" N_("Save Scenario"), NULL,
+        editor_menu_callback, MENU_EDITOR_SAVE, "<StockItem>",
+        GTK_STOCK_SAVE_AS },
 
   /* View menu ... */
   { "/" N_("_View"),                                   NULL,
@@ -1454,6 +1461,8 @@
                        can_conn_edit(&client.conn));
     menus_set_sensitive("<main>/_Edit/Toggle Fog-of-war",
                        can_conn_edit(&client.conn));
+    menus_set_sensitive("<main>/_Edit/Save Scenario",
+                       can_conn_edit(&client.conn));
 
     editgui_refresh();
 
diff -Nurd -X.diff_ignore freeciv/client/gui-gtk-2.0/pages.c 
freeciv/client/gui-gtk-2.0/pages.c
--- freeciv/client/gui-gtk-2.0/pages.c  2009-03-05 18:47:31.000000000 +0200
+++ freeciv/client/gui-gtk-2.0/pages.c  2009-05-05 22:49:37.000000000 +0300
@@ -85,6 +85,8 @@
 static GtkWidget *ruleset_combo;
 static GtkWidget *start_page_entry;
 
+static bool save_scenario = FALSE;
+
 /**************************************************************************
   spawn a server, if there isn't one, using the default settings.
 **************************************************************************/
@@ -1734,14 +1736,14 @@
 /**************************************************************************
   update the saved games list store.
 **************************************************************************/
-static void update_saves_store(GtkListStore *store)
+static void update_saves_store(GtkListStore *store, const char *dir)
 {
   struct datafile_list *files;
 
   gtk_list_store_clear(store);
 
   /* search for user saved games. */
-  files = datafilelist_infix("saves", ".sav", FALSE);
+  files = datafilelist_infix(dir, ".sav", FALSE);
   datafile_list_iterate(files, pfile) {
     GtkTreeIter it;
 
@@ -1777,7 +1779,7 @@
 **************************************************************************/
 static void update_load_page(void)
 {
-  update_saves_store(load_store);
+  update_saves_store(load_store, "saves");
 }
 
 /**************************************************************************
@@ -2343,7 +2345,7 @@
 **************************************************************************/
 static void update_save_dialog(void)
 {
-  update_saves_store(save_store);
+  update_saves_store(save_store, save_scenario ? "scenario" : "saves");
 }
 
 /**************************************************************************
@@ -2376,7 +2378,12 @@
 
       text = gtk_entry_get_text(GTK_ENTRY(save_entry));
       filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
-      send_save_game(filename);
+      if (save_scenario) {
+        dsend_packet_save_scenario(&client.conn, filename);
+      } else {
+        send_save_game(filename);
+        g_free(filename);
+      }
       g_free(filename);
     }
     break;
@@ -2427,7 +2434,7 @@
 /**************************************************************************
   create save dialog.
 **************************************************************************/
-static void create_save_dialog(void)
+static void create_save_dialog(bool scenario)
 {
   GtkWidget *shell;
 
@@ -2437,8 +2444,9 @@
   GtkCellRenderer *rend;
   GtkTreeSelection *selection;
 
+  save_scenario = scenario;
 
-  shell = gtk_dialog_new_with_buttons(_("Save Game"),
+  shell = gtk_dialog_new_with_buttons(scenario ? _("Save Scenario") : _("Save 
Game"),
       NULL,
       0,
       _("_Browse..."),
@@ -2530,10 +2538,10 @@
 /**************************************************************************
   popup save dialog.
 **************************************************************************/
-void popup_save_dialog(void)
+void popup_save_dialog(bool scenario)
 {
   if (!save_dialog_shell) {
-    create_save_dialog();
+    create_save_dialog(scenario);
   }
   update_save_dialog();
  
diff -Nurd -X.diff_ignore freeciv/client/gui-gtk-2.0/pages.h 
freeciv/client/gui-gtk-2.0/pages.h
--- freeciv/client/gui-gtk-2.0/pages.h  2008-11-09 00:26:56.000000000 +0200
+++ freeciv/client/gui-gtk-2.0/pages.h  2009-05-05 22:22:03.000000000 +0300
@@ -31,7 +31,7 @@
 
 GtkWidget *create_statusbar(void);
 void append_network_statusbar(const char *text, bool force);
-void popup_save_dialog(void);
+void popup_save_dialog(bool scenario);
 
 #endif  /* FC__PAGES_H */
 
diff -Nurd -X.diff_ignore freeciv/client/packhand.c freeciv/client/packhand.c
--- freeciv/client/packhand.c   2009-05-03 18:59:38.000000000 +0300
+++ freeciv/client/packhand.c   2009-05-05 23:06:23.000000000 +0300
@@ -2480,6 +2480,20 @@
 }
 
 /**************************************************************************
+  Received packet containing info about current scenario
+**************************************************************************/
+void handle_scenario_info(struct packet_scenario_info *packet)
+{
+  game.scenario.is_scenario = packet->is_scenario;
+
+  if (packet->is_scenario) {
+    sz_strlcpy(game.scenario.name, packet->name);
+    sz_strlcpy(game.scenario.description, packet->description);
+    game.scenario.players = packet->players;
+  }
+}
+
+/**************************************************************************
   Take arrival of ruleset control packet to indicate that
   current allocated governments should be free'd, and new
   memory allocated for new size. The same for nations.
diff -Nurd -X.diff_ignore freeciv/common/game.c freeciv/common/game.c
--- freeciv/common/game.c       2009-05-03 18:59:38.000000000 +0300
+++ freeciv/common/game.c       2009-05-05 23:04:11.000000000 +0300
@@ -357,11 +357,13 @@
 
   game.control.prefered_tileset[0] = '\0';
 
+  game.scenario.is_scenario = FALSE;
+  game.scenario.players = TRUE;
+
   sz_strlcpy(game.demography, GAME_DEFAULT_DEMOGRAPHY);
   sz_strlcpy(game.allow_take, GAME_DEFAULT_ALLOW_TAKE);
 
   game.save_options.save_random = TRUE;
-  game.save_options.save_players = TRUE;
   game.save_options.save_known = TRUE;
   game.save_options.save_starts = TRUE;
   game.save_options.save_private_map = TRUE;
diff -Nurd -X.diff_ignore freeciv/common/game.h freeciv/common/game.h
--- freeciv/common/game.h       2009-05-03 18:59:38.000000000 +0300
+++ freeciv/common/game.h       2009-05-05 23:04:41.000000000 +0300
@@ -52,6 +52,8 @@
   struct government *government_during_revolution;
 
   struct packet_ruleset_control control;
+  struct packet_scenario_info scenario;
+
   bool debug[DEBUG_LAST];
   int version;
   int timeoutint;     /* increase timeout every N turns... */
@@ -95,7 +97,6 @@
   /* used by the map editor to control game_save; could be used by the server 
too */
   struct {
     bool save_random;
-    bool save_players;
     bool save_known; /* loading will just reveal the squares around cities and 
units */
     bool save_starts; /* start positions will be auto generated */
     bool save_private_map; /* FoW map; will be created if not saved */
diff -Nurd -X.diff_ignore freeciv/common/packets.def freeciv/common/packets.def
--- freeciv/common/packets.def  2009-05-03 18:59:38.000000000 +0300
+++ freeciv/common/packets.def  2009-05-05 23:30:50.000000000 +0300
@@ -254,7 +254,7 @@
   Spaceship
   Ruleset
 
-The last used packet number is 139.
+The last used packet number is 141.
 ****************************************************/
 
 
@@ -1642,3 +1642,14 @@
   SINT32 tag;
   SINT32 id;
 end
+
+PACKET_SCENARIO_INFO=140;sc,cs,handle-via-packet,handle-per-conn
+  BOOL   is_scenario;
+  STRING name[256];
+  STRING description[MAX_LEN_PACKET];
+  BOOL   players;
+end
+
+PACKET_SAVE_SCENARIO=141;cs,handle-per-conn,dsend
+  STRING name[MAX_LEN_NAME];
+end
diff -Nurd -X.diff_ignore freeciv/server/civserver.c freeciv/server/civserver.c
--- freeciv/server/civserver.c  2009-04-29 20:40:45.000000000 +0300
+++ freeciv/server/civserver.c  2009-05-05 22:22:45.000000000 +0300
@@ -196,6 +196,8 @@
       free(option);
     } else if ((option = get_option_malloc("--saves", argv, &inx, argc))) {
       srvarg.saves_pathname = option; /* Never freed. */
+    } else if ((option = get_option_malloc("--scenarios", argv, &inx, argc))) {
+      srvarg.scenarios_pathname = option; /* Never freed */
     } else if (is_option("--version", argv[inx])) {
       showvers = TRUE;
     } else if ((option = get_option_malloc("--Announce", argv, &inx, argc))) {
diff -Nurd -X.diff_ignore freeciv/server/connecthand.c 
freeciv/server/connecthand.c
--- freeciv/server/connecthand.c        2009-05-05 11:03:52.000000000 +0300
+++ freeciv/server/connecthand.c        2009-05-05 22:24:44.000000000 +0300
@@ -147,6 +147,7 @@
       send_packet_thaw_hint(pconn);
       dsend_packet_start_phase(pconn, game.info.phase);
     } else {
+      send_scenario_info(dest);
       send_game_info(dest);
       /* send new player connection to everybody */
       send_player_info(pplayer, NULL);
diff -Nurd -X.diff_ignore freeciv/server/edithand.c freeciv/server/edithand.c
--- freeciv/server/edithand.c   2009-01-27 12:17:08.000000000 +0200
+++ freeciv/server/edithand.c   2009-05-05 23:29:35.000000000 +0300
@@ -1262,3 +1262,42 @@
     send_game_info(NULL);
   }
 }
+
+/****************************************************************************
+  Make scenario file out of current game.
+****************************************************************************/
+void handle_save_scenario(struct connection *pc, char *name)
+{
+  if (pc->access_level != ALLOW_HACK) {
+    notify_conn(pc->self, NULL, E_BAD_COMMAND,
+                _("No permissions to remotely save scenario."));
+    return;
+  }
+
+  if (!game.scenario.is_scenario) {
+    /* Scenario information not available */
+    notify_conn(pc->self, NULL, E_BAD_COMMAND,
+                _("Scenario information not set. Cannot save scenario."));
+    return;
+  }
+
+  save_game(name, "Scenario", TRUE);
+}
+
+/****************************************************************************
+  Handle scenario information packet
+****************************************************************************/
+void handle_scenario_info(struct connection *pc,
+                          struct packet_scenario_info *packet)
+{
+  game.scenario.is_scenario = packet->is_scenario;
+
+  if (packet->is_scenario) {
+    sz_strlcpy(game.scenario.name, packet->name);
+    sz_strlcpy(game.scenario.description, packet->description);
+    game.scenario.players = packet->players;
+  }
+
+  /* Send new info to everybody. */
+  send_scenario_info(NULL);
+}
diff -Nurd -X.diff_ignore freeciv/server/gamehand.c freeciv/server/gamehand.c
--- freeciv/server/gamehand.c   2009-04-29 20:40:45.000000000 +0300
+++ freeciv/server/gamehand.c   2009-05-05 22:22:03.000000000 +0300
@@ -374,6 +374,24 @@
 }
 
 /**************************************************************************
+  Send current scenario info. dest NULL causes send to everyone
+**************************************************************************/
+void send_scenario_info(struct conn_list *dest)
+{
+  struct packet_scenario_info sinfo;
+
+  if (!dest) {
+    dest = game.est_connections;
+  }
+
+  sinfo = game.scenario;
+
+  conn_list_iterate(dest, pconn) {
+    send_packet_scenario_info(pconn, &sinfo);
+  } conn_list_iterate_end;
+}
+
+/**************************************************************************
   adjusts game.info.timeout based on various server options
 
   timeoutint: adjust game.info.timeout every timeoutint turns
diff -Nurd -X.diff_ignore freeciv/server/gamehand.h freeciv/server/gamehand.h
--- freeciv/server/gamehand.h   2008-10-27 04:13:36.000000000 +0200
+++ freeciv/server/gamehand.h   2009-05-05 22:22:03.000000000 +0300
@@ -21,6 +21,8 @@
 void send_year_to_clients(int year);
 void send_game_info(struct conn_list *dest);
 
+void send_scenario_info(struct conn_list *dest);
+
 struct unit_type *crole_to_unit_type(char crole,struct player *pplayer);
 
 int update_timeout(void);
diff -Nurd -X.diff_ignore freeciv/server/savegame.c freeciv/server/savegame.c
--- freeciv/server/savegame.c   2009-04-29 20:40:45.000000000 +0300
+++ freeciv/server/savegame.c   2009-05-05 23:59:17.000000000 +0300
@@ -4064,6 +4064,7 @@
   int improvement_order_size = 0;
   int technology_order_size = 0;
   int civstyle = 0;
+  char *scen_text;
   char **improvement_order = NULL;
   char **technology_order = NULL;
   enum tile_special_type *special_order = NULL;
@@ -4103,6 +4104,22 @@
     }
   }
 
+  /* [scenario] */
+  scen_text = secfile_lookup_str_default(file, "", "scenario.name");
+  if (scen_text[0] != '\0') {
+    game.scenario.is_scenario = TRUE;
+    sz_strlcpy(game.scenario.name, scen_text);
+    scen_text = secfile_lookup_str_default(file, "",
+                                           "scenarion.description");
+    if (scen_text[0] != '\0') {
+      sz_strlcpy(game.scenario.description, scen_text);
+    } else {
+      game.scenario.description[0] = '\0';
+    }
+  } else {
+    game.scenario.is_scenario = FALSE;
+  }
+
   /* [game] */
   game.version = secfile_lookup_int_default(file, 0, "game.version");
 
@@ -4468,8 +4485,11 @@
     team_remove_player(pplayer);
   } players_iterate_end;
 
-  set_player_count(secfile_lookup_int(file, "game.nplayers"));
-
+  if (!game.info.is_new_game) {
+    set_player_count(secfile_lookup_int(file, "game.nplayers"));
+  } else {
+    set_player_count(0);
+  }
 
   script_state_load(file);
 
@@ -4843,22 +4863,28 @@
 }
 
 /***************************************************************
-...
+  Main game saving function
 ***************************************************************/
-void game_save(struct section_file *file, const char *save_reason)
+void game_save(struct section_file *file, const char *save_reason,
+               bool scenario)
 {
   int i;
   int version;
   char options[512];
   char temp[B_LAST+1];
   const char *user_message;
+  bool save_players;
+  enum server_states srv_state;
 
   /* [savefile] */
   sz_strlcpy(options, savefile_options_default);
-  if (game.info.is_new_game) {
+  if (game.info.is_new_game
+      || (scenario && !game.scenario.players)) {
     if (map.num_start_positions>0) {
       sz_strlcat(options, " startpos");
     }
+  }
+  if (game.info.is_new_game) {
     if (map.have_resources) {
       sz_strlcat(options, " specials");
     }
@@ -4934,6 +4960,13 @@
     }
   }
 
+  /* [scenario] */
+  if (scenario) {
+    secfile_insert_str(file, game.scenario.name, "scenario.name");
+    secfile_insert_str(file, game.scenario.description,
+                       "scenario.description");
+  }
+
   /* [game] */
   version = MAJOR_VERSION *10000 + MINOR_VERSION *100 + PATCH_VERSION; 
   secfile_insert_int(file, version, "game.version");
@@ -4942,8 +4975,13 @@
    * started the first time), it should always be considered a running
    * game for savegame purposes:
    */
-  secfile_insert_int(file, (int) (game.info.is_new_game ? server_state() :
-                                 S_S_RUNNING), "game.server_state");
+  if (scenario && !game.scenario.players) {
+    srv_state = S_S_INITIAL;
+  } else {
+    srv_state = game.info.is_new_game ? server_state() : S_S_RUNNING;
+  }
+
+  secfile_insert_int(file, (int) srv_state, "game.server_state");
   
   secfile_insert_str(file, get_meta_patches_string(), "game.metapatches");
   secfile_insert_bool(file, game.meta_info.user_message_set,
@@ -5103,9 +5141,15 @@
     return; /* want to save scenarios as well */
   }
 
-  secfile_insert_bool(file, game.save_options.save_players,
+  if (scenario) {
+    save_players = game.scenario.players;
+  } else {
+    save_players = TRUE;
+  }
+
+  secfile_insert_bool(file, save_players,
                      "game.save_players");
-  if (game.save_options.save_players) {
+  if (save_players) {
     /* 1.14 servers depend on improvement order in ruleset. Here we
      * are trying to simulate 1.14.1 default order
      */
diff -Nurd -X.diff_ignore freeciv/server/savegame.h freeciv/server/savegame.h
--- freeciv/server/savegame.h   2007-08-04 18:36:24.000000000 +0300
+++ freeciv/server/savegame.h   2009-05-05 22:22:03.000000000 +0300
@@ -16,6 +16,7 @@
 #include "registry.h"
 
 void game_load(struct section_file *file);
-void game_save(struct section_file *file, const char *save_reason);
+void game_save(struct section_file *file, const char *save_reason,
+               bool scenario);
 
 #endif /* FC__SAVEGAME_H */
diff -Nurd -X.diff_ignore freeciv/server/srv_main.c freeciv/server/srv_main.c
--- freeciv/server/srv_main.c   2009-05-05 11:03:52.000000000 +0300
+++ freeciv/server/srv_main.c   2009-05-05 22:31:39.000000000 +0300
@@ -179,6 +179,7 @@
   srvarg.load_filename[0] = '\0';
   srvarg.script_filename = NULL;
   srvarg.saves_pathname = "";
+  srvarg.scenarios_pathname = "";
 
   srvarg.quitidle = 0;
 
@@ -968,7 +969,7 @@
 Note that if !HAVE_LIBZ, then game.info.save_compress_level should never
 become non-zero, so no need to check HAVE_LIBZ explicitly here as well.
 **************************************************************************/
-void save_game(char *orig_filename, const char *save_reason)
+void save_game(char *orig_filename, const char *save_reason, bool scenario)
 {
   char filename[600];
   char *dot;
@@ -995,7 +996,7 @@
   timer_user = new_timer_start(TIMER_USER, TIMER_ACTIVE);
     
   section_file_init(&file);
-  game_save(&file, save_reason);
+  game_save(&file, save_reason, scenario);
 
   /* Append ".sav" to filename. */
   sz_strlcat(filename, ".sav");
@@ -1029,10 +1030,18 @@
   if (!path_is_absolute(filename)) {
     char tmpname[600];
 
-    /* Ensure the saves directory exists. */
-    make_dir(srvarg.saves_pathname);
+    if (!scenario) {
+      /* Ensure the saves directory exists. */
+      make_dir(srvarg.saves_pathname);
+
+      sz_strlcpy(tmpname, srvarg.saves_pathname);
+    } else {
+      /* Make sure scenario directory exist */
+      make_dir(srvarg.scenarios_pathname);
+
+      sz_strlcpy(tmpname, srvarg.scenarios_pathname);
+    }
 
-    sz_strlcpy(tmpname, srvarg.saves_pathname);
     if (tmpname[0] != '\0') {
       sz_strlcat(tmpname, "/");
     }
@@ -1065,7 +1074,7 @@
   assert(strlen(game.save_name)<256);
   
   generate_save_name(filename, sizeof(filename), TRUE);
-  save_game(filename, save_reason);
+  save_game(filename, save_reason, FALSE);
   save_ppm();
 }
 
diff -Nurd -X.diff_ignore freeciv/server/srv_main.h freeciv/server/srv_main.h
--- freeciv/server/srv_main.h   2009-04-29 20:40:45.000000000 +0300
+++ freeciv/server/srv_main.h   2009-05-05 22:22:03.000000000 +0300
@@ -39,6 +39,7 @@
   char load_filename[512]; /* FIXME: may not be long enough? use MAX_PATH? */
   char *script_filename;
   char *saves_pathname;
+  char *scenarios_pathname;
   char serverid[256];
   /* save a ppm of the map? */
   bool save_ppm;
@@ -94,7 +95,7 @@
 
 bool server_packet_input(struct connection *pconn, void *packet, int type);
 void start_game(void);
-void save_game(char *orig_filename, const char *save_reason);
+void save_game(char *orig_filename, const char *save_reason, bool scenario);
 void pick_random_player_name(const struct nation_type *pnation,
                             char *newname);
 void send_all_info(struct conn_list *dest);
diff -Nurd -X.diff_ignore freeciv/server/stdinhand.c freeciv/server/stdinhand.c
--- freeciv/server/stdinhand.c  2009-05-05 11:03:52.000000000 +0300
+++ freeciv/server/stdinhand.c  2009-05-05 22:22:03.000000000 +0300
@@ -695,7 +695,7 @@
     return FALSE;
   }
   if (!check) {
-    save_game(arg, "User request");
+    save_game(arg, "User request", FALSE);
   }
   return TRUE;
 }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to