Crossfire Client, Trunk
client.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
32 #include "client.h"
33 
34 #include <ctype.h>
35 #include <errno.h>
36 #include <gio/gio.h>
37 #ifdef HAVE_GIO_GNETWORKING_H
38 #include <gio/gnetworking.h>
39 #endif
40 
41 #include "external.h"
42 #include "mapdata.h"
43 #include "metaserver.h"
44 #include "script.h"
45 
46 /* actually declare the globals */
47 
49 
51 char *sound_server = BINDIR "/cfsndserv";
52 const char *config_dir;
53 const char *cache_dir;
54 
56 
59 
60 /* Use the 'new' login method by default */
63 
64 guint16 exp_table_max=0;
65 guint64 *exp_table=NULL;
66 
68 
71 static GInputStream *in;
72 
73 const char *const resists_name[NUM_RESISTS] = {
74  "armor", "magic", "fire", "elec",
75  "cold", "conf", "acid", "drain",
76  "ghit", "pois", "slow", "para",
77  "t undead", "fear", "depl","death",
78  "hword", "blind"
79 };
80 
81 typedef void (*CmdProc)(unsigned char *, int len);
82 
88 struct CmdMapping {
89  const char *cmdname;
90  void (*cmdproc)(unsigned char *, int );
92 };
93 
101 struct CmdMapping commands[] = {
102  /*
103  * The order of this table does not make much of a difference. Related
104  * commands are listed in groups.
105  */
106  { "map2", Map2Cmd, SHORT_ARRAY },
107  { "map_scroll", (CmdProc)map_scrollCmd, ASCII },
108  { "magicmap", MagicMapCmd, MIXED /* ASCII, then binary */},
109  { "newmap", NewmapCmd, NODATA },
110  { "mapextended", MapExtendedCmd, MIXED /* chars, then SHORT_ARRAY */ },
111 
112  { "item2", Item2Cmd, MIXED },
113  { "upditem", UpdateItemCmd, MIXED },
114  { "delitem", DeleteItem, INT_ARRAY },
115  { "delinv", DeleteInventory, ASCII },
116 
117  { "addspell", AddspellCmd, MIXED },
118  { "updspell", UpdspellCmd, MIXED },
119  { "delspell", DeleteSpell, INT_ARRAY },
120 
121  { "drawinfo", (CmdProc)DrawInfoCmd, ASCII },
122  { "drawextinfo", (CmdProc)DrawExtInfoCmd, ASCII},
123  {
124  "stats", StatsCmd, STATS /* Array of: int8, (int?s for
125  * that stat)
126  */
127  },
128  { "image2", Image2Cmd, MIXED /* int, int8, int, PNG */ },
129  {
130  "face2", Face2Cmd, MIXED /* int16, int8, int32, string
131  */
132  },
133  { "tick", TickCmd, INT_ARRAY /* uint32 */},
134 
135  { "music", (CmdProc)MusicCmd, ASCII },
136  {
137  "sound2", Sound2Cmd, MIXED /* int8, int8, int8, int8,
138  * int8, int8, chars, int8,
139  * chars
140  */
141  },
142  { "anim", AnimCmd, SHORT_ARRAY},
143  { "smooth", SmoothCmd, SHORT_ARRAY},
144 
145  { "player", PlayerCmd, MIXED /* 3 ints, int8, str */ },
146  { "comc", CompleteCmd, SHORT_INT },
147 
148  { "addme_failed", (CmdProc)AddMeFail, NODATA },
149  { "addme_success", (CmdProc)AddMeSuccess, NODATA },
150  { "version", (CmdProc)VersionCmd, ASCII },
151  { "goodbye", (CmdProc)GoodbyeCmd, NODATA },
152  { "setup", (CmdProc)SetupCmd, ASCII},
153  { "failure", (CmdProc)FailureCmd, ASCII},
154  { "accountplayers", (CmdProc)AccountPlayersCmd, ASCII},
155 
156  { "query", (CmdProc)handle_query, ASCII},
157  { "replyinfo", ReplyInfoCmd, ASCII},
158  { "ExtendedTextSet", (CmdProc)SinkCmd, NODATA},
159  { "ExtendedInfoSet", (CmdProc)SinkCmd, NODATA},
160 
161  { "pickup", PickupCmd, INT_ARRAY /* uint32 */},
162 };
163 
167 #define NCOMMANDS ((int)(sizeof(commands)/sizeof(struct CmdMapping)))
168 
169 GQuark client_error_quark();
170 
171 void client_mapsize(int width, int height) {
172  cs_print_string(csocket.fd, "setup mapsize %dx%d", width, height);
173 }
174 
176  LOG(LOG_DEBUG, "close_server_connection", "Closing server connection");
177  g_io_stream_close(G_IO_STREAM(csocket.fd), NULL, NULL);
178  g_object_unref(csocket.fd);
179  csocket.fd = NULL;
180 }
181 
186 char *printable(void *data, int len) {
187  char *buf = (char *)malloc(len+1);
188  if (buf != NULL) {
189  memcpy(buf, data, len);
190  for (int i = 0; i < len; i++) {
191  if (!isprint(buf[i])) {
192  buf[i] = '.';
193  } else if (buf[i] == '\n' || buf[i] == '\r') {
194  buf[i] = '\\';
195  }
196  }
197  buf[len] = '\0';
198  }
199  return buf;
200 }
201 
202 void client_run() {
203  GError* err = NULL;
204  SockList inbuf;
205  inbuf.buf = g_malloc(MAXSOCKBUF);
206  if (!SockList_ReadPacket(csocket.fd, &inbuf, MAXSOCKBUF - 1, &err)) {
207  /*
208  * If a socket error occurred while reading the packet, drop the
209  * server connection. Is there a better way to handle this?
210  */
211  if (!err) {
212  LOG(LOG_ERROR, "client_run", "%s", err->message);
213  g_error_free(err);
214  }
216  return;
217  }
218  if (inbuf.len == 0) {
220  return;
221  }
222  /*
223  * Null-terminate the buffer, and set the data pointer so it points
224  * to the first character of the data (following the packet length).
225  */
226  inbuf.buf[inbuf.len] = '\0';
227  unsigned char* data = inbuf.buf + 2;
228  /*
229  * Commands that provide data are always followed by a space. Find
230  * the space and convert it to a null character. If no spaces are
231  * found, the packet contains a command with no associatd data.
232  */
233  while ((*data != ' ') && (*data != '\0')) {
234  ++data;
235  }
236  int len;
237  if (*data == ' ') {
238  *data = '\0';
239  data++;
240  len = inbuf.len - (data - inbuf.buf);
241  } else {
242  len = 0;
243  }
244  /*
245  * Search for the command in the list of supported server commands.
246  * If the server command is supported by the client, let the script
247  * watcher know what command was received, then process it and quit
248  * searching the command list.
249  */
250  const char *cmdin = (char *)inbuf.buf + 2;
251  if (debug_protocol) {
252  char *data_print = printable(data, len);
253  if (data_print != NULL) {
254  LOG(LOG_INFO, "S->C", "len=%d cmd=%s |%s|", len, cmdin, data_print);
255  free(data_print);
256  }
257  }
258  int i;
259  for(i = 0; i < NCOMMANDS; i++) {
260  if (strcmp(cmdin, commands[i].cmdname) == 0) {
261  script_watch(cmdin, data, len, commands[i].cmdformat);
262  commands[i].cmdproc(data, len);
263  break;
264  }
265  }
266  /*
267  * After processing the command, mark the socket input buffer empty.
268  */
269  inbuf.len=0;
270  /*
271  * Complain about unsupported commands to facilitate troubleshooting.
272  * The client and server should negotiate a connection such that the
273  * server does not send commands the client does not support.
274  */
275  if (i == NCOMMANDS) {
276  LOG(LOG_ERROR, "client_run", "Unrecognized command from server (%s)\n",
277  inbuf.buf + 2);
278  error_dialog("Server error",
279  "The server sent an unrecognized command. "
280  "Crossfire Client will now disconnect."
281  "\n\nIf this problem persists with a particular "
282  "character, try playing another character, and without "
283  "disconnecting, playing the problematic character again.");
285  }
286  g_free(inbuf.buf);
287 }
288 
289 void client_connect(const char hostname[static 1]) {
290  GSocketClient *sclient = g_socket_client_new();
291 
292  // Store server hostname.
293  if (csocket.servername != NULL) {
294  g_free(csocket.servername);
295  }
296  csocket.servername = g_strdup(hostname);
297 
298  // Try to connect to server.
299  csocket.fd = g_socket_client_connect_to_host(
300  sclient, hostname, use_config[CONFIG_PORT], NULL, NULL);
301  g_object_unref(sclient);
302  if (csocket.fd == NULL) {
303  return;
304  }
305 
306  GSocket *socket = g_socket_connection_get_socket(csocket.fd);
307  int i = 1, fd = g_socket_get_fd(socket);
308 #ifndef WIN32
309 #ifdef HAVE_GIO_GNETWORKING_H
310  if (use_config[CONFIG_FASTTCP]) {
311  if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &i, sizeof(i)) == -1) {
312  perror("TCP_NODELAY");
313  }
314  }
315 #endif
316 #endif
317  in = g_io_stream_get_input_stream(G_IO_STREAM(csocket.fd));
318 }
319 
321  return csocket.fd != NULL && g_socket_connection_is_connected(csocket.fd);
322 }
323 
324 GSource *client_get_source() {
325  return g_pollable_input_stream_create_source(
326  G_POLLABLE_INPUT_STREAM(in), NULL);
327 }
328 
329 void client_negotiate(int sound) {
330  int tries;
331 
333 
334  /* We need to get the version command fairly early on because we need to
335  * know if the server will support a request to use png images. This
336  * isn't done the best, because if the server never sends the version
337  * command, we can loop here forever. However, if it doesn't send the
338  * version command, we have no idea what we are dealing with.
339  */
340  tries=0;
341  while (csocket.cs_version==0) {
342  client_run();
343  if (csocket.fd == NULL) {
344  return;
345  }
346 
347  usleep(10*1000); /* 10 milliseconds */
348  tries++;
349  /* If we haven't got a response in 10 seconds, bail out */
350  if (tries > 1000) {
351  LOG (LOG_ERROR,"common::negotiate_connection", "Connection timed out");
353  return;
354  }
355  }
356 
357  if (csocket.sc_version<1023) {
358  LOG (LOG_WARNING,"common::negotiate_connection","Server does not support PNG images, yet that is all this client");
359  LOG (LOG_WARNING,"common::negotiate_connection","supports. Either the server needs to be upgraded, or you need to");
360  LOG (LOG_WARNING,"common::negotiate_connection","downgrade your client.");
361  exit(1);
362  }
363 
364  /* If the user has specified a numeric face id, use it. If it is a string
365  * like base, then that resolves to 0, so no real harm in that.
366  */
367  if (face_info.want_faceset) {
369  }
370 
371  /* For sound, a value following determines which sound features are
372  * wanted. The value is 1 for sound effects, and 2 for background music,
373  * or the sum of 1 + 2 (3) for both.
374  *
375  * For spellmon, try each acceptable level, but make sure the one the
376  * client prefers is last.
377  */
378  cs_print_string(csocket.fd, "setup "
379  "map2cmd 1 tick 1 sound2 %d darkness %d spellmon 1 spellmon 2 "
380  "faceset %d facecache %d want_pickup 1 loginmethod %d newmapcmd 1 extendedTextInfos 1",
381  (sound >= 0) ? 3 : 0, want_config[CONFIG_LIGHTING] ? 1 : 0,
383 
384  /*
385  * We can do this right now also. There is not any reason to wait.
386  */
387  cs_print_string(csocket.fd, "requestinfo skill_info");
388  cs_print_string(csocket.fd,"requestinfo exp_table");
389  /*
390  * While these are only used for new login method, they should become
391  * standard fairly soon. All of these are pretty small, and do not add
392  * much to the cost. They make it more likely that the information is
393  * ready when the window that needs it is raised.
394  */
395  cs_print_string(csocket.fd,"requestinfo motd");
396  cs_print_string(csocket.fd,"requestinfo news");
397  cs_print_string(csocket.fd,"requestinfo rules");
398 
401 
402  /* If the server will answer the requestinfo for image_info and image_data,
403  * send it and wait for the response.
404  */
405  if (csocket.sc_version >= 1027) {
406  /* last_start is -99. This means the first face requested will be 1
407  * (not 0) - this is OK because 0 is defined as the blank face.
408  */
409  int last_end=0, last_start=-99;
410 
411  cs_print_string(csocket.fd,"requestinfo image_info");
413  replyinfo_status = 0;
415 
416  do {
417  client_run();
418  /*
419  * It is rare, but the connection can die while getting this info.
420  */
421  if (csocket.fd == NULL) {
422  return;
423  }
424 
426  /*
427  * We need to know how many faces to be able to make the
428  * request intelligently. So only do the following block if
429  * we have that info. By setting the sent flag, we will never
430  * exit this loop until that happens.
431  */
433  if (face_info.num_images != 0) {
434  /*
435  * Sort of fake things out - if we have sent the request
436  * for image sums but have not got them all answered yet,
437  * we then clear the bit from the status so we continue to
438  * loop.
439  */
440  if (last_end == face_info.num_images) {
441  /* Mark that we're all done */
442  if (replyinfo_last_face == last_end) {
445  }
446  } else {
447  /*
448  * If we are all caught up, request another 100 sums.
449  */
450  if (last_end <= (replyinfo_last_face+100)) {
451  last_start += 100;
452  last_end += 100;
453  if (last_end > face_info.num_images) {
454  last_end = face_info.num_images;
455  }
456  cs_print_string(csocket.fd,"requestinfo image_sums %d %d", last_start, last_end);
457  image_update_download_status(last_start, last_end, face_info.num_images);
458  }
459  }
460  } /* Still have image_sums request to send */
461  } /* endif download all faces */
462 
463  usleep(10*1000); /* 10 milliseconds */
464  /*
465  * Do not put in an upper time limit with tries like we did above.
466  * If the player is downloading all the images, the time this
467  * takes could be considerable.
468  */
469  } while (replyinfo_status != requestinfo_sent);
470  }
472  char buf[MAX_BUF];
473 
474  snprintf(buf, sizeof(buf), "Download of images complete. Found %d locally, downloaded %d from server\n",
477  }
478 
479  /* This needs to get changed around - we really don't want to send the
480  * SendAddMe until we do all of our negotiation, which may include things
481  * like downloading all the images and whatnot - this is more an issue if
482  * the user is not using the default face set, as in that case, we might
483  * end up building images from the wrong set.
484  * Only run this if not using new login method
485  */
486  if (!serverloginmethod) {
488  }
489 }
DeleteSpell
void DeleteSpell(unsigned char *data, int len)
Definition: commands.c:2001
SockList_ReadPacket
bool SockList_ReadPacket(GSocketConnection c[static 1], SockList sl[static 1], size_t len, GError **error)
Definition: newsocket.c:213
LOG_INFO
@ LOG_INFO
Minor, non-harmful issues.
Definition: client.h:434
MIXED
@ MIXED
Definition: script.h:48
MSG_TYPE_CLIENT
#define MSG_TYPE_CLIENT
Definition: newclient.h:387
script_watch
void script_watch(const char *cmd, const guint8 *data_initial, const int data_len, const enum CmdFormat format)
Definition: script.c:632
CmdFormat
CmdFormat
Definition: script.h:43
NUM_RESISTS
#define NUM_RESISTS
Definition: client.h:443
TickCmd
void TickCmd(guint8 *data, int len)
Definition: commands.c:2388
LOG_WARNING
@ LOG_WARNING
Warning that something might not work.
Definition: client.h:435
CONFIG_PORT
#define CONFIG_PORT
Definition: client.h:205
STATS
@ STATS
Definition: script.h:49
NameMapping
Definition: client.h:452
metaserver.h
CmdProc
void(* CmdProc)(unsigned char *, int len)
Definition: client.c:81
CmdMapping::cmdname
const char * cmdname
Definition: client.c:89
client_disconnect
void client_disconnect()
Definition: client.c:175
ClientSocket::fd
GSocketConnection * fd
Definition: client.h:124
GoodbyeCmd
void GoodbyeCmd(char *data, int len)
Definition: commands.c:1142
Face_Information_struct::num_images
gint16 num_images
Definition: client.h:408
requestinfo_sent
int requestinfo_sent
Definition: client.c:57
cache_dir
const char * cache_dir
Definition: client.c:53
commands
struct CmdMapping commands[]
Definition: client.c:101
DeleteItem
void DeleteItem(unsigned char *data, int len)
Definition: commands.c:1811
CONFIG_DOWNLOAD
#define CONFIG_DOWNLOAD
Definition: client.h:183
external.h
handle_query
void handle_query(char *data, int len)
Definition: commands.c:1556
resist_mapping
NameMapping resist_mapping[NUM_RESISTS]
Definition: client.c:67
face_info
Face_Information face_info
Definition: image.c:169
height
static int height
Definition: mapdata.c:99
INT_ARRAY
@ INT_ARRAY
Definition: script.h:46
DrawExtInfoCmd
void DrawExtInfoCmd(char *data, int len)
Definition: commands.c:1291
CONFIG_LIGHTING
#define CONFIG_LIGHTING
Definition: client.h:199
MAXSOCKBUF
#define MAXSOCKBUF
Definition: newclient.h:25
ReplyInfoCmd
void ReplyInfoCmd(unsigned char *buf, int len)
Definition: commands.c:774
client_is_connected
bool client_is_connected()
Definition: client.c:320
CmdMapping
Definition: client.c:88
AddMeFail
void AddMeFail(char *data, int len)
Definition: commands.c:1110
resists_name
const char *const resists_name[NUM_RESISTS]
Definition: client.c:73
PlayerCmd
void PlayerCmd(unsigned char *data, int len)
Definition: commands.c:1629
ClientSocket::sc_version
int sc_version
Definition: client.h:125
SmoothCmd
void SmoothCmd(unsigned char *data, int len)
Definition: commands.c:1207
client_connect
void client_connect(const char hostname[static 1])
Definition: client.c:289
exp_table_max
guint16 exp_table_max
Definition: client.c:64
replyinfo_status
int replyinfo_status
Definition: client.c:57
MapExtendedCmd
void MapExtendedCmd(unsigned char *data, int len)
Definition: commands.c:2262
VERSION_INFO
char VERSION_INFO[MAX_BUF]
Definition: client.c:48
skill_mapping
NameMapping skill_mapping[MAX_SKILL]
Definition: client.c:67
SinkCmd
void SinkCmd(unsigned char *data, int len)
Definition: commands.c:2377
NewmapCmd
void NewmapCmd(unsigned char *data, int len)
Definition: commands.c:2055
wantloginmethod
int wantloginmethod
Definition: client.c:61
in
static GInputStream * in
Definition: client.c:71
exp_table
guint64 * exp_table
Definition: client.c:65
mapdata.h
last_used_skills
int last_used_skills[MAX_SKILL+1]
Definition: client.c:55
Face_Information_struct::cache_misses
gint16 cache_misses
Definition: client.h:416
FailureCmd
void FailureCmd(char *buf, int len)
Definition: commands.c:2416
client_get_source
GSource * client_get_source()
Definition: client.c:324
NCOMMANDS
#define NCOMMANDS
Definition: client.c:167
CONFIG_CACHE
#define CONFIG_CACHE
Definition: client.h:187
SendAddMe
void SendAddMe(ClientSocket csock)
Definition: init.c:76
MAX_BUF
#define MAX_BUF
Definition: client.h:40
MusicCmd
void MusicCmd(const char *data, int len)
Definition: sound.c:113
want_skill_exp
int want_skill_exp
Definition: client.c:57
image_update_download_status
void image_update_download_status(int start, int end, int total)
Definition: image.c:309
debug_protocol
bool debug_protocol
Definition: main.c:61
ClientSocket::servername
char * servername
Definition: client.h:135
Map2Cmd
void Map2Cmd(unsigned char *data, int len)
Definition: commands.c:2081
PickupCmd
void PickupCmd(guint8 *data, int len)
Definition: commands.c:2402
client_run
void client_run()
Definition: client.c:202
NDI_GOLD
#define NDI_GOLD
Definition: newclient.h:233
CmdMapping::cmdproc
void(* cmdproc)(unsigned char *, int)
Definition: client.c:90
MAX_SKILL
#define MAX_SKILL
Definition: client.h:84
map_scrollCmd
void map_scrollCmd(char *data, int len)
Definition: commands.c:2194
Face_Information_struct::want_faceset
char * want_faceset
Definition: client.h:407
LOG
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:111
client_error_quark
GQuark client_error_quark()
Definition: client.h:631
cs_print_string
int cs_print_string(GSocketConnection *fd, const char *str,...)
Definition: newsocket.c:252
width
static int width
Definition: mapdata.c:98
NODATA
@ NODATA
Definition: script.h:50
config_dir
const char * config_dir
Definition: client.c:52
DrawInfoCmd
void DrawInfoCmd(char *data, int len)
Definition: commands.c:1227
want_config
gint16 want_config[CONFIG_NUMS]
Definition: init.c:41
draw_ext_info
void draw_ext_info(int orig_color, int type, int subtype, const char *message)
Definition: info.c:915
csocket
ClientSocket csocket
Definition: client.c:70
RI_IMAGE_INFO
#define RI_IMAGE_INFO
Definition: client.h:518
SockList::len
size_t len
Definition: newclient.h:656
SOL_TCP
#define SOL_TCP
Definition: client.h:37
Face2Cmd
void Face2Cmd(guint8 *data, int len)
Definition: image.c:526
StatsCmd
void StatsCmd(unsigned char *data, int len)
Definition: commands.c:1368
SendVersion
void SendVersion(ClientSocket csock)
Definition: init.c:71
UpdspellCmd
void UpdspellCmd(unsigned char *data, int len)
Definition: commands.c:1963
ClientSocket
Definition: client.h:123
printable
char * printable(void *data, int len)
Definition: client.c:186
LOG_ERROR
@ LOG_ERROR
Warning that something definitely didn't work.
Definition: client.h:436
ASCII
@ ASCII
Definition: script.h:44
Image2Cmd
void Image2Cmd(guint8 *data, int len)
Definition: image.c:552
CONFIG_MAPWIDTH
#define CONFIG_MAPWIDTH
Definition: client.h:201
Player_Struct
Definition: client.h:333
cpl
Client_Player cpl
Definition: client.c:69
MSG_TYPE_CLIENT_CONFIG
#define MSG_TYPE_CLIENT_CONFIG
Definition: newclient.h:630
Item2Cmd
void Item2Cmd(unsigned char *data, int len)
Definition: commands.c:1677
ClientSocket::cs_version
int cs_version
Definition: client.h:125
AddMeSuccess
void AddMeSuccess(char *data, int len)
Definition: commands.c:1126
MagicMapCmd
void MagicMapCmd(unsigned char *data, int len)
Definition: commands.c:2324
error_dialog
void error_dialog(char *error, char *message)
Definition: main.c:314
replyinfo_last_face
int replyinfo_last_face
Definition: client.c:58
CONFIG_SMOOTH
#define CONFIG_SMOOTH
Definition: client.h:208
AddspellCmd
void AddspellCmd(unsigned char *data, int len)
Definition: commands.c:1878
RI_IMAGE_SUMS
#define RI_IMAGE_SUMS
Definition: client.h:519
SHORT_ARRAY
@ SHORT_ARRAY
Definition: script.h:45
Face_Information_struct::faceset
guint8 faceset
Definition: client.h:406
AnimCmd
void AnimCmd(unsigned char *data, int len)
Definition: commands.c:1162
script.h
CmdMapping::cmdformat
enum CmdFormat cmdformat
Definition: client.c:91
use_config
gint16 use_config[CONFIG_NUMS]
Definition: client.h:242
AccountPlayersCmd
void AccountPlayersCmd(char *buf, int len)
Definition: commands.c:2462
DeleteInventory
void DeleteInventory(unsigned char *data, int len)
Definition: commands.c:1837
Face_Information_struct::cache_hits
gint16 cache_hits
Definition: client.h:416
sound_server
char * sound_server
Definition: client.c:51
CONFIG_MAPHEIGHT
#define CONFIG_MAPHEIGHT
Definition: client.h:202
CONFIG_FASTTCP
#define CONFIG_FASTTCP
Definition: client.h:185
maxfd
int maxfd
Definition: client.c:58
Sound2Cmd
void Sound2Cmd(unsigned char *data, int len)
Definition: sound.c:38
SockList::buf
unsigned char buf[MAXSOCKBUF]
Definition: newclient.h:657
SetupCmd
void SetupCmd(char *buf, int len)
Definition: commands.c:901
serverloginmethod
int serverloginmethod
Definition: client.c:62
SHORT_INT
@ SHORT_INT
Definition: script.h:47
skill_names
char * skill_names[MAX_SKILL]
Definition: client.c:50
SockList
Definition: newclient.h:651
LOG_DEBUG
@ LOG_DEBUG
Useful debugging information.
Definition: client.h:433
VersionCmd
void VersionCmd(char *data, int len)
Definition: init.c:45
client_mapsize
void client_mapsize(int width, int height)
Definition: client.c:171
client.h
UpdateItemCmd
void UpdateItemCmd(unsigned char *data, int len)
Definition: commands.c:1727
CompleteCmd
void CompleteCmd(unsigned char *data, int len)
Definition: player.c:319
client_negotiate
void client_negotiate(int sound)
Definition: client.c:329