Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2002:
[Freeciv-Dev] Re: Improved game starting version 6 [patch] [ready, IMO]
Home

[Freeciv-Dev] Re: Improved game starting version 6 [patch] [ready, IMO]

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: Improved game starting version 6 [patch] [ready, IMO] (PR#1215)
From: jdorje@xxxxxxxxxxxxxxxxxxxxx
Date: Sun, 13 Jan 2002 13:04:58 -0800 (PST)

Teemu Kurppa wrote:

On Wed, 9 Jan 2002, Daniel L Speyer wrote:

On Thu, 10 Jan 2002, [iso-8859-1] Daniel Sjölie wrote:
On 2002-01-09 13:51:53, Daniel L Speyer wrote:
Would that be ftp://ftp.freeciv.org/freeciv/incoming/conndlg6.patch ? :)

How you or someone else figured out, what's wrong with the patch ? I'd
like to try it. I browsed through the patch, but didn't catch any
suspicios lines, which could cause error.

I do not know what the problem is. Probably some character is mangled by FTP and then confuses the patch program.

Here's a patch that I've created with "cvs diff" from the tarball Daniel sent. It should be identical in effect. (It'll also store the patch more permanently than the FTP server, which appears to be about ready to purge the filed.)

jason
? jason-game-2.gz
? jason-game.gz
? jason.gz
? jasongame-test.gz
? old
? rc
? test.pl
? topology
? data/lexxy
? data/lexxy.tilespec
Index: configure.in
===================================================================
RCS file: /home/freeciv/CVS/freeciv/configure.in,v
retrieving revision 1.169
diff -u -r1.169 configure.in
--- configure.in        2001/11/07 18:48:20     1.169
+++ configure.in        2002/01/13 20:54:21
@@ -486,7 +486,7 @@
 if test "x$MINGW32" != "xyes"; then
   AC_CHECK_HEADERS(arpa/inet.h netdb.h netinet/in.h pwd.h sys/ioctl.h \
                    sys/select.h sys/signal.h sys/socket.h sys/termio.h \
-                   sys/uio.h termios.h)
+                   sys/uio.h sys/wait.h termios.h)
 fi
 if test x$client = xxaw; then
   dnl Want to get appropriate -I flags:
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.105
diff -u -r1.105 civclient.c
--- client/civclient.c  2002/01/09 16:12:52     1.105
+++ client/civclient.c  2002/01/13 20:54:22
@@ -134,7 +134,7 @@
                      "Use data file FILE.tilespec for tiles\n"));
     fprintf(stderr, _("  -v, --version\t\tPrint the version number\n"));
    } else if (is_option("--version",argv[i])) {
-    fprintf(stderr, "%s %s\n", freeciv_name_version(), client_string);
+    fprintf(stderr, "%s\n", freeciv_name_version());
     exit(0);
    } else if ((option = get_option("--log",argv,&i,argc)) != NULL)
       logfile = mystrdup(option); /* never free()d */
@@ -189,7 +189,7 @@
   ui_main(argc, argv);
 
   /* termination */
-  attribute_flush();
+
   my_shutdown_network();
 
   return 0;
@@ -548,7 +548,8 @@
        server_autoconnect();
       }
     } else {
-      gui_server_connect();
+      popup_main_menu();
+      /*      gui_server_connect(); */
     }
   }
 }
Index: client/clinet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/clinet.c,v
retrieving revision 1.51
diff -u -r1.51 clinet.c
--- client/clinet.c     2001/12/09 16:02:10     1.51
+++ client/clinet.c     2002/01/13 20:54:22
@@ -82,6 +82,8 @@
 struct connection aconnection;
 static struct sockaddr_in server_addr;
 
