Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2005:
[Freeciv-Dev] (PR#11816) Patch: ruleset listing and gtk2 setting
Home

[Freeciv-Dev] (PR#11816) Patch: ruleset listing and gtk2 setting

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: dspeyer@xxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#11816) Patch: ruleset listing and gtk2 setting
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 29 Jan 2005 17:58:05 -0800
Reply-to: bugs@xxxxxxxxxxx

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

I like the interface, more or less.

However there are problems.

1.  It shows the .. directory.  This shows the need for a better means
of choosing ruleset directories.

2.  Using /rulesetdir is not all that's needed to change the ruleset. 
That's what the .serv files are for.

So, I had two ideas:

1.  Keep the same interface, but instead of using /rulesetdir and
directories, use /read and .serv files.  This works nicely because it's
easy to find the .serv files, and it's easy to do /read.  The problem is
when switching rulesets more than once (from default to civ2 and back to
default) one must reset all server variables.  For this we'll need a
/reset command.  We'd also need a default.serv I think (although it need
not be read in most cases - only when switching *back* to default).

2.  Make rulesets be handled as a subset of scenarios.  We can make a
civ1.sav that contains the data which when read (via /load) puts us into
civ1 mode.  This is something that SHOULD be supported by scenarios. 
However when I made such a scenario (civserver -r data/civ1.serv; save
civ1.sav) and tried loading it in the gtk2 scenario page, it didn't work
very well.  Also this means you can't mix-and-match rulesets with
existing scenarios (which is sometimes a feature, sometimes a bug,
depending on the scenario...).

I'm not really sure which is better.  But the .serv idea seems easier. 
Here's a patch for it (a modification of the original patch).

-jason

? data/scenario/civ1.sav
? data/scenario/civ2.sav
? data/scenario/history.sav
Index: client/connectdlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/connectdlg_common.c,v
retrieving revision 1.28
diff -u -r1.28 connectdlg_common.c
--- client/connectdlg_common.c  4 Dec 2004 00:29:37 -0000       1.28
+++ client/connectdlg_common.c  30 Jan 2005 01:57:06 -0000
@@ -500,3 +500,43 @@
 
   send_chat(message);
 }
+
+/**************************************************************************
+  Handle the list of rulesets sent by the server.
+**************************************************************************/
+void handle_ruleset_choices(struct packet_ruleset_choices *packet)
+{
+  char *rulesets[packet->ruleset_count];
+  int i;
+  size_t suf_len = strlen(RULESET_SUFFIX);
+
+  for (i = 0; i < packet->ruleset_count; i++) {
+    size_t len = strlen(packet->rulesets[i]);
+
+    rulesets[i] = mystrdup(packet->rulesets[i]);
+
+    if (len > suf_len
+       && strcmp(rulesets[i] + len - suf_len, RULESET_SUFFIX) == 0) {
+      rulesets[i][len - suf_len] = '\0';
+    }
+  }
+  gui_set_rulesets(packet->ruleset_count, rulesets);
+
+  for (i = 0; i < packet->ruleset_count; i++) {
+    free(rulesets[i]);
+  }
+}
+
+/**************************************************************************
+  Called by the GUI code when the user sets the ruleset.  The ruleset
+  passed in here should match one of the strings given to gui_set_rulesets.
+**************************************************************************/
+void set_ruleset(const char *ruleset)
+{
+  char buf[4096];
+
+  my_snprintf(buf, sizeof(buf), "/read %s%s",
+             ruleset, RULESET_SUFFIX);
+  freelog(LOG_NORMAL, "Executing '%s'", buf);
+  send_chat(buf);
+}
Index: client/connectdlg_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/connectdlg_common.h,v
retrieving revision 1.7
diff -u -r1.7 connectdlg_common.h
--- client/connectdlg_common.h  16 Nov 2004 18:09:46 -0000      1.7
+++ client/connectdlg_common.h  30 Jan 2005 01:57:06 -0000
@@ -31,6 +31,8 @@
 
 void disconnected_from_local_server(void);
 
+void set_ruleset(const char *ruleset);
+
 extern char player_name[MAX_LEN_NAME];
 extern char *current_filename;
 
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.461
diff -u -r1.461 packhand.c
--- client/packhand.c   29 Jan 2005 17:58:17 -0000      1.461
+++ client/packhand.c   30 Jan 2005 01:57:07 -0000
@@ -2860,4 +2860,3 @@
                    packet->survives, packet->eff_value,
                    &req, packet->group_id);
 }
