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

 Scenarios are not exactly same thing as savegame from running game.
In that sense our editor is not capable of producing scenarios.
 This patch provides some framework for saving games as scenarios.

 - When scenario is loaded, contents of [scenario] are read also, and stored
 - Server sends [scenario] information to client (which does nothing with it)
 - Game saving code differentiates between scenario saves and normal saves
 - Scenario saves include [scenario] information, but are ATM
otherwise identical to normal saves
 - Scenario save is initiated by new save_scenario -packet from client
 - Gtk client editor has "Save Scenario" dialog and it can send
save_scenario packet
 - Server has new commandline option '--scenarios' for defining
directory where scenarios are saved
 - Server launched from client saves scenarios to ~/.freeciv/scenarios
 - Scenario saving will success only if [scenario] information is set.
Currently it is only set when loading existing scenario

 Since editor cannot set [scenario] data, only possible use for this
for now is updating old scenarios. One can load old scenario and then
save it via 'Save Scenario' and [scenario] remains intact. But even
that is not advisable as game is otherwise saved as running game.

 Is it so that delta code is unable to create packets that are sent
both from server to client and client to server? I tried to define
scenario_info packet as one (server sends initial information to
client, client updates) but couldn't make it compile. Currently that
packet is only used when server sends initial information to client.

 Loading distributed scenario and then saving it causes gettext
marking for scenario name and description to disappear.


 - ML

diff -Nurd -X.diff_ignore freeciv/client/connectdlg_common.c freeciv/client/connectdlg_common.c
--- freeciv/client/connectdlg_common.c	2007-03-05 21:12:22.000000000 +0200
+++ freeciv/client/connectdlg_common.c	2007-03-12 09:29:42.000000000 +0200
@@ -240,6 +240,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	2007-03-05 21:11:59.000000000 +0200
+++ freeciv/client/gui-gtk-2.0/menu.c	2007-03-12 09:37:37.000000000 +0200
@@ -164,6 +164,7 @@
   MENU_EDITOR_TOGGLE,
   MENU_EDITOR_TOOLS,
   MENU_EDITOR_RECALC_BORDERS,
+  MENU_EDITOR_SAVE,
 
   MENU_HELP_LANGUAGES,
   MENU_HELP_CONNECTING,
@@ -233,7 +234,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);
@@ -611,6 +612,9 @@
   case MENU_EDITOR_RECALC_BORDERS:
     key_editor_recalc_borders();
     break;
+  case MENU_EDITOR_SAVE:
+    popup_save_dialog(TRUE);
+    break;
   }
 }
 
@@ -950,6 +954,8 @@
     editor_menu_callback, MENU_EDITOR_TOOLS },
   { "/" N_("_Editor") "/" N_("_Recalculate Borders"), NULL,
     editor_menu_callback, MENU_EDITOR_RECALC_BORDERS },
+  { "/" N_("_Editor") "/" N_("_Save Scenario"), NULL,
+    editor_menu_callback, MENU_EDITOR_SAVE, "<StockItem>", GTK_STOCK_SAVE_AS },
 
   /* Help menu ... */
   { "/" N_("_Help"),					NULL,
@@ -1351,6 +1357,8 @@
 			can_conn_edit(&aconnection));
     menus_set_sensitive("<main>/_Editor/_Recalculate Borders",
 			can_conn_edit(&aconnection));
+    menus_set_sensitive("<main>/_Editor/_Save Scenario",
+                        can_conn_edit(&aconnection));
     menus_set_active("<main>/_Editor/Editing Mode",
 		     can_conn_edit(&aconnection));
 
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	2007-03-05 21:11:59.000000000 +0200
+++ freeciv/client/gui-gtk-2.0/pages.c	2007-03-12 09:18:21.000000000 +0200
@@ -81,6 +81,8 @@
 
 static GtkWidget *ruleset_combo;
 
+static bool save_scenario = FALSE;
+
 /**************************************************************************
   spawn a server, if there isn't one, using the default settings.
 **************************************************************************/
@@ -1645,14 +1647,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;
 
@@ -1690,7 +1692,7 @@
 **************************************************************************/
 static void update_load_page(void)
 {
-  update_saves_store(load_store);
+  update_saves_store(load_store, "saves");
 }
 
 /**************************************************************************
@@ -2251,7 +2253,7 @@
 **************************************************************************/
 static void update_save_dialog(void)
 {
-  update_saves_store(save_store);
+  update_saves_store(save_store, save_scenario ? "scenario" : "saves");
 }
 
 /**************************************************************************
@@ -2284,7 +2286,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(&aconnection, filename);
+      } else {
+        send_save_game(filename);
+        g_free(filename);
+      }
       g_free(filename);
     }
     break;
@@ -2335,7 +2342,7 @@
 /**************************************************************************
   create save dialog.
 **************************************************************************/
