Crossfire Client, Branches  R11627
metaserver.c
Go to the documentation of this file.
1 const char * const rcsid_gtk2_metaserver_c =
2  "$Id: metaserver.c 9201 2008-06-01 17:32:45Z anmaster $";
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2005 Mark Wedel & Crossfire Development Team
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22  The author can be reached via e-mail to crossfire@metalforge.org
23 */
24 
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34 
35 #include <gtk/gtk.h>
36 #include <glade/glade.h>
37 
38 #include "client.h"
39 
40 #include "image.h"
41 #include "gtk2proto.h"
42 #include "metaserver.h"
43 #include "main.h"
44 #include <pthread.h>
45 
48 static GtkListStore *store_metaserver;
49 static GtkTreeSelection *metaserver_selection;
50 
51 enum {
53 };
54 
67  GtkTreeSelection *selection,
68  GtkTreeModel *model,
69  GtkTreePath *path,
70  gboolean path_currently_selected,
71  gpointer userdata)
72 {
73  gtk_widget_set_sensitive(metaserver_button, TRUE);
74  gtk_entry_set_text(GTK_ENTRY(metaserver_entry), "");
75 
76  return TRUE;
77 }
78 
82 void get_metaserver(void)
83 {
84  static int has_init=0;
85  GtkTreeIter iter;
86  int i, j;
87  const gchar *metaserver_txt;
88  GladeXML *xml_tree;
89  GtkWidget *widget;
90 
91  if (!has_init) {
92  GtkTreeViewColumn *column;
93  GtkCellRenderer *renderer;
94 
95  metaserver_window = glade_xml_get_widget (dialog_xml,
96  "metaserver_window");
97  xml_tree = glade_get_widget_tree(GTK_WIDGET(metaserver_window));
98 
99  gtk_window_set_transient_for(GTK_WINDOW(metaserver_window), GTK_WINDOW(window_root));
100 
101  treeview_metaserver = glade_xml_get_widget(xml_tree,
102  "treeview_metaserver");
104  glade_xml_get_widget(xml_tree, "metaserver_select");
106  glade_xml_get_widget(xml_tree, "metaserver_status");
108  glade_xml_get_widget(xml_tree, "metaserver_text_entry");
109 
110  g_signal_connect ((gpointer) metaserver_window, "destroy",
111  G_CALLBACK (on_window_destroy_event), NULL);
112  g_signal_connect ((gpointer) treeview_metaserver, "row_activated",
113  G_CALLBACK (on_treeview_metaserver_row_activated), NULL);
114  g_signal_connect ((gpointer) metaserver_entry, "activate",
115  G_CALLBACK (on_metaserver_text_entry_activate), NULL);
116  g_signal_connect ((gpointer) metaserver_entry, "key_press_event",
117  G_CALLBACK (on_metaserver_text_entry_key_press_event), NULL);
118  g_signal_connect ((gpointer) metaserver_button, "clicked",
119  G_CALLBACK (on_metaserver_select_clicked), NULL);
120 
121  widget = glade_xml_get_widget(xml_tree, "button_metaserver_quit");
122  g_signal_connect ((gpointer) widget, "pressed",
123  G_CALLBACK (on_button_metaserver_quit_pressed), NULL);
124  g_signal_connect ((gpointer) widget, "activate",
125  G_CALLBACK (on_button_metaserver_quit_pressed), NULL);
126 
127  store_metaserver = gtk_list_store_new (6,
128  G_TYPE_STRING,
129  G_TYPE_STRING,
130  G_TYPE_INT,
131  G_TYPE_INT,
132  G_TYPE_STRING,
133  G_TYPE_STRING);
134 
135  gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_metaserver), GTK_TREE_MODEL(store_metaserver));
136 
137  renderer = gtk_cell_renderer_text_new ();
138  column = gtk_tree_view_column_new_with_attributes ("Hostname", renderer,
139  "text", LIST_HOSTNAME,
140  NULL);
141  gtk_tree_view_column_set_sort_column_id(column, LIST_HOSTNAME);
142  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_metaserver), column);
143 
144  renderer = gtk_cell_renderer_text_new ();
145  column = gtk_tree_view_column_new_with_attributes ("Updated (Sec)", renderer,
146  "text", LIST_IDLETIME,
147  NULL);
148  gtk_tree_view_column_set_sort_column_id(column, LIST_IDLETIME);
149  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_metaserver), column);
150 
151  renderer = gtk_cell_renderer_text_new ();
152  column = gtk_tree_view_column_new_with_attributes ("Players", renderer,
153  "text", LIST_PLAYERS,
154  NULL);
155  gtk_tree_view_column_set_sort_column_id(column, LIST_PLAYERS);
156  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_metaserver), column);
157 
158  renderer = gtk_cell_renderer_text_new ();
159  column = gtk_tree_view_column_new_with_attributes ("Version", renderer,
160  "text", LIST_VERSION,
161  NULL);
162  gtk_tree_view_column_set_sort_column_id(column, LIST_VERSION);
163  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_metaserver), column);
164 
165  renderer = gtk_cell_renderer_text_new ();
166  column = gtk_tree_view_column_new_with_attributes ("Server Comment", renderer,
167  "text", LIST_COMMENT,
168  NULL);
169  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_metaserver), column);
170 
171  gtk_widget_realize(metaserver_window);
172  metaserver_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_metaserver));
173  gtk_tree_selection_set_mode (metaserver_selection, GTK_SELECTION_BROWSE);
174  gtk_tree_selection_set_select_function(metaserver_selection, metaserver_selection_func, NULL, NULL);
175 
176  has_init=1;
177  }
178  gtk_widget_show(metaserver_window);
179 
180  gtk_label_set_text(GTK_LABEL(metaserver_status), "Waiting for data from metaserver");
181 
182  metaserver_txt = gtk_entry_get_text(GTK_ENTRY(metaserver_entry));
183  if (*metaserver_txt == '\0') {
184  gtk_widget_set_sensitive(metaserver_button, FALSE);
185  } else {
186  gtk_widget_set_sensitive(metaserver_button, TRUE);
187  }
188 
189  gtk_list_store_clear(store_metaserver);
190 
191  while (metaserver_check_status()) {
192  usleep(100);
193  gtk_main_iteration_do(FALSE);
194  }
195 
196  pthread_mutex_lock(&ms2_info_mutex);
197 
198  if (cached_servers_num) {
199  for ( i = 0; i < cached_servers_num; i++ ) {
200  for (j=0; j < meta_numservers; j++) {
201  if (!strcmp(cached_servers_name[i], meta_servers[j].hostname))
202  break;
203  }
204  if (j == meta_numservers) {
205  gtk_list_store_append(store_metaserver, &iter);
206  gtk_list_store_set(store_metaserver, &iter,
209  LIST_COMMENT, "Cached server entry",
210  -1);
211  }
212  }
213  }
214 
215  qsort(meta_servers, meta_numservers, sizeof(Meta_Info), (int (*)(const void *, const void *))meta_sort);
216 
217  for (i=0; i<meta_numservers; i++) {
218  if (check_server_version(i)){
219  gtk_list_store_append(store_metaserver, &iter);
220  gtk_list_store_set(store_metaserver, &iter,
221  LIST_HOSTNAME, meta_servers[i].hostname,
222  LIST_IPADDR, meta_servers[i].hostname,
223  LIST_IDLETIME, meta_servers[i].idle_time,
224  LIST_PLAYERS, meta_servers[i].num_players,
225  LIST_VERSION, meta_servers[i].version,
226  LIST_COMMENT, meta_servers[i].text_comment,
227  -1);
228  }
229  }
230  pthread_mutex_unlock(&ms2_info_mutex);
231  if (server) {
232  gtk_list_store_append(store_metaserver, &iter);
233  gtk_list_store_set(store_metaserver, &iter,
235  LIST_COMMENT, "default server",
236  -1);
237  }
238 
240  gtk_label_set_text(GTK_LABEL(metaserver_status), "Waiting for user selection");
241 
243  /* draw_map() is to just redraw the splash */
244  draw_map(FALSE);
245  gtk_main();
246 
247  gtk_widget_hide(metaserver_window);
248 }
249 
256 void
257 on_metaserver_select_clicked (GtkButton *button,
258  gpointer user_data)
259 {
260  GtkTreeModel *model;
261  GtkTreeIter iter;
262  char *name=NULL, *ip=NULL, buf[256], *metaserver_txt;
263 
264  metaserver_txt = (char*)gtk_entry_get_text(GTK_ENTRY(metaserver_entry));
265  if (gtk_tree_selection_get_selected (metaserver_selection, &model, &iter)) {
266  gtk_tree_model_get(model, &iter, LIST_HOSTNAME, &name, LIST_IPADDR, &ip, -1);
267 
268  } else if (*metaserver_txt == '\0') {
269 
270  /* This can happen if user blanks out server name text field then hits
271  * the connect button.
272  */
273  gtk_label_set_text(GTK_LABEL(metaserver_status), "Error - nothing selected!\n");
274  gtk_widget_set_sensitive(metaserver_button, FALSE);
275  return;
276  } else {
277  /* This shouldn't happen because the button should not be pressable
278  * until the user selects something
279  */
280  gtk_label_set_text(GTK_LABEL(metaserver_status), "Error - nothing selected!\n");
281  }
282  if (!name) name = metaserver_txt;
283 
284  snprintf(buf, 255, "Trying to connect to %s", name);
285 
286  gtk_label_set_text(GTK_LABEL(metaserver_status), buf);
287 
289  if (csocket.fd==-1) {
290  snprintf(buf, 255, "Unable to connect to %s!", name);
291  gtk_label_set_text(GTK_LABEL(metaserver_status), buf);
292  } else {
293  snprintf(buf, 255, "Connected to %s!", name);
294  gtk_label_set_text(GTK_LABEL(metaserver_status), buf);
295  gtk_main_quit();
297  }
298 }
299 
308 static void metaserver_connect_to(const char *name, const char *ip)
309 {
310  char buf[256], *cp, newname[256];
311  int port=use_config[CONFIG_PORT];
312 
313  snprintf(buf, 255, "Trying to connect to %s", name);
314 
315  gtk_label_set_text(GTK_LABEL(metaserver_status), buf);
316  strncpy(newname, name, 255);
317  newname[255]=0;
318 
319  if ((cp=strchr(newname,':'))!=NULL) {
320  port = atoi(cp+1);
321  *cp=0;
322  }
323 
324  csocket.fd=init_connection((char*)(ip?ip:newname), port);
325  if (csocket.fd==-1) {
326  snprintf(buf, 255, "Unable to connect to %s!", name);
327  gtk_label_set_text(GTK_LABEL(metaserver_status), buf);
328  } else {
329  snprintf(buf, 255, "Connected to %s!", name);
330  gtk_label_set_text(GTK_LABEL(metaserver_status), buf);
331  gtk_main_quit();
333  }
334 }
335 
345 void
347  GtkTreePath *path,
348  GtkTreeViewColumn *column,
349  gpointer user_data)
350 {
351  GtkTreeIter iter;
352  GtkTreeModel *model;
353  char *name, *ip;
354 
355  model = gtk_tree_view_get_model(treeview);
356  if (gtk_tree_model_get_iter(model, &iter, path)) {
357  gtk_tree_model_get(model, &iter, LIST_HOSTNAME, &name, LIST_IPADDR, &ip, -1);
358  metaserver_connect_to(name, ip);
359  }
360 }
361 
369 void
371  gpointer user_data)
372 {
373  const gchar *entry_text;
374 
375  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
376 
377  metaserver_connect_to(entry_text, NULL);
378 }
379 
387 void
389  gpointer user_data)
390 {
391 #ifdef WIN32
392  script_killall();
393 #endif
394  exit(0);
395 }
396 
406 gboolean
408  (GtkWidget *widget,
409  GdkEventKey *event,
410  gpointer user_data)
411 {
412 
413  gtk_widget_set_sensitive(metaserver_button, TRUE);
414  gtk_tree_selection_unselect_all(metaserver_selection);
415  return FALSE;
416 }
char * cached_servers_ip[CACHED_SERVERS_MAX]
Definition: metaserver.c:105
void on_window_destroy_event(GtkObject *object, gpointer user_data)
Definition: main.c:162
static GtkWidget * treeview_metaserver
Definition: metaserver.c:46
static XEvent event
Definition: x11.c:193
void enable_menu_items(int enable)
Definition: menubar.c:121
gboolean on_metaserver_text_entry_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
Definition: metaserver.c:408
static GtkWidget * metaserver_window
Definition: metaserver.c:46
ClientSocket csocket
Definition: client.c:78
char * server
Definition: client.c:56
static GtkWidget * metaserver_entry
Definition: metaserver.c:46
GladeXML * dialog_xml
Definition: main.c:57
void on_metaserver_select_clicked(GtkButton *button, gpointer user_data)
Definition: metaserver.c:257
int init_connection(char *host, int port)
Definition: client.c:205
static GtkWidget * metaserver_button
Definition: metaserver.c:46
Meta_Info * meta_servers
Definition: metaserver.c:55
void on_metaserver_text_entry_activate(GtkEntry *entry, gpointer user_data)
Definition: metaserver.c:370
#define TRUE
Definition: client-types.h:71
void on_treeview_metaserver_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
Definition: metaserver.c:346
GtkWidget * window_root
Definition: main.c:56
static GtkWidget * metaserver_status
Definition: metaserver.c:46
#define CONFIG_PORT
Definition: client.h:174
void get_metaserver(void)
Definition: metaserver.c:82
sint16 use_config[CONFIG_NUMS]
Definition: init.c:50
Client_Player cpl
Definition: client.c:77
static int meta_sort(Meta_Info *m1, Meta_Info *m2)
Definition: metaserver.h:76
pthread_mutex_t ms2_info_mutex
Definition: metaserver.c:171
int check_server_version(int entry)
Definition: metaserver.c:69
char * name
Definition: image.c:61
const char *const rcsid_gtk2_metaserver_c
Definition: metaserver.c:1
gboolean metaserver_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata)
Definition: metaserver.c:66
int fd
Definition: client.h:97
int cached_servers_num
Definition: metaserver.c:103
char * cached_servers_name[CACHED_SERVERS_MAX]
Definition: metaserver.c:104
static GtkTreeSelection * metaserver_selection
Definition: metaserver.c:49
static int has_init
Definition: spells.c:63
Input_State input_state
Definition: client.h:277
void on_button_metaserver_quit_pressed(GtkButton *button, gpointer user_data)
Definition: metaserver.c:388
int meta_numservers
Definition: metaserver.c:57
#define FALSE
Definition: client-types.h:68
static GtkListStore * store_metaserver
Definition: metaserver.c:48
static void metaserver_connect_to(const char *name, const char *ip)
Definition: metaserver.c:308
void draw_map(int redraw)
Definition: map.c:654
int metaserver_check_status(void)
Definition: metaserver.c:774