-
Index: client/gui-ftwl/pages.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-ftwl/pages.c,v
retrieving revision 1.2
diff -u -r1.2 pages.c
--- client/gui-ftwl/pages.c     20 Oct 2004 17:38:51 -0000      1.2
+++ client/gui-ftwl/pages.c     30 Jan 2005 01:57:07 -0000
@@ -26,3 +26,7 @@
   /* PORTME */
 }
 
+void gui_set_rulesets(char rulesets[][64], int ruleset_count)
+{
+  /* PORTME */
+}
Index: client/gui-gtk/pages.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/pages.c,v
retrieving revision 1.2
diff -u -r1.2 pages.c
--- client/gui-gtk/pages.c      20 Oct 2004 17:38:51 -0000      1.2
+++ client/gui-gtk/pages.c      30 Jan 2005 01:57:07 -0000
@@ -26,3 +26,7 @@
   /* PORTME */
 }
 
+void gui_set_rulesets(char rulesets[][64], int ruleset_count)
+{
+  /* PORTME */
+}
Index: client/gui-gtk-2.0/pages.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/pages.c,v
retrieving revision 1.14
diff -u -r1.14 pages.c
--- client/gui-gtk-2.0/pages.c  22 Jan 2005 19:45:40 -0000      1.14
+++ client/gui-gtk-2.0/pages.c  30 Jan 2005 01:57:07 -0000
@@ -66,6 +66,7 @@
 static GQueue *statusbar_queue;
 static guint statusbar_timer = 0;
 
+static GtkWidget *ruleset_combo;
 
 /**************************************************************************
   spawn a server, if there isn't one, using the default settings.
@@ -881,6 +882,24 @@
   send_chat(buf);
 }
 
+/* HACK: sometimes when creating the ruleset combo the value is set without
+ * the user's control.  In this case we don't want to do a /read. */
+static bool no_ruleset_callback = FALSE;
+
+/**************************************************************************
+  Ruleset setting callback
+**************************************************************************/
+static void ruleset_callback(GtkWidget *w, gpointer data)
+{
+  const char *name;
+
+  name = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ruleset_combo)->entry));
+
+  if (name && name[0] != '\0' && !no_ruleset_callback) {
+    set_ruleset(name);
+  }
+}
+
 /**************************************************************************
   AI fill setting callback.
 **************************************************************************/
@@ -928,7 +947,7 @@
   vbox = gtk_vbox_new(FALSE, 2);
   gtk_container_add(GTK_CONTAINER(align), vbox);
 
-  table = gtk_table_new(2, 2, FALSE);
+  table = gtk_table_new(2, 3, FALSE);
   start_options_table = table;
   gtk_table_set_row_spacings(GTK_TABLE(table), 2);
   gtk_table_set_col_spacings(GTK_TABLE(table), 12);
@@ -977,6 +996,22 @@
                        NULL);
   gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
 
+  ruleset_combo = gtk_combo_new();
+  gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ruleset_combo)->entry), "default");
+  g_signal_connect(GTK_COMBO(ruleset_combo)->entry, "changed",
+                  G_CALLBACK(ruleset_callback), GUINT_TO_POINTER(i));
+
+  gtk_table_attach_defaults(GTK_TABLE(table), ruleset_combo, 1, 2, 2, 3);
+
+  label = g_object_new(GTK_TYPE_LABEL,
+                      "use-underline", TRUE,
+                      "mnemonic-widget", GTK_COMBO(ruleset_combo)->entry,
+                       "label", _("_Ruleset:"),
+                       "xalign", 0.0,
+                       "yalign", 0.5,
+                       NULL);
+  gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
+
   align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
   button = gtk_stockbutton_new(GTK_STOCK_PREFERENCES,
       _("More Game _Options..."));
@@ -1880,3 +1915,23 @@
   gtk_window_present(GTK_WINDOW(save_dialog_shell));
 }
 