-static void create_save_dialog(void)
+static void create_save_dialog(bool scenario)
 {
   GtkWidget *shell;
 
@@ -2345,8 +2352,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..."),
@@ -2438,10 +2446,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	2007-03-05 21:11:59.000000000 +0200
+++ freeciv/client/gui-gtk-2.0/pages.h	2007-03-12 08:47:33.000000000 +0200
@@ -32,7 +32,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	2007-03-12 02:47:07.000000000 +0200
+++ freeciv/client/packhand.c	2007-03-12 07:21:22.000000000 +0200
@@ -2112,6 +2112,19 @@
 }
 
 /**************************************************************************
+ 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);
+  }
+}
+
+/**************************************************************************
   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	2007-03-08 17:18:27.000000000 +0200
+++ freeciv/common/game.c	2007-03-12 07:26:11.000000000 +0200
@@ -305,6 +305,8 @@
   game.control.nation_count = 0;
   game.control.government_count = 0;
 
+  game.scenario.is_scenario = FALSE;
+
   sz_strlcpy(game.demography, GAME_DEFAULT_DEMOGRAPHY);
   sz_strlcpy(game.allow_take, GAME_DEFAULT_ALLOW_TAKE);
 
diff -Nurd -X.diff_ignore freeciv/common/game.h freeciv/common/game.h
--- freeciv/common/game.h	2007-03-08 17:18:27.000000000 +0200
+++ freeciv/common/game.h	2007-03-12 07:09:27.000000000 +0200
@@ -64,6 +64,8 @@
   struct government *government_when_anarchy;
 
   struct packet_ruleset_control control;
+  struct packet_scenario_info scenario;
+
   bool debug[DEBUG_LAST];
   int version;
   char id[MAX_ID_LEN];		/* server only */
diff -Nurd -X.diff_ignore freeciv/common/packets.def freeciv/common/packets.def
--- freeciv/common/packets.def	2007-03-12 02:47:07.000000000 +0200
+++ freeciv/common/packets.def	2007-03-12 08:52:09.000000000 +0200
@@ -1472,3 +1472,13 @@
   COORD x, y;
   UINT8 mode;
 end
+
+PACKET_SCENARIO_INFO=134;sc,handle-via-packet
+  BOOL   is_scenario;
+  STRING name[256];
+  STRING description[MAX_LEN_PACKET];
+end
+
+PACKET_SAVE_SCENARIO=135;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	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/civserver.c	2007-03-12 09:27:37.000000000 +0200
@@ -188,6 +188,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 {
diff -Nurd -X.diff_ignore freeciv/server/connecthand.c freeciv/server/connecthand.c
--- freeciv/server/connecthand.c	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/connecthand.c	2007-03-12 07:38:05.000000000 +0200
@@ -173,6 +173,7 @@
 
   send_conn_info(dest, game.est_connections);
   send_conn_info(game.est_connections, dest);
+  send_scenario_info(dest);
   send_game_info(dest);
   send_player_info_c(NULL, dest);
   reset_all_start_commands();
diff -Nurd -X.diff_ignore freeciv/server/edithand.c freeciv/server/edithand.c
--- freeciv/server/edithand.c	2007-03-08 18:42:39.000000000 +0200
+++ freeciv/server/edithand.c	2007-03-12 08:31:18.000000000 +0200
@@ -34,6 +34,7 @@
 #include "cityturn.h"
 #include "gamehand.h"
 #include "plrhand.h"
+#include "srv_main.h"
 #include "unittools.h"
 #include "hand_gen.h"
 #include "maphand.h"
@@ -465,3 +466,22 @@
     map_calculate_borders();
   }
 }
+
+/****************************************************************************
+  Make scenario file out of current game.
+****************************************************************************/
+void handle_save_scenario(struct connection *pc, char *name)
+{
+  if (pc->access_level != ALLOW_HACK || !can_conn_edit(pc)) {
+    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);
+}
diff -Nurd -X.diff_ignore freeciv/server/gamehand.c freeciv/server/gamehand.c
--- freeciv/server/gamehand.c	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/gamehand.c	2007-03-12 07:31:43.000000000 +0200
@@ -401,6 +401,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	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/gamehand.h	2007-03-12 07:32:06.000000000 +0200
@@ -23,6 +23,8 @@
 void send_game_state(struct conn_list *dest, int state);
 void send_start_phase_to_clients(void);
 
+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	2007-03-12 02:47:07.000000000 +0200
+++ freeciv/server/savegame.c	2007-03-12 08:17:32.000000000 +0200
@@ -3405,6 +3405,22 @@
   int technology_order_size = 0;
   const char* name;
   int civstyle = 0;
+  char *scen_text;
+
+  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.version = secfile_lookup_int_default(file, 0, "game.version");
   tmp_server_state = (enum server_states)
@@ -4007,13 +4023,20 @@
 /***************************************************************
 ...
 ***************************************************************/
-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];
 
+  if (scenario) {
+    secfile_insert_str(file, game.scenario.name, "scenario.name");
+    secfile_insert_str(file, game.scenario.description,
+                       "scenario.description");
+  }
+
   version = MAJOR_VERSION *10000 + MINOR_VERSION *100 + PATCH_VERSION; 
   secfile_insert_int(file, version, "game.version");
 
diff -Nurd -X.diff_ignore freeciv/server/savegame.h freeciv/server/savegame.h
--- freeciv/server/savegame.h	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/savegame.h	2007-03-12 07:42:16.000000000 +0200
@@ -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	2007-03-08 17:18:27.000000000 +0200
+++ freeciv/server/srv_main.c	2007-03-12 09:26:14.000000000 +0200
@@ -177,6 +177,7 @@
   srvarg.load_filename[0] = '\0';
   srvarg.script_filename = NULL;
   srvarg.saves_pathname = "";
+  srvarg.scenarios_pathname = "";
 
   srvarg.quitidle = 0;
 
@@ -816,7 +817,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;
@@ -844,7 +845,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");
@@ -875,10 +876,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, "/");
     }
@@ -910,7 +919,7 @@
   
   my_snprintf(filename, sizeof(filename),
 	      "%s%+05d.sav", game.save_name, game.info.year);
-  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	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/srv_main.h	2007-03-12 09:23:20.000000000 +0200
@@ -36,6 +36,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;
@@ -59,7 +60,7 @@
 
 bool handle_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	2007-03-05 21:09:47.000000000 +0200
+++ freeciv/server/stdinhand.c	2007-03-12 08:23:37.000000000 +0200
@@ -742,7 +742,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