+int game_difficulty=-1, game_aifill=-1;
+
 /**************************************************************************
   Close socket and cleanup.  This one doesn't print a message, so should
   do so before-hand if necessary.
@@ -132,6 +134,7 @@
   if (try_to_connect(name, errbuf, errbufsize) != 0) {
     return -1;
   }
+
   return 0;
 }
 
@@ -229,6 +232,29 @@
   sz_strlcpy(req.name, user_name);
   
   send_packet_req_join_game(&aconnection, &req);
+
+  if (game_aifill!=-1){
+    char buf[15];
+    struct packet_generic_message apacket;
+    sprintf(buf,"/set aifill %d",game_aifill);
+    mystrlcpy(apacket.message, buf, MAX_LEN_MSG-MAX_LEN_USERNAME+1);
+    send_packet_generic_message(&aconnection, PACKET_CHAT_MSG, &apacket);
+  }
+  if (game_difficulty==3){
+    struct packet_generic_message apacket;
+    mystrlcpy(apacket.message, "/easy", MAX_LEN_MSG-MAX_LEN_USERNAME+1);
+    send_packet_generic_message(&aconnection, PACKET_CHAT_MSG, &apacket);
+  }
+  if (game_difficulty==5){
+    struct packet_generic_message apacket;
+    mystrlcpy(apacket.message, "/normal", MAX_LEN_MSG-MAX_LEN_USERNAME+1);
+    send_packet_generic_message(&aconnection, PACKET_CHAT_MSG, &apacket);
+  }
+  if (game_difficulty==7){
+    struct packet_generic_message apacket;
+    mystrlcpy(apacket.message, "/hard", MAX_LEN_MSG-MAX_LEN_USERNAME+1);
+    send_packet_generic_message(&aconnection, PACKET_CHAT_MSG, &apacket);
+  }
 
   return 0;
 }
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.4
diff -u -r1.4 mapview_common.c
--- client/mapview_common.c     2001/12/21 16:53:10     1.4
+++ client/mapview_common.c     2002/01/13 20:54:22
@@ -271,6 +271,7 @@
         "looked at".
     e.  If none of the cities were looked at last, choose "randomly".
     f.  If no cities can work it, return NULL.
+    g.  If an invisible (enemy) city is working it, return NULL
 **************************************************************************/
 struct city *find_city_near_tile(int x, int y)
 {
@@ -292,9 +293,11 @@
   city_map_checked_iterate(x, y, city_x, city_y, map_x, map_y) {
     pcity = map_get_city(map_x, map_y);
     if (pcity && pcity->owner == game.player_idx) {
+      /* rule g */
+      if (get_worker_city(pcity, CITY_MAP_SIZE - 1 - city_x,
+                            CITY_MAP_SIZE - 1 - city_y) != C_TILE_EMPTY)
+       return(NULL);
       /* rule c */
-      assert(get_worker_city(pcity, CITY_MAP_SIZE - 1 - city_x,
-                            CITY_MAP_SIZE - 1 - city_y) == C_TILE_EMPTY);
       if (pcity == last_pcity) {
        return pcity;           /* rule d */
       }
Index: client/gui-gtk/chatline.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/chatline.c,v
retrieving revision 1.15
diff -u -r1.15 chatline.c
--- client/gui-gtk/chatline.c   2001/11/30 12:50:36     1.15
+++ client/gui-gtk/chatline.c   2002/01/13 20:54:23
@@ -32,7 +32,6 @@
 struct genlist history_list;
 int            history_pos;
 
-
 /**************************************************************************
 ...
 **************************************************************************/
Index: client/gui-gtk/connectdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/connectdlg.c,v
retrieving revision 1.28
diff -u -r1.28 connectdlg.c
--- client/gui-gtk/connectdlg.c 2001/09/08 21:14:08     1.28
+++ client/gui-gtk/connectdlg.c 2002/01/13 20:54:23
@@ -15,9 +15,28 @@
 #endif
 
 #include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
+#include<netinet/in.h>
+
+#include <sys/socket.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+/*We really can't work without this.  It's absence whould raise an error at 
configure time*/
+/*#ifdef HAVE_SYS_WAIT_H*/
+#include <sys/wait.h>
+/*#endif*/
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #include <gtk/gtk.h>
 
 #include "fcintl.h"
@@ -33,6 +52,8 @@
 #include "gui_main.h"
 #include "gui_stuff.h"
 
+#include "inputdlg.h"
+
 #include "connectdlg.h"
 
 static GtkWidget *iname, *ihost, *iport;
@@ -40,6 +61,15 @@
 
 static GtkWidget *dialog;
 
+static GtkWidget *main_menu;
+
+static int stdin_pipe[2];
+static int stderr_pipe[2];
+static int stdout_pipe[2];
+static pid_t server_pid=-1;
+
+extern int game_difficulty, game_aifill;
+
 /* meta Server */
 static int update_meta_dialog(GtkWidget *meta_list);
 static void meta_list_callback(GtkWidget *w, gint row, gint column);
@@ -47,7 +77,37 @@
 
 static int get_meta_list(GtkWidget *list, char *errbuf, int n_errbuf);
 
+/* For server sontrols */
+extern GtkWidget* message_window_button_bar; /* From gui_main.c */
+void remove_server_controls();
+
 /**************************************************************************
+ Tests if the client has started the server.
+**************************************************************************/
+int is_server_running()
+{
+  return (server_pid>0);
+}
+
+/**************************************************************************
+ Kills the server if the client has started it (atexit handler)
+**************************************************************************/
+void kill_server()
+{
+  if (is_server_running())
+    kill(server_pid,SIGTERM);
+}
+
+/*************************************************************************
+ Exit without killing the server
+*************************************************************************/
+void quit_client_only()
+{
+  server_pid=-1;
+  exit(0);
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
 static void connect_callback(GtkWidget *w, gpointer data)
@@ -120,18 +180,38 @@
   return FALSE;
 }
 
+
 /**************************************************************************
 ...
 **************************************************************************/
+static void join_game_callback(GtkWidget *w,gpointer data)
+{ 
+  if (w)
+    destroy_message_dialog(w);
+  gui_server_connect();
+}
+
+/*************************************************************************
+                                                                         
+*************************************************************************/
+static void connect_dialog_cancel(GtkWidget* w,gpointer data)
+{ 
+  gtk_widget_destroy((GtkWidget*)data);
+  popup_main_menu();
+}
+
+/*************************************************************************
+
+*************************************************************************/
 void gui_server_connect(void)
-{
+{ 
   GtkWidget *label, *table, *book, *scrolled, *list, *vbox, *update;
   static char *titles_[6]= {N_("Server Name"), N_("Port"), N_("Version"),
                            N_("Status"), N_("Players"), N_("Comment")};
   static char **titles;
   char buf [256];
   int i;
-
+  
   if (!titles) titles = intl_slist(6, titles_);
 
   gtk_widget_set_sensitive(turn_done_button, FALSE);
@@ -231,7 +311,7 @@
   GTK_WIDGET_SET_FLAGS(connw, GTK_CAN_DEFAULT);
   gtk_widget_grab_default(connw);
 
-  quitw=gtk_button_new_with_label(_("Quit"));
+  quitw=gtk_button_new_with_label(_("Cancel"));
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), quitw,
        TRUE, TRUE, 0);
   GTK_WIDGET_SET_FLAGS(quitw, GTK_CAN_DEFAULT);
@@ -247,7 +327,7 @@
   gtk_signal_connect(GTK_OBJECT(connw), "clicked",
                      GTK_SIGNAL_FUNC(connect_callback), NULL);
   gtk_signal_connect(GTK_OBJECT(quitw), "clicked",
-                     GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+                     GTK_SIGNAL_FUNC(connect_dialog_cancel), (gpointer)dialog);
 
   gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
   gtk_widget_show_all(GTK_DIALOG(dialog)->action_area);
@@ -302,6 +382,8 @@
   static int count = 0;
   static int warning_shown = 0;
 
+  /*  write(2,"|",1);*/
+
   count++;
 
   if (count >= MAX_AUTOCONNECT_ATTEMPTS) {
@@ -312,6 +394,8 @@
     exit(1);
   }
 
+  /*  write(2,"%",1);*/
+
   switch (try_to_connect(player_name, errbuf, sizeof(errbuf))) {
   case 0:                      /* Success! */
     return FALSE;              /*  Tells GTK not to call this
@@ -324,6 +408,7 @@
                             "Please start the server."));
       warning_shown = 1;
     }
+    /*    write(2,"&",1);*/
     return TRUE;               /*  Tells GTK to keep calling this function */
   default:                     /* All other errors are fatal */
     freelog(LOG_FATAL,
@@ -365,4 +450,478 @@
   if (try_to_autoconnect()) {
     gtk_timeout_add(AUTOCONNECT_INTERVAL, try_to_autoconnect, NULL);
   }
+}
+
+/**************************************************************************
+  Sends a server command to the stdin pipe
+**************************************************************************/
+void send_server_commandline(char *s)
+{
+  write(stdin_pipe[1],s,strlen(s));
+  write(stdin_pipe[1],"\n",1);
+}
+
+/*************************************************************************
+ Callback for buttons in the server window
+*************************************************************************/
+static void server_command_button_callback(GtkWidget *w,gpointer data)
+{
+  send_server_commandline((char *)data);
+}
+
+/**************************************************************************
+ SIGCHLD handler
+**************************************************************************/
+static RETSIGTYPE server_exit_signal(int signo)
+{
+  const char *message=N_("Server has terminated\n");
+  if (is_server_running()) {
+    if (server_pid==waitpid(server_pid,NULL,WNOHANG)) {
+      server_pid=-1;
+      /* Notify the gui to disable buttons
+         Calling update_server_buttons() here leads to X11
+         networking problems like this:
+         Xlib: unexpected async reply (sequence 0x1499f)!
+       */
+      write(stdout_pipe[1],_(message),strlen(_(message))); /*RE-EXAMINE!*/
+
+      close(stdin_pipe[0]);
+      close(stdin_pipe[1]);
+      close(stdout_pipe[0]);
+      close(stdout_pipe[1]);
+      close(stderr_pipe[0]);
+      close(stderr_pipe[1]);
+    }
+  }
+  remove_server_controls();
+}
+
+/*********************************************************************
+ Removes the server controls (when the server quits)
+*********************************************************************/
+void remove_server_controls(){
+  GtkWidget *parent;
+  parent=message_window_button_bar->parent;
+  gtk_widget_destroy(message_window_button_bar);
+  message_window_button_bar=gtk_vbox_new(0,0);
+  gtk_box_pack_start(GTK_BOX(parent),message_window_button_bar,0,0,0);
+  gtk_widget_show(message_window_button_bar);
+}
+
+/*********************************************************************
+ Finishes saving a game (after the dialog)
+*********************************************************************/
+void savegame_callback(GtkWidget *w, gpointer data){
+  char buf[512];
+  sprintf(buf,"save 
%s\n",gtk_file_selection_get_filename(GTK_FILE_SELECTION(data)));
+  write(stdin_pipe[1],buf,strlen(buf));
+  gtk_widget_destroy(data);
+}
+
+/*********************************************************************
+ Pops up a save dialog and then save under the chosen name
+*********************************************************************/
+void save_game(GtkWidget *w, gpointer data){
+  GtkWidget *filesel; 
+  filesel=gtk_file_selection_new(_("Select a name to save under"));
+  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
+                    "clicked",GTK_SIGNAL_FUNC(savegame_callback),filesel);
+  gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)
+                                      ->ok_button),"clicked",
+                           GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                           (gpointer)filesel);
+  gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)
+                                      ->cancel_button),"clicked",
+                           GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                           (gpointer)filesel);
+  gtk_widget_show(filesel);
+}  
+
+/**********************************************************************
+ Fills the already made vbox for server control with appropriate buttons
+**********************************************************************/
+void add_server_ctrl_buttons(){
+  GtkWidget *wid;
+  char *tmp;
+  tmp=(char*)malloc(15*sizeof(char));
+  sprintf(tmp,"Port: %d",server_port);
+  wid=gtk_label_new(tmp);
+  free(tmp);
+  gtk_box_pack_start(GTK_BOX(message_window_button_bar),wid,0,0,0);
+  wid=gtk_button_new_with_label(_("Start Game"));
+  gtk_signal_connect(GTK_OBJECT(wid),"clicked",
+                    GTK_SIGNAL_FUNC(server_command_button_callback), 
"start\n");
+  gtk_box_pack_start(GTK_BOX(message_window_button_bar),wid,0,0,0);
+  wid=gtk_button_new_with_label(_("Save Game"));
+  gtk_signal_connect(GTK_OBJECT(wid),"clicked",
+                    GTK_SIGNAL_FUNC(save_game),NULL);
+  gtk_box_pack_start(GTK_BOX(message_window_button_bar),wid,0,0,0);
+  wid=gtk_button_new_with_label(_("End Game"));
+  gtk_signal_connect(GTK_OBJECT(wid),"clicked",
+                    GTK_SIGNAL_FUNC(server_command_button_callback), "quit\n");
+  gtk_box_pack_start(GTK_BOX(message_window_button_bar),wid,0,0,0);
+  wid=gtk_button_new_with_label(_("Get Score"));
+  gtk_signal_connect(GTK_OBJECT(wid),"clicked",
+                    GTK_SIGNAL_FUNC(server_command_button_callback), 
"score\n");
+  gtk_box_pack_start(GTK_BOX(message_window_button_bar),wid,0,0,0);
+  gtk_widget_show_all(GTK_WIDGET(message_window_button_bar));
+}
+
+/***********************************************************************
+ Handles receiving player name
+***********************************************************************/
+void chosen_name_callback(GtkWidget *w, gpointer data){
+  char *name,c;
+  int i;
+  GList *node_i, *old;
+  /*  write(2,"#",1);*/
+  name=((GList*)data)->data;
+  for(i=strlen(name);name[i]!='(';i--);
+  name[i-1]=0;
+  strcpy(player_name,name);
+  old=((GList*)data)->next;
+  gtk_widget_destroy((GtkWidget*)(old->data));
+  for(node_i=old->next;node_i;node_i=node_i->next){
+    free(old);
+    free(node_i->data);
+    old=node_i;
+  }
+  free(old);
+  write(stdin_pipe[1],"set autotoggle 1\n",17); /*Likely to be useful*/
+  c=0;
+  while(!read(stdout_pipe[0],&c,1) || c!='>') /*Wait for responce from the 
server*/
+    /*write(2,&c,1)*/;
+    /*    usleep(c=='%'?1:2);*/
+  write(stdin_pipe[1],"cmdlevel hack first\n",14);
+  c=0;
+  while(!read(stdout_pipe[0],&c,1) || c!='>'); /*Wait for responce from the 
server*/  server_autoconnect();
+  add_server_ctrl_buttons();
+}
+
+
+/************************************************************************
+ Gets the player name for a loaded game
+************************************************************************/
+
+void get_player_name(){
+  char *buf=malloc(1024*sizeof(char));
+  int i,j,tmpi;
+  GtkWidget *win, *box, *lab, *but;
+  /*********************************************************************
+   * OK, so you're probably wondering what's going on.  Here's the problem:
+   * each button must receive its name *and* a pointer to this window (to
+   * destroy it).  Furthermore, nothing can be put on the stack, or it will
+   * be lost.  This means that buf will require de-allocation.  Now, to pass 
+   * this many things requires objects or some sort, and *those* will need
+   * de-allocating too, even the ones which aren't used.
+   *
+   * So, I've built everything out of GLists (essentially conses).  It looks 
like
+   * this:
+   *       argument passed             other button's node         other 
button's node
+   *            |
+   *            V                             ^                         ^ 
+   *     (name, --)-> (win, --)-> (buf,--)-> (|,--)-> ... (|,--)-> ... 
(|,--)-~~~~
+   *          ^                                            |
+   *          \--------------------------------------------/
+   *
+   * So everything can be cleaned up in the end.  Simply, eh?
+   ********************************************************************/
+  GList *head, *tail, *tmp;
+  win=gtk_window_new(0);
+  gtk_window_set_title(GTK_WINDOW(win),_("Select connection"));
+  head=(GList*)malloc(sizeof(GList));
+  head->data=win;
+  tail=(GList*)malloc(sizeof(GList));
+  tail->data=buf;
+  head->next=tail;
+  tail->next=NULL;
+  box=gtk_vbox_new(0,0);
+  lab=gtk_label_new(_("Choose player to be"));
+  gtk_box_pack_start(GTK_BOX(box),lab,0,0,0);
+  gtk_container_add(GTK_CONTAINER(win),box);
+  write(stdin_pipe[1],"list\n",5);
+  /*  write(2,"$",1);*/
+  while(buf[(tmpi=read(stdout_pipe[0],buf,1024)) -5]!='-')
+    /*   write(2,buf,tmpi)*/;
+  for(i=5;i<1024;i++)
+    if (buf[i-2]=='-' && buf[i-1]=='-' && buf[i]=='\n')
+      break;
+  i++;
+  while(buf[i]!='-'){
+    for(j=i;j<1024;j++)
+      if (buf[j]=='\n')
+       break;
+    buf[j]=0;
+    but=gtk_button_new_with_label(buf+i);
+    gtk_object_set_user_data(GTK_OBJECT(but),buf+i);
+    tmp=(GList*)malloc(sizeof(GList));
+    tmp->data=buf+i;
+    tmp->next=head;
+    tail->next=(GList*)malloc(sizeof(GList));
+    tail=tail->next;
+    tail->data=tmp;
+    tail->next=NULL;
+    gtk_signal_connect(GTK_OBJECT(but),"clicked",
+                      GTK_SIGNAL_FUNC(chosen_name_callback), tmp);
+    gtk_box_pack_start(GTK_BOX(box),but,0,0,0);
+    i=j+1;
+  }
+  gtk_widget_show_all(win);
+}
+
+/*************************************************************************
+ Starts the server.
+*************************************************************************/
+static void start_server(char **argv)
+{
+  if (pipe(stdin_pipe)) {
+    freelog(LOG_FATAL,_("Cannot create pipe"));
+    exit(1);
+  }
+  if (pipe(stdout_pipe)) {
+    freelog(LOG_FATAL,_("Cannot create pipe"));
+    exit(1);
+  }
+  if (pipe(stderr_pipe)) {
+    freelog(LOG_FATAL,_("Cannot create pipe"));
+    exit(1);
+  }
+
+  signal(SIGCHLD,server_exit_signal);
+
+  server_pid=fork();
+
+  if (server_pid==0) {
+
+    /* redirecting stdio */
+    dup2(stdout_pipe[1],1);
+    dup2(stderr_pipe[1],2);
+    dup2(stdin_pipe[0],0);
+    
+    execvp("./ser",argv);
+    execvp("./server/civserver",argv);
+    execvp("civserver",argv);
+    /* This line is only reached if civserver cannot be started. 
+       Calling exit here is dangerous due to X11 problems
+       (async replies) */
+    _exit(1);
+  }
+  /*  write(stdin_pipe[1],"set autotoggle 1\ncmdlevel hack\n",31); Likely to 
be useful*/
+  if (argv[3]){ /* loading a file */
+    get_player_name();
+  }else{
+    char c;
+    write(stdin_pipe[1],"cmdlevel hack first\n",20);
+    server_autoconnect();
+    c=' ';
+    while(!read(stdout_pipe[0],&c,1) || c!='>'); /*Wait for responce from the 
server*/
+    write(stdin_pipe[1],"set autotoggle 1\n",17);
+    add_server_ctrl_buttons();
+  }
+}
+
+/**************************************************************************
+ Finds the lowest port which can be used for the server (starting at the 
default 5555)
+**************************************************************************/
+int min_free_port()
+{
+  int port, n, s;
+  struct sockaddr_in tmp;
+  s=socket(AF_INET, SOCK_STREAM, 0);
+  n=INADDR_ANY;
+  port=5554; /* make looping convinient */
+  do{
+    port++;
+    /*    fprintf(stderr,"Trying %d...\n",port);*/
+    memset(&tmp,0,sizeof(struct sockaddr_in));
+    tmp.sin_family=AF_INET;
+    tmp.sin_port=htons(port);
+    memcpy(&tmp.sin_addr, &n, sizeof(long));
+  }while( bind(s,(struct sockaddr*) &tmp, sizeof(struct sockaddr_in)) );
+  close(s);
+  /*  fprintf(stderr,"Returning %d\n",port);*/
+  return(port);
+}
+
+/**************************************************************************
+ Starts the server without arguments.
+**************************************************************************/
+void start_server_for_new_game()
+{
+  char *argv[4];
+  argv[0]="civserver";
+  argv[1]="-p";
+  argv[2]=malloc(6*sizeof(char)); /* This is a memory leak, but it's small, 
and one time, and 
+                                    I'm not sure when it would be safe to 
free() */ 
+  sprintf(argv[2],"%d",server_port);
+  argv[3]=NULL;
+  start_server(argv);
+}
+
+/*************************************************************************
+ Starts the server with -f option to load a game
+*************************************************************************/
+void start_server_load_game(char *filename)
+{
+  char *argv[5];
+  argv[0]="civserver";
+  argv[1]="-f";
+  argv[2]=filename;
+  argv[3]="-p";
+  argv[4]=malloc(6*sizeof(char)); /*Yes it's a memory leak*/
+  sprintf(argv[4],"%d",server_port);
+  argv[5]=NULL;
+  start_server(argv);
+}
+
+/**************************************************************************
+The callback is broken up so that the load dialog will disappear quickly, 
+in accordance with the UI principle of instant notification.
+**************************************************************************/
+static int filesel_callback2(gpointer data)
+{
+  gtk_widget_destroy(main_menu);
+  gtk_widget_set_sensitive(top_vbox,TRUE);
+  server_port=min_free_port();
+  start_server_load_game((char*)data);
+  free(data);
+  return(FALSE);
+}
+
+
+/**************************************************************************
+
+**************************************************************************/
+static void filesel_callback(GtkWidget *w,gpointer data)
+{
+  char *filename=malloc(255*sizeof(char));
+  strcpy(filename,gtk_file_selection_get_filename(GTK_FILE_SELECTION(data)));
+  gtk_timeout_add(1,filesel_callback2,filename);
+}
+
+
+/**************************************************************************
+
+**************************************************************************/
+static void load_game_callback(GtkWidget *w,gpointer data)
+{
+  GtkWidget *filesel; 
+  
+  filesel=gtk_file_selection_new(_("Please select a game file to load"));
+  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
+                    "clicked",GTK_SIGNAL_FUNC(filesel_callback),filesel);
+  gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)
+                                      ->ok_button),"clicked",
+                           GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                           (gpointer)filesel);
+  gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)
+                                      ->cancel_button),"clicked",
+                           GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                           (gpointer)filesel);
+  gtk_widget_show(filesel);
+}
+
+/**************************************************************************
+ Callback for the new game button 
+**************************************************************************/
+static void new_game_ok_callback(GtkWidget *w,gpointer data)
+{
+  GtkWidget **passed=data;
+  strcpy(player_name,gtk_entry_get_text(GTK_ENTRY(passed[0])));
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(passed[1])))
+    game_difficulty=3;
+  else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(passed[2])))
+    game_difficulty=5;
+  else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(passed[3])))
+    game_difficulty=7;
+  game_aifill=gtk_range_get_adjustment(GTK_RANGE(passed[4]))->value;
+  gtk_widget_destroy(main_menu);
+  gtk_widget_destroy(GTK_WIDGET(GTK_DIALOG(passed[5])));
+  free(data);
+  server_port=min_free_port();
+  start_server_for_new_game();
+}
+
+/**************************************************************************
+
+**************************************************************************/
+static void new_game_cancel_callback(GtkWidget *w, gpointer data)
+{
+  gtk_widget_destroy(*( ((GtkWidget**)data) +5));
+  free(data);
+}
+
+/**************************************************************************
+
+**************************************************************************/
+static void new_game_callback(GtkWidget *w,gpointer data)
+{
+  GtkWidget *diag,*hbox,*lab,*name,*radio,*scale,*ok,*canc;
+  GSList *difficulty;
+  GtkWidget **pass=(GtkWidget**)malloc(6*sizeof(GtkWidget*));
+
+  pass[5]=diag=gtk_dialog_new();
+  gtk_window_set_title(GTK_WINDOW(diag),_("Start New Game"));
+
+  hbox=gtk_hbox_new(0,0);
+  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(diag)->vbox), hbox, 0,0,5);
+  lab=gtk_label_new(_("Your name:"));
+  gtk_box_pack_start(GTK_BOX(hbox), lab, 0,0,5);
+  pass[0]=name=gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(name),player_name);
+  gtk_box_pack_end(GTK_BOX(hbox), name, 0,0,5);
+
+  hbox=gtk_hbox_new(0,0);
+  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(diag)->vbox), hbox, 0,0,0);
+  lab=gtk_label_new(_("Difficulty:"));
+  gtk_box_pack_start(GTK_BOX(hbox), lab, 0,0,5);
+  pass[3]=radio=gtk_radio_button_new_with_label(NULL,"hard");
+  difficulty=gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
+  gtk_box_pack_end(GTK_BOX(hbox), radio, 0,0,5);
+  
pass[2]=radio=gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(radio)),
+                                               "medium");
+  gtk_box_pack_end(GTK_BOX(hbox), radio, 0,0,0);
+  
pass[1]=radio=gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(radio)),
+                                               "easy");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio),1);
+  gtk_box_pack_end(GTK_BOX(hbox), radio, 0,0,0);
+
+  hbox=gtk_hbox_new(0,0);
+  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(diag)->vbox), hbox, 0,0,0);
+  lab=gtk_label_new(_("Total players (fill with AIs):"));
+  gtk_box_pack_start(GTK_BOX(hbox), lab, 0,0,5);
+  
pass[4]=scale=gtk_hscale_new(GTK_ADJUSTMENT(gtk_adjustment_new(5,0,30,1,5,0)));
+  gtk_scale_set_digits(GTK_SCALE(scale),0);
+  gtk_widget_set_usize(scale,90,0);
+  gtk_box_pack_end(GTK_BOX(hbox), scale, 0,0,5);
+
+  ok=gtk_button_new_with_label(_("OK"));
+  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(diag)->action_area), ok, 0,0,0);
+  canc=gtk_button_new_with_label(_("Cancel"));
+  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(diag)->action_area), canc, 0,0,0);
+
+  gtk_signal_connect(GTK_OBJECT(ok),"clicked",
+                    GTK_SIGNAL_FUNC(new_game_ok_callback),pass);
+  gtk_signal_connect(GTK_OBJECT(canc),"clicked",
+                    GTK_SIGNAL_FUNC(new_game_cancel_callback),pass);
+  
+  gtk_widget_show_all(diag);
+}
+
+/**************************************************************************
+
+**************************************************************************/
+void popup_main_menu()
+{
+  main_menu=popup_message_dialog(top_vbox,
+                                _("Start a game"),
+                                _("What do you wish to to?"),
+                                _("New Game"),new_game_callback,NULL,
+                                _("Load Game"),load_game_callback,NULL,
+                                _("Join Game"),join_game_callback,NULL,
+                                _("Quit Game"),gtk_main_quit,NULL,
+                                NULL);
+  gtk_widget_set_sensitive(top_vbox,FALSE);
+  gtk_signal_connect(GTK_OBJECT(main_menu),"delete_event",
+                    GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
 }
Index: client/gui-gtk/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/gui_main.c,v
retrieving revision 1.94
diff -u -r1.94 gui_main.c
--- client/gui-gtk/gui_main.c   2001/12/21 11:17:34     1.94
+++ client/gui-gtk/gui_main.c   2002/01/13 20:54:24
@@ -130,6 +130,9 @@
 
 GdkWindow *    root_window;
 
+/* VBox into which server controls can be put */
+GtkWidget *     message_window_button_bar;
+
 /* ids of the units icons in information display: (or 0) */
 static int unit_ids[MAX_NUM_UNITS_BELOW];  
 
@@ -657,6 +660,10 @@
 
       /* the chat line */
       inputline = gtk_entry_new();
+
+      message_window_button_bar=gtk_vbox_new(0,0); /*We'll fill it later, if 
we want to*/
+      gtk_box_pack_start(GTK_BOX(hbox),message_window_button_bar,0,0,0);
+
       gtk_box_pack_start(GTK_BOX(avbox), inputline, FALSE, FALSE, 0);
   }
   gtk_signal_connect(GTK_OBJECT(toplevel), "key_press_event",
Index: client/gui-gtk/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/menu.c,v
retrieving revision 1.59
diff -u -r1.59 menu.c
--- client/gui-gtk/menu.c       2001/10/26 08:07:13     1.59
+++ client/gui-gtk/menu.c       2002/01/13 20:54:25
@@ -32,6 +32,7 @@
 #include "cityrep.h"
 #include "civclient.h"
 #include "clinet.h"
+#include "connectdlg.h"
 #include "control.h"
 #include "dialogs.h"
 #include "finddlg.h"
@@ -71,6 +72,7 @@
   MENU_GAME_OUTPUT_LOG,
   MENU_GAME_CLEAR_OUTPUT,
   MENU_GAME_DISCONNECT,
+  MENU_GAME_QUIT_CLIENT,
   MENU_GAME_QUIT,
   
   MENU_KINGDOM_TAX_RATE,
@@ -184,6 +186,9 @@
   case MENU_GAME_DISCONNECT:
     disconnect_from_server();
     break;
+  case MENU_GAME_QUIT_CLIENT:
+    quit_client_only();
+    break;
   case MENU_GAME_QUIT:
     exit(0);
     break;
@@ -567,7 +572,9 @@
   { "/" N_("Game") "/sep4",                            NULL,
        NULL,                   0,                                      
"<Separator>"   },
   { "/" N_("Game") "/" N_("_Disconnect"),              NULL,
-       game_menu_callback,     MENU_GAME_DISCONNECT                            
        },
+        game_menu_callback,    MENU_GAME_DISCONNECT                            
        },