+void gui_set_rulesets(int num_rulesets, char **rulesets)
+{
+  int i;
+  GList *opts = NULL;
+
+  for (i = 0; i < num_rulesets; i++){
+    opts = g_list_append(opts, rulesets[i]);
+  }
+
+  no_ruleset_callback = TRUE;
+  gtk_combo_set_popdown_strings(GTK_COMBO(ruleset_combo), opts);
+
+  /* HACK: server should tell us the current ruleset. */
+  gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ruleset_combo)->entry),
+                    "default");
+  no_ruleset_callback = FALSE;
+
+  g_list_free(opts);
+}
+
Index: client/gui-mui/connectdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/connectdlg.c,v
retrieving revision 1.14
diff -u -r1.14 connectdlg.c
--- client/gui-mui/connectdlg.c 12 Apr 2003 18:24:41 -0000      1.14
+++ client/gui-mui/connectdlg.c 30 Jan 2005 01:57:07 -0000
@@ -322,3 +322,7 @@
   try_to_autoconnect();
 }
 
+void gui_set_rulesets(char rulesets[][64], int ruleset_count)
+{
+  /* PORTME */
+}
Index: client/gui-stub/pages.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-stub/pages.c,v
retrieving revision 1.2
diff -u -r1.2 pages.c
--- client/gui-stub/pages.c     20 Oct 2004 17:38:51 -0000      1.2
+++ client/gui-stub/pages.c     30 Jan 2005 01:57:07 -0000
@@ -26,3 +26,7 @@
   /* PORTME */
 }
 
+void gui_set_rulesets(char rulesets[][64], int ruleset_count)
+{
+  /* PORTME */
+}
Index: client/include/connectdlg_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/connectdlg_g.h,v
retrieving revision 1.6
diff -u -r1.6 connectdlg_g.h
--- client/include/connectdlg_g.h       10 Apr 2004 03:47:49 -0000      1.6
+++ client/include/connectdlg_g.h       30 Jan 2005 01:57:07 -0000
@@ -19,4 +19,6 @@
 void gui_server_connect(void);
 void server_autoconnect(void);
 
+void gui_set_rulesets(int num_rulesets, char **rulesets);
+
 #endif  /* FC__CONNECTDLG_G_H */
Index: common/fc_types.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/fc_types.h,v
retrieving revision 1.13
diff -u -r1.13 fc_types.h
--- common/fc_types.h   23 Jan 2005 10:48:22 -0000      1.13
+++ common/fc_types.h   30 Jan 2005 01:57:07 -0000
@@ -42,4 +42,8 @@
 #define SP_MAX 20
 #define MAX_NUM_REQS 2
 
+#define MAX_NUM_RULESETS 16
+#define MAX_RULESET_NAME_LENGTH 64
+#define RULESET_SUFFIX ".serv"
+
 #endif /* FC__FC_TYPES_H */
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.91
diff -u -r1.91 packets.def
--- common/packets.def  29 Jan 2005 17:58:18 -0000      1.91
+++ common/packets.def  30 Jan 2005 01:57:07 -0000
@@ -83,6 +83,8 @@
 
      handle-via-packet: force the packet type of the handle
      function. Otherwise the fields are passed to the handle function.
+     This is invoked automatically for packets with more than 5 fields
+     or packets whose names are of the form foo_ruleset.
 
      handle-per-conn: normally the first parameter of the handle
      function is the player. handle-per-conn changes this to the
@@ -224,7 +226,7 @@
   Spaceship
   Ruleset
 
-The last used packet number is 114.
+The last used packet number is 115.
 ****************************************************/
 
 
@@ -1228,6 +1230,11 @@
  BOOL you_have_hack;
 end
 
+PACKET_RULESET_CHOICES=115;sc
+  UINT8 ruleset_count;
+  STRING rulesets[MAX_NUM_RULESETS:ruleset_count][MAX_RULESET_NAME_LENGTH];
+end
+
 PACKET_GAME_LOAD=111;sc,handle-via-packet,lsend
   BOOL load_successful;
   UINT8 nplayers;
Index: data/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/Makefile.am,v
retrieving revision 1.27
diff -u -r1.27 Makefile.am
--- data/Makefile.am    20 Oct 2004 03:45:19 -0000      1.27
+++ data/Makefile.am    30 Jan 2005 01:57:07 -0000
@@ -25,6 +25,7 @@
 SERVER_FILES = \
        civ1.serv \
        civ2.serv \
+       default.serv \
        history.serv
 else
 SERVER_FILES =
