#include "cool.h" #include "string.h" #include "netio.h" #include "buf.h" #include "netio_private.h" #include "servers.h" static const char *create_fail = "Either there is already a player with that name, or that name is illegal.\r\n"; static const char *connect_fail = "Either that player does not exist, or has a different password.\r\n"; static void check_connect (Player * p, char *msg); static void stop_programming (Player * p); static struct timeval msec2timeval (int msec); static void player_command (Player * p, char *command); void tell (Playerid player, const char *msg) { Player *p; String *str; for (p = players; p; p = p->next) { if (p->connected && p->id == player) { str = string_cpy (msg); str = string_cat (str, "\r\n"); buf_add (&p->output, str); break; } } } void boot (Playerid who) { Player *p; for (p = players; p; p = p->next) { if (p->connected && p->id == who) { send (p->fd, DISCONNECT_MSG, strlen (DISCONNECT_MSG), 0); disconnect_player (p->id); remove_player (p); break; } } } void player_command (Player * p, char *command) { if (!p->connected) { check_connect (p, command); } else if (p->isprogramming) { if (!strcmp (command, ".")) { stop_programming (p); } else { fprintf (p->progfile, "%s\n", command); } } else { while (isspace ((int)*command)) { command++; } p->parsing = 1; parse (p->id, command); } } void parse_done (Playerid player) { Player *p; for (p = players; p; p = p->next) { if (p->id == player) { p->parsing = 0; } } } static Player *find_connect (Playerid player, Player * not) { Player *p; for (p = players; p; p = p->next) { if (p != not && p->connected && p->id == player) { return p; } } return 0; } static void check_connect (Player * p, char *msg) { char *command, *user, *password; Playerid player; Player *oldp; parse_connect (msg, &command, &user, &password); if (!strncmp (command, "co", 2)) { player = connect_player (user, password); if (player == NOTHING) { send (p->fd, connect_fail, strlen (connect_fail), 0); writelog (); fprintf (stderr, "Player failed connect %s on descriptor %d\n", user, p->fd); } else if ((oldp = find_connect (player, p))) { writelog (); fprintf (stderr, "Player %s(#%d) transferred from fd %d to fd %d\n", user, player, oldp->fd, p->fd); p->connected = 1; p->id = player; send (oldp->fd, TRANSFER_MSG1, strlen (TRANSFER_MSG1), 0); remove_player (oldp); send (p->fd, TRANSFER_MSG2, strlen (TRANSFER_MSG2), 0); send (p->fd, CONNECT_MSG, strlen (CONNECT_MSG), 0); } else { writelog (); fprintf (stderr, "Player connected %s(#%d) on descriptor %d\n", user, player, p->fd); p->connected = 1; p->id = player; send (p->fd, CONNECT_MSG, strlen (CONNECT_MSG), 0); } } else if (!strncmp (command, "cr", 2) && !registration) { player = create_player (user, password); if (player == NOTHING) { send (p->fd, create_fail, strlen (create_fail), 0); writelog (); fprintf (stderr, "Player failed create %s on descriptor %d\n", user, p->fd); } else { writelog (); fprintf (stderr, "Player created: %s(#%d) on descriptor %d\n", user, player, p->fd); p->connected = 1; p->id = player; send (p->fd, CONNECT_MSG, strlen (CONNECT_MSG), 0); } } else { buf_add (&(p->output), string_cpy (welcome)); } } void parse_connect (char *msg, char **command, char **user, char **pass) { while (*msg && isascii (*msg) && isspace ((int)*msg)) /* skip whitespace */ msg++; *command = msg; while (*msg && isascii (*msg) && !isspace ((int)*msg)) /* skip command */ msg++; if (*msg) { *msg++ = '\0'; /* terminate cmd */ } while (*msg && isascii (*msg) && isspace ((int)*msg)) /* skip whitespace */ msg++; *user = msg; while (*msg && isascii (*msg) && !isspace ((int)*msg)) /* skip user */ msg++; if (*msg) { *msg++ = '\0'; /* terminate user */ } while (*msg && isascii (*msg) && isspace ((int)*msg)) /* skip whitespace */ msg++; *pass = msg; while (*msg && isascii (*msg) && !isspace ((int)*msg)) /* skip password */ msg++; *msg = '\0'; /* terminate pass */ } int start_programming (Playerid player, void **progwhat) { Player *p; for (p = players; p; p = p->next) { if (p->id == player) { break; } } if (!p) { return -1; } sprintf (p->progfilename, "%s/%s_%d", PROGDIR, serv_id2name (0), player); if (!(p->progfile = fopen (p->progfilename, "wb"))) { writelog (); fprintf (stderr, "Couldn't open programming temp file "); perror (p->progfilename); p->progfilename[0] = '\0'; return -2; } else { p->isprogramming = 1; p->progwhat = (void *) progwhat; return 0; } } static Playerid progr; /* programmer */ static void stop_programming (Player * p) { fclose (p->progfile); p->isprogramming = 0; if (!(p->progfile = fopen (p->progfilename, "rb"))) { writelog (); perror (p->progfilename); } else { progr = p->id; do_compile (p->id, p->progfile, p->progwhat); fclose (p->progfile); unlink (p->progfilename); } tell (p->id, "Exiting programming mode."); p->progfilename[0] = '\0'; p->progfile = 0; } #define MSEC(T) (T.tv_sec * 1000 + T.tv_usec / 1000) static struct timeval msec2timeval (int msec) { struct timeval r; r.tv_sec = msec / 1000; r.tv_usec = (msec % 1000) * 1000; return r; } void queue_player_commands (struct timeval cur_time, struct timeval *timeout) { Player *p; int msec_since_last; static struct timeval last = { 0, 0 }; struct timeval new; msec_since_last = MSEC (cur_time) - MSEC (last); last = cur_time; for (p = players; p; p = p->next) { p->quota += msec_since_last; if (p->quota > MAX_CMDS * MSEC_PER_CMD) { p->quota = MAX_CMDS * MSEC_PER_CMD; } if (p->input.head && p->quota >= 0 && !p->parsing) { player_command (p, p->input.head->str->str); buf_delhead (&p->input); if (!p->isprogramming) { p->quota -= MSEC_PER_CMD; } } if (p->input.head && p->quota < 0) { /* return when quota is positive */ new = msec2timeval (-p->quota); *timeout = (timercmp (&new, timeout, <))? new : *timeout; } } }