Atrinik Client  4.0
main.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
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 at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <toolkit/gitversion.h>
32 #include <region_map.h>
33 #include <toolkit/packet.h>
34 #include <toolkit/string.h>
35 #include <toolkit/clioptions.h>
36 #include <toolkit/path.h>
37 #include <resources.h>
38 #include <toolkit/signals.h>
39 #include <toolkit/colorspace.h>
40 #include <toolkit/binreloc.h>
41 #include <toolkit/datetime.h>
42 #include <toolkit/socket_crypto.h>
43 #include <toolkit/x11.h>
44 #include <cmake.h>
45 
47 SDL_Surface *ScreenSurface;
49 struct sockaddr_in insock;
52 
55 
57 uint32_t LastTick;
58 
59 texture_struct *cursor_texture;
60 int cursor_x = -1;
61 int cursor_y = -1;
62 
63 /* update map area */
64 int map_redraw_flag;
65 int minimap_redraw_flag;
66 
69 Animations *animations = NULL;
71 size_t animations_num = 0;
72 
74 struct screensize *Screensize;
75 
78 
82 static uint32_t last_keepalive;
83 
88 
92 typedef struct keepalive_data_struct {
94 
95  uint32_t ticks;
96  uint32_t id;
98 
100 static int keepalive_id;
101 static int keepalive_ping;
102 static int keepalive_ping_avg;
103 static int keepalive_ping_num;
104 
108 static void keepalive_reset(void)
109 {
110  keepalive_data_struct *keepalive, *tmp;
111 
112  last_keepalive = SDL_GetTicks();
113  keepalive_id = 0;
114  keepalive_ping = 0;
115  keepalive_ping_avg = 0;
116  keepalive_ping_num = 0;
117 
118  LL_FOREACH_SAFE(keepalive_data, keepalive, tmp)
119  {
120  LL_DELETE(keepalive_data, keepalive);
121  efree(keepalive);
122  }
123 }
124 
128 static void keepalive_send(void)
129 {
130  keepalive_data_struct *keepalive;
131  packet_struct *packet;
132 
133  keepalive = emalloc(sizeof(*keepalive));
134  keepalive->ticks = SDL_GetTicks();
135  keepalive->id = ++keepalive_id;
136  LL_PREPEND(keepalive_data, keepalive);
137 
138  packet = packet_new(SERVER_CMD_KEEPALIVE, 0, 0);
139  packet_append_uint32(packet, keepalive->id);
140  packet_enable_ndelay(packet);
141  socket_send_packet(packet);
142  last_keepalive = keepalive->ticks;
143 }
144 
149 {
150  draw_info(COLOR_WHITE, "\nPing statistics this session:");
151  draw_info_format(COLOR_WHITE, "Keepalive TX: %d, RX: %d, missed: %d",
154  draw_info_format(COLOR_WHITE, "Average ping: %d", keepalive_ping_avg);
155  draw_info_format(COLOR_WHITE, "Last ping: %d", keepalive_ping);
156 }
157 
159 void socket_command_keepalive(uint8_t *data, size_t len, size_t pos)
160 {
161  uint32_t id, ticks;
162  keepalive_data_struct *keepalive, *tmp;
163 
164  id = packet_to_uint32(data, len, &pos);
165  ticks = SDL_GetTicks();
166 
167  LL_FOREACH_SAFE(keepalive_data, keepalive, tmp)
168  {
169  if (id == keepalive->id) {
170  LL_DELETE(keepalive_data, keepalive);
171 
172  keepalive_ping = ticks - keepalive->ticks;
176  efree(keepalive);
177 
178  return;
179  }
180  }
181 
182  LOG(BUG, "Received unknown keepalive ID: %d", id);
183 }
184 
188 static void init_game_data(void)
189 {
190  init_map_data(0, 0, 0, 0);
191  memset(FaceList, 0, sizeof(struct _face_struct) * MAX_FACE_TILES);
192 
193  init_keys();
194  memset(&cpl, 0, sizeof(cpl));
195  object_init();
196  clear_player();
197 
198  memset(&MapData, 0, sizeof(MapData));
199 
200  msg_anim.message[0] = '\0';
201 
202  cpl.state = ST_INIT;
203  map_redraw_flag = minimap_redraw_flag = 1;
204  csocket.sc = NULL;
205 
206  metaserver_init();
207  spells_init();
208  skills_init();
209 }
210 
216 static int game_status_chain(void)
217 {
218  if (cpl.state == ST_INIT) {
219  clear_map(true);
220  cpl.state = ST_META;
221  } else if (cpl.state == ST_META) {
223 
224  metaserver_add("localhost",
225  1728,
226  -1,
227  "Localhost",
228  "local",
229  "Localhost. Start server before you try to connect.");
230 
231  for (size_t i = 0; i < clioption_settings.servers_num; i++) {
232  size_t pos = 0;
233  char host[MAX_BUF];
234  string_get_word(clioption_settings.servers[i],
235  &pos,
236  ' ',
237  VS(host),
238  0);
239  char port[MAX_BUF];
240  string_get_word(clioption_settings.servers[i],
241  &pos,
242  ' ',
243  VS(port),
244  0);
245  char port_crypto[MAX_BUF];
246  string_get_word(clioption_settings.servers[i],
247  &pos,
248  ' ',
249  VS(port_crypto),
250  0);
251  int port_num = atoi(port);
252  int port_crypto_num = atoi(port_crypto);
253  metaserver_add(host,
254  port_num != 0 ? port_num : 1728,
255  port_crypto_num != 0 ? port_crypto_num : -1,
256  host,
257  "user server",
258  "Server from command line --server option.");
259  }
260 
262  cpl.state = ST_START;
263  } else if (cpl.state == ST_START) {
264  if (csocket.sc != NULL) {
265  client_socket_close(&csocket);
266  }
267 
268  effect_stop();
269  clear_map(true);
271  map_redraw_flag = minimap_redraw_flag = 1;
272  cpl.state = ST_WAITLOOP;
273  } else if (cpl.state == ST_STARTCONNECT) {
274  int port = selected_server->port;
275  if (selected_server->port_crypto != -1) {
276  port = selected_server->port_crypto;
277  }
279  "Trying server %s (%d)...",
280  selected_server->name,
281  port);
282  keepalive_reset();
283  cpl.state = ST_CONNECT;
284  } else if (cpl.state == ST_CONNECT) {
285  bool secure = false;
286  int port = selected_server->port;
287  if (selected_server->port_crypto != -1) {
288  secure = true;
289  port = selected_server->port_crypto;
290  }
291 
292  /* Ensure we have a public key record. */
293  if (secure && METASERVER_GET_PUBKEY(selected_server) == NULL) {
295  "The server %s (%d) does not have a public key "
296  "record, refusing to connect.",
297  selected_server->name,
298  selected_server->port);
299  cpl.state = ST_START;
300  return 1;
301  }
302 
303  if (!client_socket_open(&csocket,
304  selected_server->hostname,
305  port,
306  secure)) {
307  draw_info(COLOR_RED, "Connection failed!");
308  cpl.state = ST_START;
309  return 1;
310  }
311 
312  if (!metaserver_cert_verify_host(selected_server,
313  socket_get_addr(csocket.sc))) {
314  draw_info(COLOR_RED, "Failed to verify the IP address of the "
315  "specified server - it is very likely the "
316  "server has been compromised!");
317  cpl.state = ST_START;
318  return 1;
319  }
320 
322  clear_player();
323 
324  if (secure) {
325  packet_struct *packet = packet_new(SERVER_CMD_CRYPTO, 16, 0);
326  packet_append_uint8(packet, CMD_CRYPTO_HELLO);
327  socket_send_packet(packet);
328  cpl.state = ST_WAITCRYPTO;
329  } else {
330  cpl.state = ST_START_DATA;
331  }
332  } else if (cpl.state == ST_START_DATA) {
333  packet_struct *packet = packet_new(SERVER_CMD_VERSION, 16, 0);
334  packet_append_uint32(packet, SOCKET_VERSION);
335  socket_send_packet(packet);
336 
337  keepalive_send();
338  cpl.state = ST_WAITVERSION;
339  } else if (cpl.state == ST_VERSION) {
340  packet_struct *packet;
341 
342  packet = packet_new(SERVER_CMD_SETUP, 256, 256);
343  packet_append_uint8(packet, CMD_SETUP_SOUND);
344  packet_append_uint8(packet, 1);
345  packet_append_uint8(packet, CMD_SETUP_MAPSIZE);
346  packet_append_uint8(packet, setting_get_int(OPT_CAT_MAP, OPT_MAP_WIDTH));
347  packet_append_uint8(packet, setting_get_int(OPT_CAT_MAP, OPT_MAP_HEIGHT));
348  packet_append_uint8(packet, CMD_SETUP_DATA_URL);
349  packet_append_string_terminated(packet, "");
350  socket_send_packet(packet);
351 
352  cpl.state = ST_WAITSETUP;
353  } else if (cpl.state == ST_REQUEST_FILES_LISTING) {
354  /* Retrieve the server files listing. */
356  /* Load up the existing server files. */
359  } else if (cpl.state == ST_WAITREQUEST_FILES_LISTING) {
361  cpl.state = ST_REQUEST_FILES;
362  }
363  } else if (cpl.state == ST_REQUEST_FILES) {
364  if (server_files_processed()) {
366  cpl.state = ST_LOGIN;
367  }
368  } else if (cpl.state == ST_WAITFORPLAY) {
369  clear_map(true);
370  }
371 
372  return 1;
373 }
374 
378 static void play_action_sounds(void)
379 {
380  if (cpl.warn_statdown) {
381  sound_play_effect("warning_statdown.ogg", 100);
382  cpl.warn_statdown = 0;
383  }
384 
385  if (cpl.warn_statup) {
386  sound_play_effect("warning_statup.ogg", 100);
387  cpl.warn_statup = 0;
388  }
389 
390  if (cpl.warn_hp) {
391  if (cpl.warn_hp == 2) {
392  sound_play_effect("warning_hp2.ogg", 100);
393  } else {
394  sound_play_effect("warning_hp.ogg", 100);
395  }
396 
397  cpl.warn_hp = 0;
398  }
399 }
400 
404 void list_vid_modes(void)
405 {
406  SDL_Rect **modes;
407 
408  /* Get available fullscreen/hardware modes */
409  modes = SDL_ListModes(NULL, SDL_HWACCEL);
410 
411  /* Check if there are any modes available */
412  if (modes == (SDL_Rect **) 0) {
413  LOG(ERROR, "No video modes available!");
414  exit(1);
415  }
416 }
417 
421 static void sound_background_hook(void)
422 {
423  WIDGET_REDRAW_ALL(MPLAYER_ID);
424 }
425 
426 void clioption_settings_deinit(void)
427 {
428  size_t i;
429 
430  for (i = 0; i < clioption_settings.servers_num; i++) {
431  efree(clioption_settings.servers[i]);
432  }
433 
434  if (clioption_settings.servers) {
435  efree(clioption_settings.servers);
436  }
437 
438  for (i = 0; i < clioption_settings.metaservers_num; i++) {
439  efree(clioption_settings.metaservers[i]);
440  }
441 
442  if (clioption_settings.metaservers) {
443  efree(clioption_settings.metaservers);
444  }
445 
446  for (i = 0; i < arraysize(clioption_settings.connect); i++) {
447  if (clioption_settings.connect[i]) {
448  efree(clioption_settings.connect[i]);
449  }
450  }
451 
452  if (clioption_settings.game_news_url) {
453  efree(clioption_settings.game_news_url);
454  }
455 }
456 
460 static const char *const clioptions_option_server_desc =
461 "Adds a server to the list of servers.\n\n"
462 "Usage:\n"
463 " --server=example.com";
465 static bool
466 clioptions_option_server (const char *arg,
467  char **errmsg)
468 {
469  clioption_settings.servers =
470  erealloc(clioption_settings.servers,
471  sizeof(*clioption_settings.servers) *
472  (clioption_settings.servers_num + 1));
473  clioption_settings.servers[clioption_settings.servers_num] =
474  estrdup(arg);
475  clioption_settings.servers_num++;
476  return true;
477 }
478 
482 static const char *const clioptions_option_metaserver_desc =
483 "Adds a metaserver to the list of metaserver that will be tried.\n\n"
484 "Usage:\n"
485 " --metaserver=example.com";
487 static bool
489  char **errmsg)
490 {
491  clioption_settings.metaservers =
492  erealloc(clioption_settings.metaservers,
493  sizeof(*clioption_settings.metaservers) *
494  (clioption_settings.metaservers_num + 1));
495  clioption_settings.metaservers[clioption_settings.metaservers_num] =
496  estrdup(arg);
497  clioption_settings.metaservers_num++;
498  return true;
499 }
500 
504 static const char *const clioptions_option_connect_desc =
505 "Automatically connects to a server.\n\n"
506 "Usage:\n"
507 " --connect=<server>:<account>:<password>:<character>\n\n"
508 "Everything past the server is optional; you could for example only specify "
509 "the account, or specify everything but leave the password field empty to "
510 "still get a prompt for the password but still select the character "
511 "automatically.";
513 static bool
514 clioptions_option_connect (const char *arg,
515  char **errmsg)
516 {
517  char *cp = estrdup(arg);
518  char *cps[4];
519  size_t num = string_split(cp, cps, arraysize(cps), ':');
520 
521  for (size_t i = 0; i < num; i++) {
522  if (*cps[i] == '\0') {
523  continue;
524  }
525 
526  clioption_settings.connect[i] = estrdup(cps[i]);
527  }
528 
529  efree(cp);
530  return true;
531 }
532 
536 static const char *clioptions_option_nometa_desc =
537 "Do not query the metaserver.";
539 static bool
540 clioptions_option_nometa (const char *arg,
541  char **errmsg)
542 {
544  return true;
545 }
546 
551 "Enable text API debugging (shows bounding boxes for text that uses them).";
553 static bool
555  char **errmsg)
556 {
558  return true;
559 }
560 
565 "Enable widget rendering debugging (highlights widgets whenever they get "
566 "re-rendered).";
568 static bool
570  char **errmsg)
571 {
573  return true;
574 }
575 
580 "Sets the game news URL. Typically this doesn't need to be changed.";
582 static bool
584  char **errmsg)
585 {
586  clioption_settings.game_news_url = estrdup(arg);
587  return true;
588 }
589 
594 "On disconnect, will automatically attempt to reconnect to the "
595 "server/account/etc as specified with --connect.";
597 static bool
599  char **errmsg)
600 {
601  clioption_settings.reconnect = 1;
602  return true;
603 }
604 
614 int main(int argc, char *argv[])
615 {
616  char *path;
617  int done = 0, update, frames;
618  uint32_t anim_tick, frame_start_time, elapsed_time, fps_limit,
619  last_frame_ticks, last_memory_check;
620  int fps_limits[] = {30, 60, 120, 0};
621 
622  toolkit_import(signals);
623  signals_set_traceback_prefix(EXECUTABLE);
624 
625  toolkit_import(binreloc);
626  toolkit_import(clioptions);
627  toolkit_import(colorspace);
628  toolkit_import(curl);
629  toolkit_import(datetime);
630  toolkit_import(logger);
631  toolkit_import(math);
632  toolkit_import(memory);
633  toolkit_import(packet);
634  toolkit_import(sha1);
635  toolkit_import(socket);
636  toolkit_import(socket_crypto);
637  toolkit_import(string);
638  toolkit_import(stringbuffer);
639  toolkit_import(x11);
640 
641  path_fopen = client_fopen_wrapper;
642 
643  char version[MAX_BUF];
644  package_get_version_full(VS(version));
645 
646  /* Store user agent for cURL, including if this is a GNU/Linux build of
647  * the client or a Windows one. */
648  char user_agent[MAX_BUF];
649 #if defined(WIN32)
650  snprintf(VS(user_agent), "Atrinik Client (Win32)/%s (%d)",
651  version, SOCKET_VERSION);
652 #elif defined(__GNUC__)
653  snprintf(VS(user_agent), "Atrinik Client (GNU/Linux)/%s (%d)",
654  version, SOCKET_VERSION);
655 #else
656  snprintf(VS(user_agent), "Atrinik Client (Unknown)/%s (%d)",
657  version, SOCKET_VERSION);
658 #endif
659 
660  curl_set_user_agent(user_agent);
661 
662  clioption_t *cli;
663 
664  /* Non-argument options */
665  CLIOPTIONS_CREATE_ARGUMENT(cli, server, "Add a server to the list");
666  CLIOPTIONS_CREATE_ARGUMENT(cli, metaserver, "Add a metaserver to the list");
667  CLIOPTIONS_CREATE_ARGUMENT(cli, connect, "Connect to the specified server");
668  CLIOPTIONS_CREATE_ARGUMENT(cli, game_news_url, "Set game news URL");
669 
670  /* Argument options*/
671  CLIOPTIONS_CREATE(cli, nometa, "Disable querying the metaserver");
672  CLIOPTIONS_CREATE(cli, text_debug, "Enable text API debugging");
673  CLIOPTIONS_CREATE(cli, widget_render_debug, "Enable widget debugging");
674  CLIOPTIONS_CREATE(cli, reconnect, "Reconnect automatically");
675 
676  memset(&clioption_settings, 0, sizeof(clioption_settings));
677 
678  path = file_path("client.cfg", "r");
679  clioptions_load(path, NULL);
680  efree(path);
681  path = file_path("client-custom.cfg", "r");
682  clioptions_load(path, NULL);
683  efree(path);
684 
685  clioptions_parse(argc, argv);
686 
687  logger_open_log(LOG_FILE);
688 
689  upgrader_init();
690  settings_init();
691  init_game_data();
692 
693  if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0) {
694  LOG(ERROR, "Couldn't initialize SDL: %s", SDL_GetError());
695  exit(1);
696  }
697 
698  /* Start the system after starting SDL */
699  video_init();
700  system_start();
702  SDL_EnableUNICODE(1);
703  text_init();
704  texture_init();
705  sound_init();
707  keybind_load();
708  load_mapdef_dat();
709  image_init();
712  resources_init();
713 
714  StringBuffer *sb = stringbuffer_new();
715  stringbuffer_append_printf(sb,
716  "%s/.atrinik/%s",
717  get_config_dir(),
718  version);
719  path = stringbuffer_finish(sb);
720  socket_crypto_set_path(path);
721  efree(path);
722 
723  char buf[HUGE_BUF];
724  snprintf(VS(buf), "Welcome to Atrinik version %s", version);
725 #ifdef GITVERSION
726  snprintfcat(VS(buf), "%s",
727  " (" STRINGIFY(GITBRANCH) "/" STRINGIFY(GITVERSION)
728  " by " STRINGIFY(GITAUTHOR) ")");
729 #endif
730  draw_info(COLOR_HGOLD, buf);
731 
732  if (!x11_clipboard_register_events()) {
733  draw_info(COLOR_RED, "Failed to initialize clipboard support, clipboard actions will not be possible.");
734  }
735 
736  settings_apply();
737  scrollbar_init();
738  button_init();
739 
740  atexit(system_end);
741 
742  cursor_texture = texture_get(TEXTURE_TYPE_CLIENT, "cursor_default");
743 
745 
746  LastTick = anim_tick = last_frame_ticks = last_memory_check =
747  SDL_GetTicks();
748  frames = 0;
749 
750  while (!done) {
751  frame_start_time = SDL_GetTicks();
752  done = Event_PollInputDevice();
753 
754  /* Have we been shutdown? */
755  if (handle_socket_shutdown()) {
756  if (cpl.state != ST_STARTCONNECT) {
757  cpl.state = ST_START;
758  /* Make sure no popup is visible. */
760  }
761 
762  continue;
763  }
764 
765  /* Check the memory every 10 seconds. */
766  if (SDL_GetTicks() - last_memory_check > 10 * 1000) {
767  memory_check_all();
768  last_memory_check = SDL_GetTicks();
769  }
770 
771  if (cpl.state > ST_CONNECT) {
772  /* Send keepalive command every 2 minutes. */
773  if (SDL_GetTicks() - last_keepalive > (2 * 60) * 1000) {
774  keepalive_send();
775  }
776 
777  DoClient();
778  }
779 
780  /* If not connected, walk through connection chain and/or wait for
781  * action */
782  if (cpl.state != ST_PLAY) {
783  if (!game_status_chain()) {
784  LOG(ERROR, "Error connecting: cpl.state: %d SocketError: %s "
785  "(%d)", cpl.state, strerror(s_errno), s_errno);
786  }
787  } else if (SDL_GetAppState() & SDL_APPACTIVE) {
788  if (LastTick - anim_tick > 125) {
789  anim_tick = LastTick;
790  animate_objects();
791  map_animate();
792  }
793 
795  }
796 
797  update = 0;
798 
799  if (!(SDL_GetAppState() & SDL_APPACTIVE)) {
800  } else if (cpl.state == ST_PLAY) {
801  static int old_cursor_x = -1, old_cursor_y = -1;
802 
803  if (widgets_need_redraw()) {
804  update = 1;
805  } else if (cursor_x != old_cursor_x || cursor_y != old_cursor_y) {
806  update = 1;
807  old_cursor_x = cursor_x;
808  old_cursor_y = cursor_y;
809  } else if (event_dragging_need_redraw()) {
810  update = 1;
811  } else if (popup_need_redraw()) {
812  update = 1;
813  } else if (tooltip_need_redraw()) {
814  update = 1;
815  } else if (map_redraw_flag || minimap_redraw_flag) {
816  update = 1;
817  } else if (map_anims_need_redraw()) {
818  update = 1;
819  }
820  } else {
821  update = 1;
822  }
823 
824  if (update) {
825  SDL_FillRect(ScreenSurface, NULL, 0);
826  }
827 
828  if (cpl.state <= ST_WAITFORPLAY) {
829  intro_show();
830  } else if (cpl.state == ST_PLAY) {
831  process_widgets(update);
832  }
833 
835  tooltip_show();
836 
837  /* Show the currently dragged item. */
838  if (event_dragging_check()) {
839  int mx, my;
840 
841  SDL_GetMouseState(&mx, &my);
843  mx, my, INVENTORY_ICON_SIZE, INVENTORY_ICON_SIZE, false);
844  }
845 
847  cursor_x != -1 && cursor_y != -1 &&
848  SDL_GetAppState() & SDL_APPMOUSEFOCUS) {
850  cursor_x - texture_surface(cursor_texture)->w / 2,
851  cursor_y - texture_surface(cursor_texture)->h / 2,
852  NULL,
853  texture_surface(cursor_texture));
854  }
855 
856  texture_gc();
857  font_gc();
858  sprite_cache_gc();
859 
860  if (update) {
861  SDL_Flip(ScreenSurface);
862  }
863 
864  LastTick = SDL_GetTicks();
865 
866  if (SDL_GetAppState() & SDL_APPACTIVE) {
867  frames++;
868 
869  if (LastTick - last_frame_ticks >= 1000) {
870  last_frame_ticks = LastTick;
871  effect_frames(frames);
872  frames = 0;
873  }
874  }
875 
876  elapsed_time = SDL_GetTicks() - frame_start_time;
877  fps_limit = fps_limits[setting_get_int(OPT_CAT_CLIENT, OPT_FPS_LIMIT)];
878 
879  if (fps_limit != 0) {
880  while (1) {
881  if (elapsed_time < 1000 / fps_limit) {
882  SDL_Delay(MAX(1, 1000 / fps_limit - elapsed_time));
883 
884  if (!(SDL_GetAppState() & SDL_APPACTIVE) && SDL_GetTicks() - frame_start_time < 1000) {
885  SDL_PumpEvents();
886  continue;
887  }
888  }
889 
890  break;
891  }
892  }
893  }
894 
895  return 0;
896 }
void system_end(void)
Definition: wrapper.c:51
void scrollbar_init()
Definition: scrollbar.c:44
static const char * clioptions_option_game_news_url_desc
Definition: main.c:579
server_struct * selected_server
Definition: main.c:54
void client_socket_close(client_socket_t *csock)
Definition: socket.c:429
Definition: main.h:332
void init_keys(void)
Definition: keys.c:37
FILE * client_fopen_wrapper(const char *fname, const char *mode)
Definition: wrapper.c:508
void settings_init(void)
Definition: settings.c:96
static uint32_t ticks
Definition: range_buttons.c:38
void list_vid_modes(void)
Definition: main.c:404
Definition: main.h:252
static bool clioptions_option_reconnect(const char *arg, char **errmsg)
Definition: main.c:598
static bool clioptions_option_metaserver(const char *arg, char **errmsg)
Definition: main.c:488
void draw_info(const char *color, const char *str)
Definition: textwin.c:448
static int keepalive_id
UID for sending keepalives.
Definition: main.c:100
_anim_table * anim_table
Definition: main.c:68
void metaserver_get_servers(void)
Definition: metaserver.c:801
void load_mapdef_dat(void)
Definition: map.c:109
#define SOCKET_VERSION
Definition: config.h:34
SDL_Surface * texture_surface(texture_struct *texture)
Definition: texture.c:303
void sound_play_effect(const char *filename, int volume)
Definition: sound.c:367
static int keepalive_ping_num
Number of keepalive pings.
Definition: main.c:103
static int keepalive_ping_avg
Average keepalive ping time.
Definition: main.c:102
void animate_objects(void)
Definition: item.c:510
int map_anims_need_redraw(void)
Definition: map.c:2671
int widgets_need_redraw(void)
Definition: widget.c:1661
void intro_show(void)
Definition: intro.c:174
int tooltip_need_redraw(void)
Definition: tooltip.c:196
Definition: main.h:312
bool metaserver_cert_verify_host(server_struct *server, const char *host)
Definition: metaserver.c:591
void sound_background_hook_register(void *ptr)
Definition: sound.c:238
void button_init()
Definition: button.c:37
void DoClient(void)
Definition: client.c:89
struct sockaddr_in insock
Definition: main.c:49
struct screensize * Screensize
Definition: main.c:74
void cmd_aliases_init(void)
Definition: cmd_aliases.c:165
void text_init(void)
Definition: text.c:336
void metaserver_init(void)
Definition: metaserver.c:86
static bool clioptions_option_text_debug(const char *arg, char **errmsg)
Definition: main.c:554
bool client_socket_open(client_socket_t *csock, const char *host, int port, bool secure)
Definition: socket.c:477
struct keepalive_data_struct keepalive_data_struct
#define COLOR_HGOLD
Definition: text.h:319
texture_struct * texture_get(texture_type_t type, const char *name)
Definition: texture.c:279
SDL_Surface * ScreenSurface
Definition: main.c:47
void keepalive_ping_stats(void)
Definition: main.c:148
void texture_init(void)
Definition: texture.c:176
#define MAX_FACE_TILES
Definition: config.h:52
void server_files_listing_retrieve(void)
Definition: server_files.c:207
#define COLOR_RED
Definition: text.h:295
void tooltip_show(void)
Definition: tooltip.c:116
void widget_render_enable_debug(void)
Definition: widget.c:2660
_mapdata MapData
Definition: map.c:64
#define COLOR_GREEN
Definition: text.h:297
char message[MAX_BUF]
Definition: main.h:129
client_socket_t csocket
Definition: main.c:51
void sprite_init_system(void)
Definition: sprite.c:62
static bool clioptions_option_game_news_url(const char *arg, char **errmsg)
Definition: main.c:583
static const char *const clioptions_option_metaserver_desc
Definition: main.c:482
static uint8_t text_debug
Definition: text.c:39
tag_t dragging_tag
Definition: player.h:187
char * package_get_version_full(char *dst, size_t dstlen)
Definition: misc.c:69
static void init_game_data(void)
Definition: main.c:188
void keybind_load(void)
Definition: keybind.c:60
char * name
Definition: main.h:65
server_struct * metaserver_add(const char *hostname, int port, int port_crypto, const char *name, const char *version, const char *desc)
Definition: metaserver.c:731
void system_start(void)
Definition: wrapper.c:38
static const char * clioptions_option_text_debug_desc
Definition: main.c:550
Client_Player cpl
Definition: client.c:50
static const char * clioptions_option_nometa_desc
Definition: main.c:536
_face_struct FaceList[MAX_FACE_TILES]
Definition: main.c:77
static void keepalive_send(void)
Definition: main.c:128
static keepalive_data_struct * keepalive_data
Keepalive data.
Definition: main.c:99
int64_t setting_get_int(int cat, int setting)
Definition: settings.c:414
static int keepalive_ping
Last keepalive ping time.
Definition: main.c:101
static bool clioptions_option_connect(const char *arg, char **errmsg)
Definition: main.c:514
void toolkit_widget_init(void)
Definition: widget.c:243
void object_init(void)
Definition: item.c:42
void socket_thread_start(void)
Definition: socket.c:353
uint32_t id
ID of the keepalive command.
Definition: main.c:96
static void keepalive_reset(void)
Definition: main.c:108
void font_gc(void)
Definition: text.c:297
static const char *const clioptions_option_connect_desc
Definition: main.c:504
struct keepalive_data_struct * next
Next keepalive data.
Definition: main.c:93
void sound_init(void)
Definition: sound.c:248
int server_files_listing_processed(void)
Definition: server_files.c:228
int handle_socket_shutdown(void)
Definition: socket.c:402
char * hostname
Definition: main.h:68
#define METASERVER_GET_PUBKEY(server)
Definition: main.h:119
size_t animations_num
Definition: main.c:71
static int widget_render_debug
Definition: widget.c:106
void clear_player(void)
Definition: player.c:80
void resources_reload(void)
Definition: resources.c:85
static void sound_background_hook(void)
Definition: main.c:421
void skills_init(void)
Definition: skills.c:66
int server_files_processed(void)
Definition: server_files.c:377
#define INVENTORY_ICON_SIZE
Definition: inventory.h:60
Definition: main.h:242
void socket_command_keepalive(uint8_t *data, size_t len, size_t pos)
Definition: main.c:159
static const char * clioptions_option_widget_render_debug_desc
Definition: main.c:564
void resources_init(void)
Definition: resources.c:47
struct msg_anim_struct msg_anim
Definition: main.c:80
#define LOG_FILE
Definition: config.h:43
void text_enable_debug(void)
Definition: text.c:2494
object * object_find(tag_t tag)
Definition: item.c:139
void spells_init(void)
Definition: spells.c:74
uint32_t LastTick
Definition: main.c:57
void metaserver_clear_data(void)
Definition: metaserver.c:697
Definition: main.h:247
char * file_path(const char *path, const char *mode)
Definition: wrapper.c:369
clioption_settings_struct clioption_settings
Definition: main.c:87
static uint32_t last_keepalive
Definition: main.c:82
void surface_show(SDL_Surface *surface, int x, int y, SDL_Rect *srcrect, SDL_Surface *src)
Definition: sprite.c:761
void server_files_load(int post_load)
Definition: server_files.c:151
void video_init(void)
Definition: video.c:45
static const char *const clioptions_option_server_desc
Definition: main.c:460
void process_widgets(int draw)
Definition: widget.c:1770
int main(int argc, char *argv[])
Definition: main.c:614
void settings_apply(void)
Definition: settings.c:557
void metaserver_disable(void)
Definition: metaserver.c:103
int port
Definition: main.h:80
void draw_info_format(const char *color, const char *format,...)
Definition: textwin.c:429
int port_crypto
Definition: main.h:83
void server_files_init(void)
Definition: server_files.c:47
void object_show_centered(SDL_Surface *surface, object *tmp, int x, int y, int w, int h, bool fit)
Definition: item.c:545
void upgrader_init(void)
Definition: upgrader.c:268
static int game_status_chain(void)
Definition: main.c:216
uint32_t ticks
When the keepalive command was sent.
Definition: main.c:95
const char * get_config_dir(void)
Definition: wrapper.c:303
void texture_gc(void)
Definition: texture.c:238
static void play_action_sounds(void)
Definition: main.c:378
static bool clioptions_option_server(const char *arg, char **errmsg)
Definition: main.c:466
void sprite_cache_gc(void)
Definition: sprite.c:274
void effect_stop(void)
Definition: effects.c:689
void image_init(void)
Definition: image.c:62
#define COLOR_WHITE
Definition: text.h:289
int Event_PollInputDevice(void)
Definition: event.c:130
static bool clioptions_option_nometa(const char *arg, char **errmsg)
Definition: main.c:540
static bool clioptions_option_widget_render_debug(const char *arg, char **errmsg)
Definition: main.c:569
void init_map_data(int xl, int yl, int px, int py)
Definition: map.c:410
void clear_map(bool hard)
Definition: map.c:154
static const char * clioptions_option_reconnect_desc
Definition: main.c:593