@@ -43,6 +44,7 @@
        helpdata.txt    \
        civ1.serv       \
        civ2.serv       \
+       default.serv    \
        history.serv
 
 if CLIENT
Index: data/default.serv
===================================================================
RCS file: data/default.serv
diff -N data/default.serv
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ data/default.serv   30 Jan 2005 01:57:07 -0000
@@ -0,0 +1,12 @@
+# Server commands to make default Freeciv rules
+#
+# You don't need this when starting the server but it can be used to restore
+# rules after they've been changed.
+#
+
+rulesetdir default
+
+# HACK: These are included to cancel out the settings from civ2.ruleset, etc.
+set researchcost 20
+set startunits ccx
+set borders 7
\ No newline at end of file
Index: data/history.serv
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/history.serv,v
retrieving revision 1.1
diff -u -r1.1 history.serv
--- data/history.serv   12 Aug 2002 20:05:47 -0000      1.1
+++ data/history.serv   30 Jan 2005 01:57:07 -0000
@@ -3,3 +3,8 @@
 # Use this as, eg, "./ser -r data/history.serv" 
 #
 rulesetdir history
+
+# HACK: These are included to cancel out the settings from civ2.ruleset, etc.
+set researchcost 20
+set startunits ccx
+set borders 7
Index: server/gamehand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gamehand.c,v
retrieving revision 1.149
diff -u -r1.149 gamehand.c
--- server/gamehand.c   22 Jan 2005 19:45:44 -0000      1.149
+++ server/gamehand.c   30 Jan 2005 01:57:08 -0000
@@ -449,6 +449,38 @@
 
 
 /************************************************************************** 
+  Call this on a connection with HACK access to send it a set of ruleset
+  choices.  Probably this should be called immediately when granting
+  HACK access to a connection.
+**************************************************************************/
+static void send_ruleset_choices(struct connection *pc)
+{
+  struct packet_ruleset_choices packet;
+  static const char **rulesets = NULL;
+  int i;
+
+  if (pc->access_level != ALLOW_HACK) {
+    freelog(LOG_ERROR, "Trying to send ruleset choices to "
+           "unprivilidged client.");
+    return;
+  }
+
+  if (!rulesets) {
+    /* This is only read once per server invocation.  Add a new ruleset
+     * and you have to restart the server. */
+    rulesets = datafilelist(RULESET_SUFFIX);
+  }
+
+  for (i = 0; i < MAX_NUM_RULESETS && rulesets[i]; i++) {
+    sz_strlcpy(packet.rulesets[i], rulesets[i]);
+  }
+  packet.ruleset_count = i;
+
+  send_packet_ruleset_choices(pc, &packet);
+}
+
+
+/************************************************************************** 
 opens a file specified by the packet and compares the packet values with
 the file values. Sends an answer to the client once it's done.
 **************************************************************************/
@@ -475,4 +507,6 @@
   }
 
   dsend_packet_single_want_hack_reply(pc, you_have_hack);
+
+  send_ruleset_choices(pc);
 }
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.381
diff -u -r1.381 stdinhand.c
--- server/stdinhand.c  22 Jan 2005 20:22:23 -0000      1.381
+++ server/stdinhand.c  30 Jan 2005 01:57:09 -0000
@@ -954,12 +954,20 @@
 bool read_init_script(struct connection *caller, char *script_filename)
 {
   FILE *script_file;
-  char real_filename[1024];
+  char tilde_filename[4096];
+  char *real_filename;
+
+  interpret_tilde(tilde_filename, sizeof(tilde_filename), script_filename);
+
+  real_filename = datafilename(tilde_filename);
+  if (!real_filename) {
+    real_filename = tilde_filename;
+  }
+
+  /* This used to print out the script_filename, but it seems more useful
+   * to show the real_filename. */
+  freelog(LOG_NORMAL, _("Loading script file: %s"), real_filename);
 
-  freelog(LOG_NORMAL, _("Loading script file: %s"), script_filename);
-  
-  interpret_tilde(real_filename, sizeof(real_filename), script_filename);
- 
   if (is_reg_file_for_access(real_filename, FALSE)
       && (script_file = fopen(real_filename, "r"))) {
     char buffer[MAX_LEN_CONSOLE_LINE];

[Prev in Thread] Current Thread [Next in Thread]