+  { "/" N_("Game") "/" N_("Quit client only"),          NULL,
+    game_menu_callback,     MENU_GAME_QUIT_CLIENT                              
         },
   { "/" N_("Game") "/" N_("_Quit"),                    "<control>q",
        gtk_main_quit,          0                                               
        },
   /* Kingdom menu ... */
@@ -955,6 +962,8 @@
 *****************************************************************/
 void update_menus(void)
 {
+  menus_set_sensitive("<main>/_Game/Quit client only", is_server_running());
+  menus_set_sensitive("<main>/_Game/_Disconnect",!is_server_running());
   if(get_client_state()!=CLIENT_GAME_RUNNING_STATE) {
     menus_set_sensitive("<main>/_Reports", FALSE);
     menus_set_sensitive("<main>/_Kingdom", FALSE);
Index: client/include/connectdlg_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/connectdlg_g.h,v
retrieving revision 1.2
diff -u -r1.2 connectdlg_g.h
--- client/include/connectdlg_g.h       2001/08/28 18:41:57     1.2
+++ client/include/connectdlg_g.h       2002/01/13 20:54:26
@@ -15,5 +15,14 @@
 
 void gui_server_connect(void);
 void server_autoconnect(void);
+int is_server_running(void);
+void kill_server(void);
+void quit_client_only(void);
+void show_server_window(void);
+void send_server_commandline(char *s);
+void start_server_for_new_game(void);
+void start_server_load_game(char *filename);
+void popup_main_menu(void);
+
 
 #endif  /* FC__CONNECTDLG_G_H */

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