--- deliantra/server/socket/request.C 2006/09/07 20:03:21 1.15 +++ deliantra/server/socket/request.C 2006/09/10 13:43:33 1.16 @@ -1,6 +1,7 @@ + /* * static char *rcsid_init_c = - * "$Id: request.C,v 1.15 2006/09/07 20:03:21 pippijn Exp $"; + * "$Id: request.C,v 1.16 2006/09/10 13:43:33 root Exp $"; */ /* @@ -66,20 +67,20 @@ /* This block is basically taken from socket.c - I assume if it works there, * it should work here. */ -#ifndef WIN32 /* ---win32 exclude unix headers */ -#include -#include -#include -#include -#include +#ifndef WIN32 /* ---win32 exclude unix headers */ +# include +# include +# include +# include +# include #endif /* win32 */ #ifdef HAVE_UNISTD_H -#include +# include #endif #ifdef HAVE_SYS_TIME_H -#include +# include #endif #include "sounds.h" @@ -90,92 +91,97 @@ * client. If a value is -1, then we don't send that to the * client. */ -short atnr_cs_stat[NROFATTACKS] = {CS_STAT_RES_PHYS, - CS_STAT_RES_MAG,CS_STAT_RES_FIRE, CS_STAT_RES_ELEC, - CS_STAT_RES_COLD, CS_STAT_RES_CONF, CS_STAT_RES_ACID, - CS_STAT_RES_DRAIN, -1 /* weaponmagic */, - CS_STAT_RES_GHOSTHIT, CS_STAT_RES_POISON, - CS_STAT_RES_SLOW, CS_STAT_RES_PARA, CS_STAT_TURN_UNDEAD, - CS_STAT_RES_FEAR, -1 /* Cancellation */, - CS_STAT_RES_DEPLETE, CS_STAT_RES_DEATH, - -1 /* Chaos */, -1 /* Counterspell */, - -1 /* Godpower */, CS_STAT_RES_HOLYWORD, - CS_STAT_RES_BLIND, - -1, /* Internal */ - -1, /* life stealing */ - -1 /* Disease - not fully done yet */ +short atnr_cs_stat[NROFATTACKS] = { CS_STAT_RES_PHYS, + CS_STAT_RES_MAG, CS_STAT_RES_FIRE, CS_STAT_RES_ELEC, + CS_STAT_RES_COLD, CS_STAT_RES_CONF, CS_STAT_RES_ACID, + CS_STAT_RES_DRAIN, -1 /* weaponmagic */ , + CS_STAT_RES_GHOSTHIT, CS_STAT_RES_POISON, + CS_STAT_RES_SLOW, CS_STAT_RES_PARA, CS_STAT_TURN_UNDEAD, + CS_STAT_RES_FEAR, -1 /* Cancellation */ , + CS_STAT_RES_DEPLETE, CS_STAT_RES_DEATH, + -1 /* Chaos */ , -1 /* Counterspell */ , + -1 /* Godpower */ , CS_STAT_RES_HOLYWORD, + CS_STAT_RES_BLIND, + -1, /* Internal */ + -1, /* life stealing */ + -1 /* Disease - not fully done yet */ }; static void -socket_map_scroll (NewSocket *ns, int dx, int dy) +socket_map_scroll (NewSocket * ns, int dx, int dy) { - struct Map newmap; - int x,y, mx, my; + struct Map newmap; + int x, y, mx, my; - { - char buf[MAXSOCKBUF]; + { + char buf[MAXSOCKBUF]; - sprintf(buf,"map_scroll %d %d", dx, dy); - Write_String_To_Socket(ns, buf, strlen (buf)); - } + sprintf (buf, "map_scroll %d %d", dx, dy); + Write_String_To_Socket (ns, buf, strlen (buf)); + } - /* If we are using the Map1aCmd, we may in fact send - * head information that is outside the viewable map. - * So set the mx,my to the max value we want to - * look for. Removed code to do so - it caused extra - * complexities for the client, and probably doesn't make - * that much difference in bandwidth. - */ - mx = ns->mapx; - my = ns->mapy; + /* If we are using the Map1aCmd, we may in fact send + * head information that is outside the viewable map. + * So set the mx,my to the max value we want to + * look for. Removed code to do so - it caused extra + * complexities for the client, and probably doesn't make + * that much difference in bandwidth. + */ + mx = ns->mapx; + my = ns->mapy; - if (ns->mapmode == Map1aCmd) { - mx += MAX_HEAD_OFFSET; - my += MAX_HEAD_OFFSET; + if (ns->mapmode == Map1aCmd) + { + mx += MAX_HEAD_OFFSET; + my += MAX_HEAD_OFFSET; } - /* the x and y here are coordinates for the new map, i.e. if we moved - * (dx,dy), newmap[x][y] = oldmap[x-dx][y-dy]. For this reason, - * if the destination x or y coordinate is outside the viewable - * area, we clear the values - otherwise, the old values - * are preserved, and the check_head thinks it needs to clear them. - */ - for(x=0; x= ns->mapx || y >= ns->mapy) { - /* clear cells outside the viewable area */ - memset(&newmap.cells[x][y], 0, sizeof(struct MapCell)); + /* the x and y here are coordinates for the new map, i.e. if we moved + * (dx,dy), newmap[x][y] = oldmap[x-dx][y-dy]. For this reason, + * if the destination x or y coordinate is outside the viewable + * area, we clear the values - otherwise, the old values + * are preserved, and the check_head thinks it needs to clear them. + */ + for (x = 0; x < mx; x++) + { + for (y = 0; y < my; y++) + { + if (x >= ns->mapx || y >= ns->mapy) + { + /* clear cells outside the viewable area */ + memset (&newmap.cells[x][y], 0, sizeof (struct MapCell)); } - else if ((x+dx) < 0 || (x+dx) >= ns->mapx || (y+dy) < 0 || (y + dy) >= ns->mapy) { - /* clear newly visible tiles within the viewable area */ - memset(&(newmap.cells[x][y]), 0, sizeof(struct MapCell)); + else if ((x + dx) < 0 || (x + dx) >= ns->mapx || (y + dy) < 0 || (y + dy) >= ns->mapy) + { + /* clear newly visible tiles within the viewable area */ + memset (&(newmap.cells[x][y]), 0, sizeof (struct MapCell)); } - else { - memcpy(&(newmap.cells[x][y]), - &(ns->lastmap.cells[x+dx][y+dy]),sizeof(struct MapCell)); + else + { + memcpy (&(newmap.cells[x][y]), &(ns->lastmap.cells[x + dx][y + dy]), sizeof (struct MapCell)); } } } - memcpy(&(ns->lastmap), &newmap,sizeof(struct Map)); + memcpy (&(ns->lastmap), &newmap, sizeof (struct Map)); - /* Make sure that the next "map1" command will be sent (even if it is - * empty). - */ - ns->sent_scroll = 1; + /* Make sure that the next "map1" command will be sent (even if it is + * empty). + */ + ns->sent_scroll = 1; } static void clear_map (player *pl) { - NewSocket &socket = pl->socket; + NewSocket & socket = pl->socket; memset (&socket.lastmap, 0, sizeof (socket.lastmap)); if (socket.newmapcmd == 1) Write_String_To_Socket (&socket, "newmap", 6); - socket.update_look = 1; + socket.update_look = 1; socket.look_position = 0; } @@ -183,9 +189,9 @@ static void check_map_change (player *pl) { - NewSocket &socket = pl->socket; + NewSocket & socket = pl->socket; object *ob = pl->ob; - char buf[MAX_BUF]; /* eauugggh */ + char buf[MAX_BUF]; /* eauugggh */ if (socket.current_map != ob->map) { @@ -195,24 +201,27 @@ if (socket.mapinfocmd) { - if (ob->map && ob->map->path [0]) + if (ob->map && ob->map->path[0]) { int flags = 0; - if (ob->map->tile_path [0]) flags |= 1; - if (ob->map->tile_path [1]) flags |= 2; - if (ob->map->tile_path [2]) flags |= 4; - if (ob->map->tile_path [3]) flags |= 8; + if (ob->map->tile_path[0]) + flags |= 1; + if (ob->map->tile_path[1]) + flags |= 2; + if (ob->map->tile_path[2]) + flags |= 4; + if (ob->map->tile_path[3]) + flags |= 8; snprintf (buf, MAX_BUF, "mapinfo - spatial %d %d %d %d %d %s", - flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y, - ob->map->width, ob->map->height, ob->map->path); + flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y, ob->map->width, ob->map->height, ob->map->path); } else snprintf (buf, MAX_BUF, "mapinfo current"); Write_String_To_Socket (&socket, buf, strlen (buf)); - } + } } else if (socket.current_x != ob->x || socket.current_y != ob->y) { @@ -220,7 +229,7 @@ int dy = ob->y - socket.current_y; if (socket.buggy_mapscroll && (abs (dx) > 8 || abs (dy) > 8)) - clear_map (pl); // current (<= 1.9.1) clients have unchecked buffer overflows + clear_map (pl); // current (<= 1.9.1) clients have unchecked buffer overflows else { socket_map_scroll (&socket, ob->x - socket.current_x, ob->y - socket.current_y); @@ -233,16 +242,18 @@ socket.current_y = ob->y; } -void ExtCmd (char *buf, int len, player *pl) +void +ExtCmd (char *buf, int len, player *pl) { INVOKE_PLAYER (EXTCMD, pl, ARG_DATA (buf, len)); } -void MapInfoCmd (char *buf, int len, player *pl) +void +MapInfoCmd (char *buf, int len, player *pl) { // mapinfo tag spatial flags x y w h hash - + char bigbuf[MAX_BUF], *token; token = buf; @@ -261,7 +272,7 @@ sint16 dx, dy; int mapx = pl->socket.mapx / 2 - pl->ob->x; int mapy = pl->socket.mapy / 2 - pl->ob->y; - int max_distance = 8; // limit maximum path length to something generous + int max_distance = 8; // limit maximum path length to something generous while (*buf && map && max_distance) { @@ -269,22 +280,30 @@ switch (dir) { - case '1': - dx = 0; dy = -1; map = get_map_from_coord (map, &dx, &dy); - map && (mapy -= map->height); - break; - case '2': - mapx += map->width; - dx = map->width; dy = 0; map = get_map_from_coord (map, &dx, &dy); - break; - case '3': - mapy += map->height; - dx = 0; dy = map->height; map = get_map_from_coord (map, &dx, &dy); - break; - case '4': - dx = -1; dy = 0; map = get_map_from_coord (map, &dx, &dy); - map && (mapx -= map->width); - break; + case '1': + dx = 0; + dy = -1; + map = get_map_from_coord (map, &dx, &dy); + map && (mapy -= map->height); + break; + case '2': + mapx += map->width; + dx = map->width; + dy = 0; + map = get_map_from_coord (map, &dx, &dy); + break; + case '3': + mapy += map->height; + dx = 0; + dy = map->height; + map = get_map_from_coord (map, &dx, &dy); + break; + case '4': + dx = -1; + dy = 0; + map = get_map_from_coord (map, &dx, &dy); + map && (mapx -= map->width); + break; } --max_distance; @@ -292,184 +311,236 @@ if (!max_distance) snprintf (bigbuf, MAX_BUF, "mapinfo %s error", token); - else if (map && map->path [0]) + else if (map && map->path[0]) { int flags = 0; - if (map->tile_path [0]) flags |= 1; - if (map->tile_path [1]) flags |= 2; - if (map->tile_path [2]) flags |= 4; - if (map->tile_path [3]) flags |= 8; - - snprintf (bigbuf, MAX_BUF, "mapinfo %s spatial %d %d %d %d %d %s", - token, flags, mapx, mapy, - map->width, map->height, map->path); + if (map->tile_path[0]) + flags |= 1; + if (map->tile_path[1]) + flags |= 2; + if (map->tile_path[2]) + flags |= 4; + if (map->tile_path[3]) + flags |= 8; + + snprintf (bigbuf, MAX_BUF, "mapinfo %s spatial %d %d %d %d %d %s", token, flags, mapx, mapy, map->width, map->height, map->path); } else snprintf (bigbuf, MAX_BUF, "mapinfo %s nomap", token); } else snprintf (bigbuf, MAX_BUF, "mapinfo %s unsupported", token); - + Write_String_To_Socket (&pl->socket, bigbuf, strlen (bigbuf)); } /** This is the Setup cmd - easy first implementation */ -void SetUp(char *buf, int len, NewSocket *ns) +void +SetUp (char *buf, int len, NewSocket * ns) { - int s, slen; - char *cmd, *param, cmdback[HUGE_BUF]; + int s, slen; + char *cmd, *param, cmdback[HUGE_BUF]; - /* run through the cmds of setup - * syntax is setup ... - * - * we send the status of the cmd back, or a FALSE is the cmd is the server unknown - * The client then must sort this out - */ - - LOG(llevInfo,"Get SetupCmd:: %s\n", buf); - strcpy(cmdback,"setup"); - for(s=0;s ... + * + * we send the status of the cmd back, or a FALSE is the cmd is the server unknown + * The client then must sort this out + */ + + LOG (llevInfo, "Get SetupCmd:: %s\n", buf); + strcpy (cmdback, "setup"); + for (s = 0; s < len;) + { - if(s>=len) - break; + cmd = &buf[s]; - param = &buf[s]; + /* find the next space, and put a null there */ + for (; buf[s] && buf[s] != ' '; s++); + buf[s++] = 0; + while (buf[s] == ' ') + s++; - for(;buf[s] && buf[s] != ' ';s++) ; - buf[s++]=0; - while (buf[s] == ' ') s++; - - slen = strlen(cmdback); - safe_strcat(cmdback, " ", &slen, HUGE_BUF); - safe_strcat(cmdback, cmd, &slen, HUGE_BUF); - safe_strcat(cmdback, " ", &slen, HUGE_BUF); - - if (!strcmp(cmd,"sound")) { - ns->sound = atoi(param); - safe_strcat(cmdback, param, &slen, HUGE_BUF); - } - else if (!strcmp(cmd,"exp64")) { - ns->exp64 = atoi(param); - safe_strcat(cmdback, param, &slen, HUGE_BUF); - } else if (!strcmp(cmd, "spellmon")) { - ns->monitor_spells = atoi(param); - safe_strcat(cmdback, param, &slen, HUGE_BUF); - } else if (!strcmp(cmd,"darkness")) { - ns->darkness = atoi(param); - safe_strcat(cmdback, param, &slen, HUGE_BUF); - } else if (!strcmp(cmd,"map1cmd")) { - if (atoi(param)) ns->mapmode = Map1Cmd; - /* if beyond this size, need to use map1cmd no matter what */ - if (ns->mapx>11 || ns->mapy>11) ns->mapmode = Map1Cmd; - safe_strcat(cmdback, ns->mapmode == Map1Cmd?"1":"0", &slen, HUGE_BUF); - } else if (!strcmp(cmd,"map1acmd")) { - if (atoi(param)) ns->mapmode = Map1aCmd; - /* if beyond this size, need to use map1acmd no matter what */ - if (ns->mapx>11 || ns->mapy>11) ns->mapmode = Map1aCmd; - safe_strcat(cmdback, ns->mapmode == Map1aCmd?"1":"0", &slen, HUGE_BUF); - } else if (!strcmp(cmd,"newmapcmd")) { - ns->newmapcmd= atoi(param); - safe_strcat(cmdback, param, &slen, HUGE_BUF); + if (s >= len) + break; + + param = &buf[s]; + + for (; buf[s] && buf[s] != ' '; s++); + buf[s++] = 0; + while (buf[s] == ' ') + s++; + + slen = strlen (cmdback); + safe_strcat (cmdback, " ", &slen, HUGE_BUF); + safe_strcat (cmdback, cmd, &slen, HUGE_BUF); + safe_strcat (cmdback, " ", &slen, HUGE_BUF); + + if (!strcmp (cmd, "sound")) + { + ns->sound = atoi (param); + safe_strcat (cmdback, param, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "exp64")) + { + ns->exp64 = atoi (param); + safe_strcat (cmdback, param, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "spellmon")) + { + ns->monitor_spells = atoi (param); + safe_strcat (cmdback, param, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "darkness")) + { + ns->darkness = atoi (param); + safe_strcat (cmdback, param, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "map1cmd")) + { + if (atoi (param)) + ns->mapmode = Map1Cmd; + /* if beyond this size, need to use map1cmd no matter what */ + if (ns->mapx > 11 || ns->mapy > 11) + ns->mapmode = Map1Cmd; + safe_strcat (cmdback, ns->mapmode == Map1Cmd ? "1" : "0", &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "map1acmd")) + { + if (atoi (param)) + ns->mapmode = Map1aCmd; + /* if beyond this size, need to use map1acmd no matter what */ + if (ns->mapx > 11 || ns->mapy > 11) + ns->mapmode = Map1aCmd; + safe_strcat (cmdback, ns->mapmode == Map1aCmd ? "1" : "0", &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "newmapcmd")) + { + ns->newmapcmd = atoi (param); + safe_strcat (cmdback, param, &slen, HUGE_BUF); // } else if (!strcmp(cmd,"plugincmd")) { // ns->plugincmd = atoi(param); -// safe_strcat(cmdback, param, &slen, HUGE_BUF); - } else if (!strcmp(cmd,"mapinfocmd")) { - ns->mapinfocmd = atoi(param); - safe_strcat(cmdback, "1", &slen, HUGE_BUF); - } else if (!strcmp(cmd,"extcmd")) { - ns->extcmd = atoi(param); - safe_strcat(cmdback, "1", &slen, HUGE_BUF); - } else if (!strcmp(cmd,"extmap")) { - ns->extmap = atoi(param); - safe_strcat(cmdback, "1", &slen, HUGE_BUF); - } else if (!strcmp(cmd,"facecache")) { - ns->facecache = atoi(param); - safe_strcat(cmdback, param, &slen, HUGE_BUF); - } else if (!strcmp(cmd,"faceset")) { - char tmpbuf[20]; - int q = atoi(param); - - if (is_valid_faceset(q)) - ns->faceset=q; - sprintf(tmpbuf,"%d", ns->faceset); - safe_strcat(cmdback, tmpbuf, &slen, HUGE_BUF); - /* if the client is using faceset, it knows about image2 command */ - ns->image2=1; - } else if (!strcmp(cmd,"itemcmd")) { - /* Version of the item protocol command to use. Currently, - * only supported versions are 1 and 2. Using a numeric - * value will make it very easy to extend this in the future. - */ - char tmpbuf[20]; - int q = atoi(param); - if (q<1 || q>2) { - strcpy(tmpbuf,"FALSE"); - } else { - ns->itemcmd = q; - sprintf(tmpbuf,"%d", ns->itemcmd); - } - safe_strcat(cmdback, tmpbuf, &slen, HUGE_BUF); - } else if (!strcmp(cmd,"mapsize")) { - int x, y=0; - char tmpbuf[MAX_BUF], *cp; - - x = atoi(param); - for (cp = param; *cp!=0; cp++) - if (*cp == 'x' || *cp == 'X') { - y = atoi(cp+1); - break; - } - if (x < 9 || y < 9 || x>MAP_CLIENT_X || y > MAP_CLIENT_Y) { - sprintf(tmpbuf," %dx%d", MAP_CLIENT_X, MAP_CLIENT_Y); - safe_strcat(cmdback, tmpbuf, &slen, HUGE_BUF); - } else { - ns->mapx = x; - ns->mapy = y; - /* better to send back what we are really using and not the - * param as given to us in case it gets parsed differently. - */ - sprintf(tmpbuf,"%dx%d", x,y); - safe_strcat(cmdback, tmpbuf, &slen, HUGE_BUF); - /* If beyond this size and still using orig map command, need to - * go to map1cmd. - */ - if ((x>11 || y>11) && ns->mapmode == Map0Cmd) ns->mapmode = Map1Cmd; - } - } else if (!strcmp(cmd,"extendedMapInfos")) { - /* Added by tchize - * prepare to use the mapextended command - */ - char tmpbuf[20]; - ns->ext_mapinfos = (atoi(param)); - sprintf(tmpbuf,"%d", ns->ext_mapinfos); - safe_strcat(cmdback, tmpbuf, &slen, HUGE_BUF); - } else if (!strcmp(cmd,"extendedTextInfos")) { - /* Added by tchize - * prepare to use the extended text commands - * Client toggle this to non zero to get exttext - */ - char tmpbuf[20]; - - ns->has_readable_type = (atoi(param)); - sprintf(tmpbuf,"%d", ns->has_readable_type); - safe_strcat(cmdback, tmpbuf, &slen, HUGE_BUF); - } else { - /* Didn't get a setup command we understood - - * report a failure to the client. - */ - safe_strcat(cmdback, "FALSE", &slen, HUGE_BUF); - } - } /* for processing all the setup commands */ - LOG(llevInfo,"SendBack SetupCmd:: %s\n", cmdback); - Write_String_To_Socket(ns, cmdback, strlen(cmdback)); +// safe_strcat(cmdback, param, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "mapinfocmd")) + { + ns->mapinfocmd = atoi (param); + safe_strcat (cmdback, "1", &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "extcmd")) + { + ns->extcmd = atoi (param); + safe_strcat (cmdback, "1", &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "extmap")) + { + ns->extmap = atoi (param); + safe_strcat (cmdback, "1", &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "facecache")) + { + ns->facecache = atoi (param); + safe_strcat (cmdback, param, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "faceset")) + { + char tmpbuf[20]; + int q = atoi (param); + + if (is_valid_faceset (q)) + ns->faceset = q; + sprintf (tmpbuf, "%d", ns->faceset); + safe_strcat (cmdback, tmpbuf, &slen, HUGE_BUF); + /* if the client is using faceset, it knows about image2 command */ + ns->image2 = 1; + } + else if (!strcmp (cmd, "itemcmd")) + { + /* Version of the item protocol command to use. Currently, + * only supported versions are 1 and 2. Using a numeric + * value will make it very easy to extend this in the future. + */ + char tmpbuf[20]; + int q = atoi (param); + + if (q < 1 || q > 2) + { + strcpy (tmpbuf, "FALSE"); + } + else + { + ns->itemcmd = q; + sprintf (tmpbuf, "%d", ns->itemcmd); + } + safe_strcat (cmdback, tmpbuf, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "mapsize")) + { + int x, y = 0; + char tmpbuf[MAX_BUF], *cp; + + x = atoi (param); + for (cp = param; *cp != 0; cp++) + if (*cp == 'x' || *cp == 'X') + { + y = atoi (cp + 1); + break; + } + if (x < 9 || y < 9 || x > MAP_CLIENT_X || y > MAP_CLIENT_Y) + { + sprintf (tmpbuf, " %dx%d", MAP_CLIENT_X, MAP_CLIENT_Y); + safe_strcat (cmdback, tmpbuf, &slen, HUGE_BUF); + } + else + { + ns->mapx = x; + ns->mapy = y; + /* better to send back what we are really using and not the + * param as given to us in case it gets parsed differently. + */ + sprintf (tmpbuf, "%dx%d", x, y); + safe_strcat (cmdback, tmpbuf, &slen, HUGE_BUF); + /* If beyond this size and still using orig map command, need to + * go to map1cmd. + */ + if ((x > 11 || y > 11) && ns->mapmode == Map0Cmd) + ns->mapmode = Map1Cmd; + } + } + else if (!strcmp (cmd, "extendedMapInfos")) + { + /* Added by tchize + * prepare to use the mapextended command + */ + char tmpbuf[20]; + + ns->ext_mapinfos = (atoi (param)); + sprintf (tmpbuf, "%d", ns->ext_mapinfos); + safe_strcat (cmdback, tmpbuf, &slen, HUGE_BUF); + } + else if (!strcmp (cmd, "extendedTextInfos")) + { + /* Added by tchize + * prepare to use the extended text commands + * Client toggle this to non zero to get exttext + */ + char tmpbuf[20]; + + ns->has_readable_type = (atoi (param)); + sprintf (tmpbuf, "%d", ns->has_readable_type); + safe_strcat (cmdback, tmpbuf, &slen, HUGE_BUF); + } + else + { + /* Didn't get a setup command we understood - + * report a failure to the client. + */ + safe_strcat (cmdback, "FALSE", &slen, HUGE_BUF); + } + } /* for processing all the setup commands */ + LOG (llevInfo, "SendBack SetupCmd:: %s\n", cmdback); + Write_String_To_Socket (ns, cmdback, strlen (cmdback)); } /** @@ -478,61 +549,76 @@ * I am not sure if this file is the best place for this function. however, * it either has to be here or init_sockets needs to be exported. */ -void AddMeCmd(char *buf, int len, NewSocket *ns) +void +AddMeCmd (char *buf, int len, NewSocket * ns) { - Settings oldsettings; - oldsettings=settings; - if (ns->status != Ns_Add || add_player(ns)) { - Write_String_To_Socket(ns, "addme_failed",12); - } else { - /* Basically, the add_player copies the socket structure into - * the player structure, so this one (which is from init_sockets) - * is not needed anymore. The write below should still work, as the - * stuff in ns is still relevant. - */ - Write_String_To_Socket(ns, "addme_success",13); - socket_info.nconns--; - ns->status = Ns_Avail; + Settings oldsettings; + + oldsettings = settings; + if (ns->status != Ns_Add || add_player (ns)) + { + Write_String_To_Socket (ns, "addme_failed", 12); + } + else + { + /* Basically, the add_player copies the socket structure into + * the player structure, so this one (which is from init_sockets) + * is not needed anymore. The write below should still work, as the + * stuff in ns is still relevant. + */ + Write_String_To_Socket (ns, "addme_success", 13); + socket_info.nconns--; + ns->status = Ns_Avail; } - settings=oldsettings; + settings = oldsettings; } /** Reply to ExtendedInfos command */ -void ToggleExtendedInfos (char *buf, int len, NewSocket *ns){ - char cmdback[MAX_BUF]; - char command[50]; - int info,nextinfo; - cmdback[0]='\0'; - nextinfo=0; - while (1){ - /* 1. Extract an info*/ - info=nextinfo; - while ( (info=len) - break; - nextinfo=info+1; - while ( (nextinfo=49) /*Erroneous info asked*/ - continue; - strncpy (command,&(buf[info]),nextinfo-info); - command[nextinfo-info]='\0'; - /* 2. Interpret info*/ - if (!strcmp("smooth",command)){ - /* Toggle smoothing*/ - ns->EMI_smooth=!ns->EMI_smooth; - }else{ - /*bad value*/ - } - /*3. Next info*/ - } - strcpy (cmdback,"ExtendedInfoSet"); - if (ns->EMI_smooth){ - strcat (cmdback," "); - strcat (cmdback,"smoothing"); - } - Write_String_To_Socket(ns, cmdback,strlen(cmdback)); +void +ToggleExtendedInfos (char *buf, int len, NewSocket * ns) +{ + char cmdback[MAX_BUF]; + char command[50]; + int info, nextinfo; + + cmdback[0] = '\0'; + nextinfo = 0; + while (1) + { + /* 1. Extract an info */ + info = nextinfo; + while ((info < len) && (buf[info] == ' ')) + info++; + if (info >= len) + break; + nextinfo = info + 1; + while ((nextinfo < len) && (buf[nextinfo] != ' ')) + nextinfo++; + if (nextinfo - info >= 49) /*Erroneous info asked */ + continue; + strncpy (command, &(buf[info]), nextinfo - info); + command[nextinfo - info] = '\0'; + /* 2. Interpret info */ + if (!strcmp ("smooth", command)) + { + /* Toggle smoothing */ + ns->EMI_smooth = !ns->EMI_smooth; + } + else + { + /*bad value */ + } + /*3. Next info */ + } + strcpy (cmdback, "ExtendedInfoSet"); + if (ns->EMI_smooth) + { + strcat (cmdback, " "); + strcat (cmdback, "smoothing"); + } + Write_String_To_Socket (ns, cmdback, strlen (cmdback)); } + /* #define MSG_TYPE_BOOK 1 #define MSG_TYPE_CARD 2 @@ -540,42 +626,49 @@ #define MSG_TYPE_SIGN 4 #define MSG_TYPE_MONUMENT 5 #define MSG_TYPE_SCRIPTED_DIALOG 6*/ + /** Reply to ExtendedInfos command */ -void ToggleExtendedText (char *buf, int len, NewSocket *ns){ - char cmdback[MAX_BUF]; - char temp[10]; - char command[50]; - int info,nextinfo,i,flag; - cmdback[0]='\0'; - nextinfo=0; - while (1){ - /* 1. Extract an info*/ - info=nextinfo; - while ( (info=len) - break; - nextinfo=info+1; - while ( (nextinfo=49) /*Erroneous info asked*/ - continue; - strncpy (command,&(buf[info]),nextinfo-info); - command[nextinfo-info]='\0'; - /* 2. Interpret info*/ - i = sscanf(command,"%d",&flag); - if ( (i==1) && (flag>0) && (flag<=MSG_TYPE_LAST)) - ns->supported_readables|=(1<supported_readables &(1<= len) + break; + nextinfo = info + 1; + while ((nextinfo < len) && (buf[nextinfo] != ' ')) + nextinfo++; + if (nextinfo - info >= 49) /*Erroneous info asked */ + continue; + strncpy (command, &(buf[info]), nextinfo - info); + command[nextinfo - info] = '\0'; + /* 2. Interpret info */ + i = sscanf (command, "%d", &flag); + if ((i == 1) && (flag > 0) && (flag <= MSG_TYPE_LAST)) + ns->supported_readables |= (1 << flag); + /*3. Next info */ + } + /* Send resulting state */ + strcpy (cmdback, "ExtendedTextSet"); + for (i = 0; i <= MSG_TYPE_LAST; i++) + if (ns->supported_readables & (1 << i)) + { + strcat (cmdback, " "); + snprintf (temp, sizeof (temp), "%d", i); + strcat (cmdback, temp); + } + Write_String_To_Socket (ns, cmdback, strlen (cmdback)); } /** @@ -585,44 +678,48 @@ * if we know the client wants it, might as well push it to the * client. */ -static void SendSmooth(NewSocket *ns, uint16 face) { - uint16 smoothface; - unsigned char reply[MAX_BUF]; - SockList sl; - - /* If we can't find a face, return and set it so we won't try to send this - * again. - */ - if ((!FindSmooth (face, &smoothface)) && - (!FindSmooth ( smooth_face->number, &smoothface))) { - - LOG(llevError,"could not findsmooth for %d. Neither default (%s)\n", face, &smooth_face->name); - ns->faces_sent[face] |= NS_FACESENT_SMOOTH; - return; - } - - if (!(ns->faces_sent[smoothface] & NS_FACESENT_FACE)) - esrv_send_face(ns, smoothface, 0); - - ns->faces_sent[face] |= NS_FACESENT_SMOOTH; - - sl.buf=reply; - strcpy((char*)sl.buf,"smooth "); - sl.len=strlen((char*)sl.buf); - SockList_AddShort(&sl, face); - SockList_AddShort(&sl, smoothface); - Send_With_Handling(ns, &sl); +static void +SendSmooth (NewSocket * ns, uint16 face) +{ + uint16 smoothface; + unsigned char reply[MAX_BUF]; + SockList sl; + + /* If we can't find a face, return and set it so we won't try to send this + * again. + */ + if ((!FindSmooth (face, &smoothface)) && (!FindSmooth (smooth_face->number, &smoothface))) + { + + LOG (llevError, "could not findsmooth for %d. Neither default (%s)\n", face, &smooth_face->name); + ns->faces_sent[face] |= NS_FACESENT_SMOOTH; + return; + } + + if (!(ns->faces_sent[smoothface] & NS_FACESENT_FACE)) + esrv_send_face (ns, smoothface, 0); + + ns->faces_sent[face] |= NS_FACESENT_SMOOTH; + + sl.buf = reply; + strcpy ((char *) sl.buf, "smooth "); + sl.len = strlen ((char *) sl.buf); + SockList_AddShort (&sl, face); + SockList_AddShort (&sl, smoothface); + Send_With_Handling (ns, &sl); } /** * Tells client the picture it has to use * to smooth a picture number given as argument. */ -void AskSmooth (char *buf, int len, NewSocket *ns){ - uint16 facenbr; +void +AskSmooth (char *buf, int len, NewSocket * ns) +{ + uint16 facenbr; - facenbr=atoi (buf); - SendSmooth(ns, facenbr); + facenbr = atoi (buf); + SendSmooth (ns, facenbr); } @@ -633,46 +730,50 @@ * This handles the general commands from the client (ie, north, fire, cast, * etc.) */ -void PlayerCmd(char *buf, int len, player *pl) +void +PlayerCmd (char *buf, int len, player *pl) { - /* The following should never happen with a proper or honest client. - * Therefore, the error message doesn't have to be too clear - if - * someone is playing with a hacked/non working client, this gives them - * an idea of the problem, but they deserve what they get - */ - if (pl->state!=ST_PLAYING) { - new_draw_info_format(NDI_UNIQUE, 0,pl->ob, - "You can not issue commands - state is not ST_PLAYING (%s)", buf); - return; - } - /* Check if there is a count. In theory, a zero count could also be - * sent, so check for that also. - */ - if (atoi(buf) || buf[0]=='0') { - pl->count=atoi((char*)buf); - buf=strchr(buf,' '); /* advance beyond the numbers */ - if (!buf) { + /* The following should never happen with a proper or honest client. + * Therefore, the error message doesn't have to be too clear - if + * someone is playing with a hacked/non working client, this gives them + * an idea of the problem, but they deserve what they get + */ + if (pl->state != ST_PLAYING) + { + new_draw_info_format (NDI_UNIQUE, 0, pl->ob, "You can not issue commands - state is not ST_PLAYING (%s)", buf); + return; + } + /* Check if there is a count. In theory, a zero count could also be + * sent, so check for that also. + */ + if (atoi (buf) || buf[0] == '0') + { + pl->count = atoi ((char *) buf); + buf = strchr (buf, ' '); /* advance beyond the numbers */ + if (!buf) + { #ifdef ESRV_DEBUG - LOG(llevDebug,"PlayerCmd: Got count but no command.\n"); + LOG (llevDebug, "PlayerCmd: Got count but no command.\n"); #endif - return; + return; } - buf++; + buf++; } - /* This should not happen anymore. */ - if (pl->ob->speed_left<-1.0) { - LOG(llevError,"Player has negative time - shouldn't do command.\n"); - } - /* In c_new.c */ - execute_newserver_command(pl->ob, (char*)buf); - /* Perhaps something better should be done with a left over count. - * Cleaning up the input should probably be done first - all actions - * for the command that issued the count should be done before any other - * commands. - */ + /* This should not happen anymore. */ + if (pl->ob->speed_left < -1.0) + { + LOG (llevError, "Player has negative time - shouldn't do command.\n"); + } + /* In c_new.c */ + execute_newserver_command (pl->ob, (char *) buf); + /* Perhaps something better should be done with a left over count. + * Cleaning up the input should probably be done first - all actions + * for the command that issued the count should be done before any other + * commands. + */ - pl->count=0; + pl->count = 0; } @@ -683,126 +784,134 @@ * 'ncom' method which gives more information back to the client so it * can throttle. */ -void NewPlayerCmd(uint8 *buf, int len, player *pl) +void +NewPlayerCmd (uint8 * buf, int len, player *pl) { - int time,repeat; - short packet; - unsigned char command[MAX_BUF]; - SockList sl; - - if (len < 7) { - LOG(llevDebug,"Corrupt ncom command <%s> not long enough - discarding\n", buf); - return; - } - - packet = GetShort_String(buf); - repeat = GetInt_String(buf+2); - /* -1 is special - no repeat, but don't update */ - if (repeat!=-1) { - pl->count=repeat; - } - if ((len-4) >= MAX_BUF) len=MAX_BUF-5; - - strncpy((char*)command, (char*)buf+6, len-4); - command[len-4]='\0'; - - /* The following should never happen with a proper or honest client. - * Therefore, the error message doesn't have to be too clear - if - * someone is playing with a hacked/non working client, this gives them - * an idea of the problem, but they deserve what they get - */ - if (pl->state!=ST_PLAYING) { - new_draw_info_format(NDI_UNIQUE, 0,pl->ob, - "You can not issue commands - state is not ST_PLAYING (%s)", buf); - return; - } - - /* This should not happen anymore. */ - if (pl->ob->speed_left<-1.0) { - LOG(llevError,"Player has negative time - shouldn't do command.\n"); - } - /* In c_new.c */ - execute_newserver_command(pl->ob, (char*)command); - /* Perhaps something better should be done with a left over count. - * Cleaning up the input should probably be done first - all actions - * for the command that issued the count should be done before any other - * commands. - */ - pl->count=0; - - /* Send confirmation of command execution now */ - sl.buf = command; - strcpy((char*)sl.buf,"comc "); - sl.len=5; - SockList_AddShort(&sl,packet); - if (FABS(pl->ob->speed) < 0.001) time=MAX_TIME * 100; - else - time = ( int )( MAX_TIME/ FABS(pl->ob->speed) ); - SockList_AddInt(&sl,time); - Send_With_Handling(&pl->socket, &sl); + int time, repeat; + short packet; + unsigned char command[MAX_BUF]; + SockList sl; + + if (len < 7) + { + LOG (llevDebug, "Corrupt ncom command <%s> not long enough - discarding\n", buf); + return; + } + + packet = GetShort_String (buf); + repeat = GetInt_String (buf + 2); + /* -1 is special - no repeat, but don't update */ + if (repeat != -1) + { + pl->count = repeat; + } + if ((len - 4) >= MAX_BUF) + len = MAX_BUF - 5; + + strncpy ((char *) command, (char *) buf + 6, len - 4); + command[len - 4] = '\0'; + + /* The following should never happen with a proper or honest client. + * Therefore, the error message doesn't have to be too clear - if + * someone is playing with a hacked/non working client, this gives them + * an idea of the problem, but they deserve what they get + */ + if (pl->state != ST_PLAYING) + { + new_draw_info_format (NDI_UNIQUE, 0, pl->ob, "You can not issue commands - state is not ST_PLAYING (%s)", buf); + return; + } + + /* This should not happen anymore. */ + if (pl->ob->speed_left < -1.0) + { + LOG (llevError, "Player has negative time - shouldn't do command.\n"); + } + /* In c_new.c */ + execute_newserver_command (pl->ob, (char *) command); + /* Perhaps something better should be done with a left over count. + * Cleaning up the input should probably be done first - all actions + * for the command that issued the count should be done before any other + * commands. + */ + pl->count = 0; + + /* Send confirmation of command execution now */ + sl.buf = command; + strcpy ((char *) sl.buf, "comc "); + sl.len = 5; + SockList_AddShort (&sl, packet); + if (FABS (pl->ob->speed) < 0.001) + time = MAX_TIME * 100; + else + time = (int) (MAX_TIME / FABS (pl->ob->speed)); + SockList_AddInt (&sl, time); + Send_With_Handling (&pl->socket, &sl); } /** This is a reply to a previous query. */ -void ReplyCmd(char *buf, int len, player *pl) +void +ReplyCmd (char *buf, int len, player *pl) { - /* This is to synthesize how the data would be stored if it - * was normally entered. A bit of a hack, and should be cleaned up - * once all the X11 code is removed from the server. - * - * We pass 13 to many of the functions because this way they - * think it was the carriage return that was entered, and the - * function then does not try to do additional input. - */ - snprintf(pl->write_buf, sizeof(pl->write_buf), ":%s", buf); - - /* this avoids any hacking here */ - - switch (pl->state) { + /* This is to synthesize how the data would be stored if it + * was normally entered. A bit of a hack, and should be cleaned up + * once all the X11 code is removed from the server. + * + * We pass 13 to many of the functions because this way they + * think it was the carriage return that was entered, and the + * function then does not try to do additional input. + */ + snprintf (pl->write_buf, sizeof (pl->write_buf), ":%s", buf); + + /* this avoids any hacking here */ + + switch (pl->state) + { case ST_PLAYING: - LOG(llevError,"Got reply message with ST_PLAYING input state\n"); - break; + LOG (llevError, "Got reply message with ST_PLAYING input state\n"); + break; case ST_PLAY_AGAIN: - /* We can check this for return value (2==quit). Maybe we - * should, and do something appropriate? - */ - receive_play_again(pl->ob, buf[0]); - break; + /* We can check this for return value (2==quit). Maybe we + * should, and do something appropriate? + */ + receive_play_again (pl->ob, buf[0]); + break; case ST_ROLL_STAT: - key_roll_stat(pl->ob,buf[0]); - break; + key_roll_stat (pl->ob, buf[0]); + break; case ST_CHANGE_CLASS: - key_change_class(pl->ob, buf[0]); - break; + key_change_class (pl->ob, buf[0]); + break; case ST_CONFIRM_QUIT: - key_confirm_quit(pl->ob, buf[0]); - break; + key_confirm_quit (pl->ob, buf[0]); + break; case ST_CONFIGURE: - LOG(llevError,"In client input handling, but into configure state\n"); - pl->state = ST_PLAYING; - break; + LOG (llevError, "In client input handling, but into configure state\n"); + pl->state = ST_PLAYING; + break; case ST_GET_NAME: - receive_player_name(pl->ob,13); - break; + receive_player_name (pl->ob, 13); + break; case ST_GET_PASSWORD: case ST_CONFIRM_PASSWORD: - receive_player_password(pl->ob,13); - break; + receive_player_password (pl->ob, 13); + break; - case ST_GET_PARTY_PASSWORD: /* Get password for party */ - receive_party_password(pl->ob,13); - break; + case ST_GET_PARTY_PASSWORD: /* Get password for party */ + receive_party_password (pl->ob, 13); + break; default: - LOG(llevError,"Unknown input state: %d\n", pl->state); + LOG (llevError, "Unknown input state: %d\n", pl->state); } } @@ -813,77 +922,87 @@ * backwards compatible, having it be a later version should not be a * problem. */ -void VersionCmd(char *buf, int len,NewSocket *ns) +void +VersionCmd (char *buf, int len, NewSocket * ns) { - char *cp; - char version_warning[256]; - - if (!buf) { - LOG(llevError, "CS: received corrupted version command\n"); - return; + char *cp; + char version_warning[256]; + + if (!buf) + { + LOG (llevError, "CS: received corrupted version command\n"); + return; } - ns->cs_version = atoi(buf); - ns->sc_version = ns->cs_version; - if (VERSION_CS != ns->cs_version) { + ns->cs_version = atoi (buf); + ns->sc_version = ns->cs_version; + if (VERSION_CS != ns->cs_version) + { #ifdef ESRV_DEBUG - LOG(llevDebug, "CS: csversion mismatch (%d,%d)\n", VERSION_CS,ns->cs_version); + LOG (llevDebug, "CS: csversion mismatch (%d,%d)\n", VERSION_CS, ns->cs_version); #endif } - cp = strchr(buf+1,' '); - if (!cp) return; - ns->sc_version = atoi(cp); - if (VERSION_SC != ns->sc_version) { + cp = strchr (buf + 1, ' '); + if (!cp) + return; + ns->sc_version = atoi (cp); + if (VERSION_SC != ns->sc_version) + { #ifdef ESRV_DEBUG - LOG(llevDebug, "CS: scversion mismatch (%d,%d)\n",VERSION_SC,ns->sc_version); + LOG (llevDebug, "CS: scversion mismatch (%d,%d)\n", VERSION_SC, ns->sc_version); #endif } - cp = strchr(cp+1, ' '); - if (cp) { - LOG(llevDebug,"CS: connection from client of type <%s>, ip %s\n", cp, ns->host); - - snprintf (ns->client, sizeof (ns->client), "%s", cp + 1); - - /* This is first implementation - i skip all beta DX clients with it - * Add later stuff here for other clients - */ - - /* these are old dxclients */ - /* Version 1024 added support for singular + plural name values - - * requiing this minimal value reduces complexity of that code, and it - * has been around for a long time. - */ - if(!strcmp(" CF DX CLIENT", cp) || ns->sc_version < 1024 ) + cp = strchr (cp + 1, ' '); + if (cp) + { + LOG (llevDebug, "CS: connection from client of type <%s>, ip %s\n", cp, ns->host); + + snprintf (ns->client, sizeof (ns->client), "%s", cp + 1); + + /* This is first implementation - i skip all beta DX clients with it + * Add later stuff here for other clients + */ + + /* these are old dxclients */ + /* Version 1024 added support for singular + plural name values - + * requiing this minimal value reduces complexity of that code, and it + * has been around for a long time. + */ + if (!strcmp (" CF DX CLIENT", cp) || ns->sc_version < 1024) { - sprintf(version_warning,"drawinfo %d %s", NDI_RED, "**** VERSION WARNING ****\n**** CLIENT IS TOO OLD!! UPDATE THE CLIENT!! ****"); - Write_String_To_Socket(ns, version_warning, strlen(version_warning)); + sprintf (version_warning, "drawinfo %d %s", NDI_RED, + "**** VERSION WARNING ****\n**** CLIENT IS TOO OLD!! UPDATE THE CLIENT!! ****"); + Write_String_To_Socket (ns, version_warning, strlen (version_warning)); } } } /** sound related functions. */ - -void SetSound(char *buf, int len, NewSocket *ns) + +void +SetSound (char *buf, int len, NewSocket * ns) { - ns->sound = atoi(buf); + ns->sound = atoi (buf); } /** client wants the map resent */ -void MapRedrawCmd(char *buf, int len, player *pl) +void +MapRedrawCmd (char *buf, int len, player *pl) { + /* This function is currently disabled; just clearing the map state results in * display errors. It should clear the cache and send a newmap command. * Unfortunately this solution does not work because some client versions send * a mapredraw command after receiving a newmap command. */ #if 0 - /* Okay, this is MAJOR UGLY. but the only way I know how to - * clear the "cache" - */ - memset(&pl->socket.lastmap, 0, sizeof(struct Map)); - draw_client_map(pl->ob); + /* Okay, this is MAJOR UGLY. but the only way I know how to + * clear the "cache" + */ + memset (&pl->socket.lastmap, 0, sizeof (struct Map)); + draw_client_map (pl->ob); #endif } @@ -891,27 +1010,30 @@ * Moves an object (typically, container to inventory). * syntax is: move (to) (tag) (nrof) */ -void MoveCmd(char *buf, int len,player *pl) +void +MoveCmd (char *buf, int len, player *pl) { - int vals[3], i; + int vals[3], i; - /* A little funky here. We only cycle for 2 records, because - * we obviously am not going to find a space after the third - * record. Perhaps we should just replace this with a - * sscanf? - */ - for (i=0; i<2; i++) { - vals[i]=atoi(buf); - if (!(buf = strchr(buf, ' '))) { - LOG(llevError,"Incomplete move command: %s\n", buf); - return; + /* A little funky here. We only cycle for 2 records, because + * we obviously am not going to find a space after the third + * record. Perhaps we should just replace this with a + * sscanf? + */ + for (i = 0; i < 2; i++) + { + vals[i] = atoi (buf); + if (!(buf = strchr (buf, ' '))) + { + LOG (llevError, "Incomplete move command: %s\n", buf); + return; } - buf++; + buf++; } - vals[2]=atoi(buf); + vals[2] = atoi (buf); /* LOG(llevDebug,"Move item %d (nrof=%d) to %d.\n", vals[1], vals[2], vals[0]);*/ - esrv_move_object(pl->ob,vals[0], vals[1], vals[2]); + esrv_move_object (pl->ob, vals[0], vals[1], vals[2]); } @@ -926,12 +1048,13 @@ * Asks the client to query the user. This way, the client knows * it needs to send something back (vs just printing out a message) */ -void send_query(NewSocket *ns, uint8 flags, char *text) +void +send_query (NewSocket * ns, uint8 flags, char *text) { - char buf[MAX_BUF]; + char buf[MAX_BUF]; - sprintf(buf,"query %d %s", flags, text?text:""); - Write_String_To_Socket(ns, buf, strlen(buf)); + sprintf (buf, "query %d %s", flags, text ? text : ""); + Write_String_To_Socket (ns, buf, strlen (buf)); } #define AddIfInt64(Old,New,Type) if (Old != New) {\ @@ -973,122 +1096,139 @@ * Since this gets sent a lot, this is actually one of the few binary * commands for now. */ -void esrv_update_stats(player *pl) +void +esrv_update_stats (player *pl) { - SockList sl; - char buf[MAX_BUF]; - uint16 flags; - - sl.buf=(unsigned char*)malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"stats "); - sl.len=strlen((char*)sl.buf); - - if(pl->ob != NULL) - { - AddIfShort(pl->last_stats.hp, pl->ob->stats.hp, CS_STAT_HP); - AddIfShort(pl->last_stats.maxhp, pl->ob->stats.maxhp, CS_STAT_MAXHP); - AddIfShort(pl->last_stats.sp, pl->ob->stats.sp, CS_STAT_SP); - AddIfShort(pl->last_stats.maxsp, pl->ob->stats.maxsp, CS_STAT_MAXSP); - AddIfShort(pl->last_stats.grace, pl->ob->stats.grace, CS_STAT_GRACE); - AddIfShort(pl->last_stats.maxgrace, pl->ob->stats.maxgrace, CS_STAT_MAXGRACE); - AddIfShort(pl->last_stats.Str, pl->ob->stats.Str, CS_STAT_STR); - AddIfShort(pl->last_stats.Int, pl->ob->stats.Int, CS_STAT_INT); - AddIfShort(pl->last_stats.Pow, pl->ob->stats.Pow, CS_STAT_POW); - AddIfShort(pl->last_stats.Wis, pl->ob->stats.Wis, CS_STAT_WIS); - AddIfShort(pl->last_stats.Dex, pl->ob->stats.Dex, CS_STAT_DEX); - AddIfShort(pl->last_stats.Con, pl->ob->stats.Con, CS_STAT_CON); - AddIfShort(pl->last_stats.Cha, pl->ob->stats.Cha, CS_STAT_CHA); - } - if(pl->socket.exp64) { - uint8 s; - for(s=0;slast_skill_ob[s] && - pl->last_skill_exp[s] != pl->last_skill_ob[s]->stats.exp) { - - /* Always send along the level if exp changes. This is only - * 1 extra byte, but keeps processing simpler. - */ - SockList_AddChar(&sl, ( char )( s + CS_STAT_SKILLINFO )); - SockList_AddChar(&sl, ( char )pl->last_skill_ob[s]->level); - SockList_AddInt64(&sl, pl->last_skill_ob[s]->stats.exp); - pl->last_skill_exp[s] = pl->last_skill_ob[s]->stats.exp; - } - } - } - if (pl->socket.exp64) { - AddIfInt64(pl->last_stats.exp, pl->ob->stats.exp, CS_STAT_EXP64); - } else { - AddIfInt(pl->last_stats.exp, ( int )pl->ob->stats.exp, CS_STAT_EXP); - } - AddIfShort(pl->last_level, ( char )pl->ob->level, CS_STAT_LEVEL); - AddIfShort(pl->last_stats.wc, pl->ob->stats.wc, CS_STAT_WC); - AddIfShort(pl->last_stats.ac, pl->ob->stats.ac, CS_STAT_AC); - AddIfShort(pl->last_stats.dam, pl->ob->stats.dam, CS_STAT_DAM); - AddIfFloat(pl->last_speed, pl->ob->speed, CS_STAT_SPEED); - AddIfShort(pl->last_stats.food, pl->ob->stats.food, CS_STAT_FOOD); - AddIfFloat(pl->last_weapon_sp, pl->weapon_sp, CS_STAT_WEAP_SP); - AddIfInt(pl->last_weight_limit, (sint32)weight_limit[pl->ob->stats.Str], CS_STAT_WEIGHT_LIM); - flags=0; - if (pl->fire_on) flags |=SF_FIREON; - if (pl->run_on) flags |= SF_RUNON; - - AddIfShort(pl->last_flags, flags, CS_STAT_FLAGS); - if (pl->socket.sc_version<1025) { - AddIfShort(pl->last_resist[ATNR_PHYSICAL], pl->ob->resist[ATNR_PHYSICAL], CS_STAT_ARMOUR); - } else { - int i; - - for (i=0; ilast_resist[i], pl->ob->resist[i], ( char )atnr_cs_stat[i]); - } - } - if (pl->socket.monitor_spells) { - AddIfInt(pl->last_path_attuned, pl->ob->path_attuned, CS_STAT_SPELL_ATTUNE); - AddIfInt(pl->last_path_repelled, pl->ob->path_repelled, CS_STAT_SPELL_REPEL); - AddIfInt(pl->last_path_denied, pl->ob->path_denied, CS_STAT_SPELL_DENY); - } - rangetostring(pl->ob, buf); /* we want use the new fire & run system in new client */ - AddIfString(pl->socket.stats.range, buf, CS_STAT_RANGE); - set_title(pl->ob, buf); - AddIfString(pl->socket.stats.title, buf, CS_STAT_TITLE); + SockList sl; + char buf[MAX_BUF]; + uint16 flags; + + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "stats "); + sl.len = strlen ((char *) sl.buf); - /* Only send it away if we have some actual data */ - if (sl.len>6) { + if (pl->ob != NULL) + { + AddIfShort (pl->last_stats.hp, pl->ob->stats.hp, CS_STAT_HP); + AddIfShort (pl->last_stats.maxhp, pl->ob->stats.maxhp, CS_STAT_MAXHP); + AddIfShort (pl->last_stats.sp, pl->ob->stats.sp, CS_STAT_SP); + AddIfShort (pl->last_stats.maxsp, pl->ob->stats.maxsp, CS_STAT_MAXSP); + AddIfShort (pl->last_stats.grace, pl->ob->stats.grace, CS_STAT_GRACE); + AddIfShort (pl->last_stats.maxgrace, pl->ob->stats.maxgrace, CS_STAT_MAXGRACE); + AddIfShort (pl->last_stats.Str, pl->ob->stats.Str, CS_STAT_STR); + AddIfShort (pl->last_stats.Int, pl->ob->stats.Int, CS_STAT_INT); + AddIfShort (pl->last_stats.Pow, pl->ob->stats.Pow, CS_STAT_POW); + AddIfShort (pl->last_stats.Wis, pl->ob->stats.Wis, CS_STAT_WIS); + AddIfShort (pl->last_stats.Dex, pl->ob->stats.Dex, CS_STAT_DEX); + AddIfShort (pl->last_stats.Con, pl->ob->stats.Con, CS_STAT_CON); + AddIfShort (pl->last_stats.Cha, pl->ob->stats.Cha, CS_STAT_CHA); + } + if (pl->socket.exp64) + { + uint8 s; + + for (s = 0; s < NUM_SKILLS; s++) + { + if (pl->last_skill_ob[s] && pl->last_skill_exp[s] != pl->last_skill_ob[s]->stats.exp) + { + + /* Always send along the level if exp changes. This is only + * 1 extra byte, but keeps processing simpler. + */ + SockList_AddChar (&sl, (char) (s + CS_STAT_SKILLINFO)); + SockList_AddChar (&sl, (char) pl->last_skill_ob[s]->level); + SockList_AddInt64 (&sl, pl->last_skill_ob[s]->stats.exp); + pl->last_skill_exp[s] = pl->last_skill_ob[s]->stats.exp; + } + } + } + if (pl->socket.exp64) + { + AddIfInt64 (pl->last_stats.exp, pl->ob->stats.exp, CS_STAT_EXP64); + } + else + { + AddIfInt (pl->last_stats.exp, (int) pl->ob->stats.exp, CS_STAT_EXP); + } + AddIfShort (pl->last_level, (char) pl->ob->level, CS_STAT_LEVEL); + AddIfShort (pl->last_stats.wc, pl->ob->stats.wc, CS_STAT_WC); + AddIfShort (pl->last_stats.ac, pl->ob->stats.ac, CS_STAT_AC); + AddIfShort (pl->last_stats.dam, pl->ob->stats.dam, CS_STAT_DAM); + AddIfFloat (pl->last_speed, pl->ob->speed, CS_STAT_SPEED); + AddIfShort (pl->last_stats.food, pl->ob->stats.food, CS_STAT_FOOD); + AddIfFloat (pl->last_weapon_sp, pl->weapon_sp, CS_STAT_WEAP_SP); + AddIfInt (pl->last_weight_limit, (sint32) weight_limit[pl->ob->stats.Str], CS_STAT_WEIGHT_LIM); + flags = 0; + if (pl->fire_on) + flags |= SF_FIREON; + if (pl->run_on) + flags |= SF_RUNON; + + AddIfShort (pl->last_flags, flags, CS_STAT_FLAGS); + if (pl->socket.sc_version < 1025) + { + AddIfShort (pl->last_resist[ATNR_PHYSICAL], pl->ob->resist[ATNR_PHYSICAL], CS_STAT_ARMOUR); + } + else + { + int i; + + for (i = 0; i < NROFATTACKS; i++) + { + /* Skip ones we won't send */ + if (atnr_cs_stat[i] == -1) + continue; + AddIfShort (pl->last_resist[i], pl->ob->resist[i], (char) atnr_cs_stat[i]); + } + } + if (pl->socket.monitor_spells) + { + AddIfInt (pl->last_path_attuned, pl->ob->path_attuned, CS_STAT_SPELL_ATTUNE); + AddIfInt (pl->last_path_repelled, pl->ob->path_repelled, CS_STAT_SPELL_REPEL); + AddIfInt (pl->last_path_denied, pl->ob->path_denied, CS_STAT_SPELL_DENY); + } + rangetostring (pl->ob, buf); /* we want use the new fire & run system in new client */ + AddIfString (pl->socket.stats.range, buf, CS_STAT_RANGE); + set_title (pl->ob, buf); + AddIfString (pl->socket.stats.title, buf, CS_STAT_TITLE); + + /* Only send it away if we have some actual data */ + if (sl.len > 6) + { #ifdef ESRV_DEBUG - LOG(llevDebug,"Sending stats command, %d bytes long.\n", sl.len); + LOG (llevDebug, "Sending stats command, %d bytes long.\n", sl.len); #endif - Send_With_Handling(&pl->socket, &sl); + Send_With_Handling (&pl->socket, &sl); } - free(sl.buf); + free (sl.buf); } /** * Tells the client that here is a player it should start using. */ -void esrv_new_player(player *pl, uint32 weight) +void +esrv_new_player (player *pl, uint32 weight) { - SockList sl; + SockList sl; + + pl->last_weight = weight; - pl->last_weight = weight; + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); - sl.buf=(unsigned char*)malloc(MAXSOCKBUF); + strcpy ((char *) sl.buf, "player "); + sl.len = strlen ((char *) sl.buf); + SockList_AddInt (&sl, pl->ob->count); + SockList_AddInt (&sl, weight); + SockList_AddInt (&sl, pl->ob->face->number); - strcpy((char*)sl.buf,"player "); - sl.len=strlen((char*)sl.buf); - SockList_AddInt(&sl, pl->ob->count); - SockList_AddInt(&sl, weight); - SockList_AddInt(&sl, pl->ob->face->number); - - SockList_AddChar(&sl, ( char )strlen(pl->ob->name)); - strcpy((char*)sl.buf+sl.len, pl->ob->name); - sl.len += strlen(pl->ob->name); - - Send_With_Handling(&pl->socket, &sl); - free(sl.buf); - SET_FLAG(pl->ob, FLAG_CLIENT_SENT); + SockList_AddChar (&sl, (char) strlen (pl->ob->name)); + strcpy ((char *) sl.buf + sl.len, pl->ob->name); + sl.len += strlen (pl->ob->name); + + Send_With_Handling (&pl->socket, &sl); + free (sl.buf); + SET_FLAG (pl->ob, FLAG_CLIENT_SENT); } @@ -1099,36 +1239,39 @@ * how much we are sending - on the other hand, this should only happen * when the player logs in and picks stuff up. */ -void esrv_send_animation(NewSocket *ns, short anim_num) +void +esrv_send_animation (NewSocket * ns, short anim_num) { - SockList sl; - int i; + SockList sl; + int i; - /* Do some checking on the anim_num we got. Note that the animations - * are added in contigous order, so if the number is in the valid - * range, it must be a valid animation. - */ - if (anim_num < 0 || anim_num > num_animations) { - LOG(llevError,"esrv_send_anim (%d) out of bounds??\n",anim_num); - return; - } - - sl.buf = (unsigned char*) malloc(MAXSOCKBUF); - strcpy((char*)sl.buf, "anim "); - sl.len=5; - SockList_AddShort(&sl, anim_num); - SockList_AddShort(&sl, 0); /* flags - not used right now */ - /* Build up the list of faces. Also, send any information (ie, the - * the face itself) down to the client. - */ - for (i=0; ifaces_sent[animations[anim_num].faces[i]] & NS_FACESENT_FACE)) - esrv_send_face(ns,animations[anim_num].faces[i],0); - SockList_AddShort(&sl, animations[anim_num].faces[i]); /* flags - not used right now */ - } - Send_With_Handling(ns, &sl); - free(sl.buf); - ns->anims_sent[anim_num] = 1; + /* Do some checking on the anim_num we got. Note that the animations + * are added in contigous order, so if the number is in the valid + * range, it must be a valid animation. + */ + if (anim_num < 0 || anim_num > num_animations) + { + LOG (llevError, "esrv_send_anim (%d) out of bounds??\n", anim_num); + return; + } + + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "anim "); + sl.len = 5; + SockList_AddShort (&sl, anim_num); + SockList_AddShort (&sl, 0); /* flags - not used right now */ + /* Build up the list of faces. Also, send any information (ie, the + * the face itself) down to the client. + */ + for (i = 0; i < animations[anim_num].num_animations; i++) + { + if (!(ns->faces_sent[animations[anim_num].faces[i]] & NS_FACESENT_FACE)) + esrv_send_face (ns, animations[anim_num].faces[i], 0); + SockList_AddShort (&sl, animations[anim_num].faces[i]); /* flags - not used right now */ + } + Send_With_Handling (ns, &sl); + free (sl.buf); + ns->anims_sent[anim_num] = 1; } @@ -1142,43 +1285,48 @@ * This adds face_num to a map cell at x,y. If the client doesn't have * the face yet, we will also send it. */ -static void esrv_map_setbelow(NewSocket *ns, int x,int y, - short face_num, struct Map *newmap) +static void +esrv_map_setbelow (NewSocket * ns, int x, int y, short face_num, struct Map *newmap) { - if(newmap->cells[x][y].count >= MAP_LAYERS) { - LOG(llevError,"Too many faces in map cell %d %d\n",x,y); - return; - abort(); + if (newmap->cells[x][y].count >= MAP_LAYERS) + { + LOG (llevError, "Too many faces in map cell %d %d\n", x, y); + return; + abort (); } - newmap->cells[x][y].faces[newmap->cells[x][y].count] = face_num; - newmap->cells[x][y].count ++; - if (!(ns->faces_sent[face_num] & NS_FACESENT_FACE)) - esrv_send_face(ns,face_num,0); + newmap->cells[x][y].faces[newmap->cells[x][y].count] = face_num; + newmap->cells[x][y].count++; + if (!(ns->faces_sent[face_num] & NS_FACESENT_FACE)) + esrv_send_face (ns, face_num, 0); } -struct LayerCell { +struct LayerCell +{ uint16 xy; short face; }; -struct MapLayer { +struct MapLayer +{ int count; struct LayerCell lcells[MAP_CLIENT_X * MAP_CLIENT_Y]; }; /** Checkes if map cells have changed */ -static int mapcellchanged(NewSocket *ns,int i,int j, struct Map *newmap) +static int +mapcellchanged (NewSocket * ns, int i, int j, struct Map *newmap) { int k; if (ns->lastmap.cells[i][j].count != newmap->cells[i][j].count) return 1; - for(k=0;kcells[i][j].count;k++) { - if (ns->lastmap.cells[i][j].faces[k] != - newmap->cells[i][j].faces[k]) { - return 1; + for (k = 0; k < newmap->cells[i][j].count; k++) + { + if (ns->lastmap.cells[i][j].faces[k] != newmap->cells[i][j].faces[k]) + { + return 1; + } } - } return 0; } @@ -1187,114 +1335,124 @@ * cnum is the client number, cur is the the buffer we put all of * this data into. we return the end of the data. layers is * how many layers of data we should back. - */ -static uint8 *compactlayer(NewSocket *ns, unsigned char *cur, int numlayers, - struct Map *newmap) -{ - int x,y,k; - int face; - unsigned char *fcur; - struct MapLayer layers[MAP_LAYERS]; - - for(k = 0;kmapx;x++) { - for(y=0;ymapy;y++) { - if (!mapcellchanged(ns,x,y,newmap)) - continue; - if (newmap->cells[x][y].count == 0) { - *cur = x*ns->mapy+y; /* mark empty space */ - cur++; - continue; - } - for(k=0;kcells[x][y].count;k++) { - layers[k].lcells[layers[k].count].xy = x*ns->mapy+y; - layers[k].lcells[layers[k].count].face = - newmap->cells[x][y].faces[k]; - layers[k].count++; + */ +static uint8 * +compactlayer (NewSocket * ns, unsigned char *cur, int numlayers, struct Map *newmap) +{ + int x, y, k; + int face; + unsigned char *fcur; + struct MapLayer layers[MAP_LAYERS]; + + for (k = 0; k < MAP_LAYERS; k++) + layers[k].count = 0; + fcur = cur; + for (x = 0; x < ns->mapx; x++) + { + for (y = 0; y < ns->mapy; y++) + { + if (!mapcellchanged (ns, x, y, newmap)) + continue; + if (newmap->cells[x][y].count == 0) + { + *cur = x * ns->mapy + y; /* mark empty space */ + cur++; + continue; + } + for (k = 0; k < newmap->cells[x][y].count; k++) + { + layers[k].lcells[layers[k].count].xy = x * ns->mapy + y; + layers[k].lcells[layers[k].count].face = newmap->cells[x][y].faces[k]; + layers[k].count++; } } } - /* If no data, return now. */ - if (fcur == cur && layers[0].count == 0) - return cur; - *cur = 255; /* mark end of explicitly cleared cells */ - cur++; - /* First pack by layers. */ - for(k=0;k> 8; - cur++; - *cur = layers[k].lcells[x].face & 0xFF; - cur++; - face = layers[k].lcells[x].face; - /* Now, we back the redundant data into 1 byte xy pairings */ - for(y=x;y> 8; + cur++; + *cur = layers[k].lcells[x].face & 0xFF; + cur++; + face = layers[k].lcells[x].face; + /* Now, we back the redundant data into 1 byte xy pairings */ + for (y = x; y < layers[k].count; y++) + { + if (layers[k].lcells[y].face == face) + { + *cur = (uint8) layers[k].lcells[y].xy; + cur++; + layers[k].lcells[y].face = -1; } } - *(cur-1) = *(cur-1) | 128; /* mark for end of xy's; 11*11 < 128 */ - /* forward over the now redundant data */ - while(x < layers[k].count && - layers[k].lcells[x].face == -1) - x++; + *(cur - 1) = *(cur - 1) | 128; /* mark for end of xy's; 11*11 < 128 */ + /* forward over the now redundant data */ + while (x < layers[k].count && layers[k].lcells[x].face == -1) + x++; } - *fcur = *fcur | 128; /* mark for end of faces at this layer */ + *fcur = *fcur | 128; /* mark for end of faces at this layer */ } - return cur; + return cur; } -static void esrv_map_doneredraw(NewSocket *ns, struct Map *newmap) +static void +esrv_map_doneredraw (NewSocket * ns, struct Map *newmap) { - static long frames,bytes,tbytes,tframes; - char *cur; - SockList sl; + static long frames, bytes, tbytes, tframes; + char *cur; + SockList sl; - sl.buf=(unsigned char*)malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"map "); - sl.len=strlen((char*)sl.buf); + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "map "); + sl.len = strlen ((char *) sl.buf); - cur = (char *) compactlayer(ns,(unsigned char*) sl.buf+sl.len,MAP_LAYERS,newmap); - sl.len=cur-(char*)sl.buf; + cur = (char *) compactlayer (ns, (unsigned char *) sl.buf + sl.len, MAP_LAYERS, newmap); + sl.len = cur - (char *) sl.buf; /* LOG(llevDebug, "Sending map command.\n");*/ - if (sl.len>( int )strlen("map ") || ns->sent_scroll) { - /* All of this is just accounting stuff */ - if (tframes>100) { - tframes = tbytes = 0; - } - tframes++; - frames++; - tbytes += sl.len; - bytes += sl.len; - memcpy(&ns->lastmap,newmap,sizeof(struct Map)); - Send_With_Handling(ns, &sl); - ns->sent_scroll = 0; + if (sl.len > (int) strlen ("map ") || ns->sent_scroll) + { + /* All of this is just accounting stuff */ + if (tframes > 100) + { + tframes = tbytes = 0; + } + tframes++; + frames++; + tbytes += sl.len; + bytes += sl.len; + memcpy (&ns->lastmap, newmap, sizeof (struct Map)); + Send_With_Handling (ns, &sl); + ns->sent_scroll = 0; } - free(sl.buf); + free (sl.buf); } /** Clears a map cell */ -static void map_clearcell(struct MapCell *cell, int face0, int face1, int face2, int count) +static void +map_clearcell (struct MapCell *cell, int face0, int face1, int face2, int count) { - cell->faces[0] = face0; - cell->faces[1] = face1; - cell->faces[2] = face2; - cell->count = count; - cell->stat_hp = 0; - cell->player = 0; + cell->faces[0] = face0; + cell->faces[1] = face1; + cell->faces[2] = face2; + cell->count = count; + cell->stat_hp = 0; + cell->player = 0; } #define MAX_HEAD_POS MAX(MAX_CLIENT_X, MAX_CLIENT_Y) @@ -1307,19 +1465,21 @@ * re-examined. */ -static object *heads[MAX_HEAD_POS * MAX_HEAD_POS * MAX_LAYERS]; +static object *heads[MAX_HEAD_POS * MAX_HEAD_POS * MAX_LAYERS]; /** * Returns true if any of the heads for this * space is set. Returns false if all are blank - this is used * for empty space checking. */ -static inline int have_head(int ax, int ay) { +static inline int +have_head (int ax, int ay) +{ - if (heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS] || - heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + 1] || - heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + 2]) return 1; - return 0; + if (heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS] || + heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + 1] || heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + 2]) + return 1; + return 0; } /** @@ -1329,25 +1489,27 @@ * if needed, and returning 1. If this no data needs to get * sent, it returns zero. */ -static int check_head (SockList &sl, NewSocket &ns, int ax, int ay, int layer) +static int +check_head (SockList & sl, NewSocket & ns, int ax, int ay, int layer) { - short face_num; + short face_num; - if (heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]) - face_num = heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]->face->number; - else - face_num = 0; + if (heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]) + face_num = heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]->face->number; + else + face_num = 0; - if (face_num != ns.lastmap.cells[ax][ay].faces[layer]) { - SockList_AddShort (&sl, face_num); - if (face_num && !(ns.faces_sent[face_num] & NS_FACESENT_FACE)) - esrv_send_face (&ns, face_num, 0); - heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer] = NULL; - ns.lastmap.cells[ax][ay].faces[layer] = face_num; - return 1; + if (face_num != ns.lastmap.cells[ax][ay].faces[layer]) + { + SockList_AddShort (&sl, face_num); + if (face_num && !(ns.faces_sent[face_num] & NS_FACESENT_FACE)) + esrv_send_face (&ns, face_num, 0); + heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer] = NULL; + ns.lastmap.cells[ax][ay].faces[layer] = face_num; + return 1; } - return 0; /* No change */ + return 0; /* No change */ } /** @@ -1370,184 +1532,209 @@ * actually match. */ -static int update_space(SockList *sl, NewSocket *ns, mapstruct *mp, int mx, int my, int sx, int sy, int layer) +static int +update_space (SockList * sl, NewSocket * ns, mapstruct *mp, int mx, int my, int sx, int sy, int layer) { - object *ob, *head; - uint16 face_num; - int bx, by,i; - - /* If there is a multipart object stored away, treat that as more important. - * If not, then do the normal processing. - */ - - head = heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer]; - - /* Check to see if this head is part of the set of objects - * we would normally send for this space. If so, then - * don't use the head value. We need to do the check - * here and not when setting up the heads[] value for two reasons - - * 1) the heads[] values will get used even if the space is not visible. - * 2) its possible the head is not on the same map as a part, and I'd - * rather not need to do the map translation overhead. - * 3) We need to do some extra checking to make sure that we will - * otherwise send the image as this layer, eg, either it matches - * the head value, or is not multipart. - */ - if (head && !head->more) { - for (i=0; ihead) ob=ob->head; - - if (ob == head) { - heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer] = NULL; - head = NULL; - break; - } - } - } - - ob = head; - if (!ob) ob = GET_MAP_FACE_OBJ(mp, mx, my, layer); - - /* If there is no object for this space, or if the face for the object - * is the blank face, set the face number to zero. - * else if we have the stored head object for this space, that takes - * precedence over the other object for this space. - * otherwise, we do special head processing - */ - if (!ob || ob->face == blank_face) face_num=0; - else if (head){ - /* if this is a head that had previously been stored */ - face_num = ob->face->number; - } else { - /* if the faces for the different parts of a multipart object - * are the same, we only want to send the bottom right most - * portion of the object. That info is in the tail_.. values - * of the head. Note that for the head itself, ob->head will - * be null, so we only do this block if we are working on - * a tail piece. - */ - - /* tail_x and tail_y will only be set in the head object. If - * this is the head object and these are set, we proceed - * with logic to only send bottom right. Similarly, if - * this is one of the more parts but the head has those values - * set, we want to do the processing. There can be cases where - * the head is not visible but one of its parts is, so we just - * can always expect that ob->arch->tail_x will be true for all - * object we may want to display. - */ - if ((ob->arch->tail_x || ob->arch->tail_y) || - (ob->head && (ob->head->arch->tail_x || ob->head->arch->tail_y))) { - - if (ob->head) head = ob->head; - else head = ob; - - /* Basically figure out where the offset is from where we are right - * now. the ob->arch->clone.{x,y} values hold the offset that this current - * piece is from the head, and the tail is where the tail is from the - * head. Note that bx and by will equal sx and sy if we are already working - * on the bottom right corner. If ob is the head, the clone values - * will be zero, so the right thing will still happen. - */ - bx = sx + head->arch->tail_x - ob->arch->clone.x; - by = sy + head->arch->tail_y - ob->arch->clone.y; - - /* I don't think this can ever happen, but better to check for it just - * in case. - */ - if (bx < sx || by < sy) { - LOG(llevError,"update_space: bx (%d) or by (%d) is less than sx (%d) or sy (%d)\n", - bx, by, sx, sy); - face_num = 0; - } - /* single part object, multipart object with non merged faces, - * of multipart object already at lower right. - */ - else if (bx == sx && by == sy) { - face_num = ob->face->number; - - /* if this face matches one stored away, clear that one away. - * this code relies on the fact that the map1 commands - * goes from 2 down to 0. - */ - for (i=0; iface->number == face_num) - heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + i] = NULL; - } - else { - /* If this head is stored away, clear it - otherwise, - * there can be cases where a object is on multiple layers - - * we only want to send it once. - */ - face_num = head->face->number; - for (i=0; iface->number == face_num) - heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i] = NULL; - - /* First, try to put the new head on the same layer. If that is used up, - * then find another layer. - */ - if (heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + layer] == NULL) { - heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + layer] = head; - } else for (i=0; imore) + { + for (i = 0; i < MAP_LAYERS; i++) + { + ob = GET_MAP_FACE_OBJ (mp, mx, my, i); + if (!ob) + continue; + + if (ob->head) + ob = ob->head; + + if (ob == head) + { + heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer] = NULL; + head = NULL; + break; + } + } + } + + ob = head; + if (!ob) + ob = GET_MAP_FACE_OBJ (mp, mx, my, layer); + + /* If there is no object for this space, or if the face for the object + * is the blank face, set the face number to zero. + * else if we have the stored head object for this space, that takes + * precedence over the other object for this space. + * otherwise, we do special head processing + */ + if (!ob || ob->face == blank_face) + face_num = 0; + else if (head) + { + /* if this is a head that had previously been stored */ + face_num = ob->face->number; + } + else + { + /* if the faces for the different parts of a multipart object + * are the same, we only want to send the bottom right most + * portion of the object. That info is in the tail_.. values + * of the head. Note that for the head itself, ob->head will + * be null, so we only do this block if we are working on + * a tail piece. + */ + + /* tail_x and tail_y will only be set in the head object. If + * this is the head object and these are set, we proceed + * with logic to only send bottom right. Similarly, if + * this is one of the more parts but the head has those values + * set, we want to do the processing. There can be cases where + * the head is not visible but one of its parts is, so we just + * can always expect that ob->arch->tail_x will be true for all + * object we may want to display. + */ + if ((ob->arch->tail_x || ob->arch->tail_y) || (ob->head && (ob->head->arch->tail_x || ob->head->arch->tail_y))) + { + + if (ob->head) + head = ob->head; + else + head = ob; + + /* Basically figure out where the offset is from where we are right + * now. the ob->arch->clone.{x,y} values hold the offset that this current + * piece is from the head, and the tail is where the tail is from the + * head. Note that bx and by will equal sx and sy if we are already working + * on the bottom right corner. If ob is the head, the clone values + * will be zero, so the right thing will still happen. + */ + bx = sx + head->arch->tail_x - ob->arch->clone.x; + by = sy + head->arch->tail_y - ob->arch->clone.y; + + /* I don't think this can ever happen, but better to check for it just + * in case. + */ + if (bx < sx || by < sy) + { + LOG (llevError, "update_space: bx (%d) or by (%d) is less than sx (%d) or sy (%d)\n", bx, by, sx, sy); + face_num = 0; + } + /* single part object, multipart object with non merged faces, + * of multipart object already at lower right. + */ + else if (bx == sx && by == sy) + { + face_num = ob->face->number; + + /* if this face matches one stored away, clear that one away. + * this code relies on the fact that the map1 commands + * goes from 2 down to 0. + */ + for (i = 0; i < MAP_LAYERS; i++) + if (heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + i] && + heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + i]->face->number == face_num) + heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + i] = NULL; + } + else + { + /* If this head is stored away, clear it - otherwise, + * there can be cases where a object is on multiple layers - + * we only want to send it once. + */ + face_num = head->face->number; + for (i = 0; i < MAP_LAYERS; i++) + if (heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i] && + heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i]->face->number == face_num) + heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i] = NULL; + + /* First, try to put the new head on the same layer. If that is used up, + * then find another layer. + */ + if (heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + layer] == NULL) + { + heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + layer] = head; } - face_num = 0; /* Don't send this object - we'll send the head later */ + else + for (i = 0; i < MAX_LAYERS; i++) + { + if (heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i] == NULL || + heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i] == head) + { + heads[(by * MAX_HEAD_POS + bx) * MAX_LAYERS + i] = head; + } + } + face_num = 0; /* Don't send this object - we'll send the head later */ } - } else { - /* In this case, we are already at the lower right or single part object, - * so nothing special - */ - face_num = ob->face->number; - - /* clear out any head entries that have the same face as this one */ - for (bx=0; bxface->number == face_num) - heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + bx] = NULL; - } - } /* else not already head object or blank face */ - - /* This is a real hack. Basically, if we have nothing to send for this layer, - * but there is a head on the next layer, send that instead. - * Without this, what happens is you can get the case where the player stands - * on the same space as the head. However, if you have overlapping big objects - * of the same type, what happens then is it doesn't think it needs to send - * This tends to make stacking also work/look better. - */ - if (!face_num && layer > 0 && heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer -1]) { - face_num = heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer -1]->face->number; - heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer -1] = NULL; - } - - /* Another hack - because of heads and whatnot, this face may match one - * we already sent for a lower layer. In that case, don't send - * this one. - */ - if (face_num && layer+1lastmap.cells[sx][sy].faces[layer+1] == face_num) { - face_num = 0; - } - - /* We've gotten what face we want to use for the object. Now see if - * if it has changed since we last sent it to the client. - */ - if (ns->lastmap.cells[sx][sy].faces[layer] != face_num) { - ns->lastmap.cells[sx][sy].faces[layer] = face_num; - if (!(ns->faces_sent[face_num] & NS_FACESENT_FACE)) - esrv_send_face(ns, face_num, 0); - SockList_AddShort(sl, face_num); - return 1; + } + else + { + /* In this case, we are already at the lower right or single part object, + * so nothing special + */ + face_num = ob->face->number; + + /* clear out any head entries that have the same face as this one */ + for (bx = 0; bx < layer; bx++) + if (heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + bx] && + heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + bx]->face->number == face_num) + heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + bx] = NULL; + } + } /* else not already head object or blank face */ + + /* This is a real hack. Basically, if we have nothing to send for this layer, + * but there is a head on the next layer, send that instead. + * Without this, what happens is you can get the case where the player stands + * on the same space as the head. However, if you have overlapping big objects + * of the same type, what happens then is it doesn't think it needs to send + * This tends to make stacking also work/look better. + */ + if (!face_num && layer > 0 && heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer - 1]) + { + face_num = heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer - 1]->face->number; + heads[(sy * MAX_HEAD_POS + sx) * MAX_LAYERS + layer - 1] = NULL; + } + + /* Another hack - because of heads and whatnot, this face may match one + * we already sent for a lower layer. In that case, don't send + * this one. + */ + if (face_num && layer + 1 < MAP_LAYERS && ns->lastmap.cells[sx][sy].faces[layer + 1] == face_num) + { + face_num = 0; + } + + /* We've gotten what face we want to use for the object. Now see if + * if it has changed since we last sent it to the client. + */ + if (ns->lastmap.cells[sx][sy].faces[layer] != face_num) + { + ns->lastmap.cells[sx][sy].faces[layer] = face_num; + if (!(ns->faces_sent[face_num] & NS_FACESENT_FACE)) + esrv_send_face (ns, face_num, 0); + SockList_AddShort (sl, face_num); + return 1; } - /* Nothing changed */ - return 0; + /* Nothing changed */ + return 0; } /** @@ -1569,37 +1756,41 @@ * take. */ -static inline int update_smooth(SockList *sl, NewSocket *ns, mapstruct *mp, int mx, int my, int sx, int sy, int layer) +static inline int +update_smooth (SockList * sl, NewSocket * ns, mapstruct *mp, int mx, int my, int sx, int sy, int layer) { - object *ob; - int smoothlevel; /* old face_num;*/ + object *ob; + int smoothlevel; /* old face_num; */ - ob = GET_MAP_FACE_OBJ(mp, mx, my, layer); + ob = GET_MAP_FACE_OBJ (mp, mx, my, layer); - /* If there is no object for this space, or if the face for the object - * is the blank face, set the smoothlevel to zero. - */ - if (!ob || ob->face == blank_face || MAP_NOSMOOTH(mp)) smoothlevel=0; - else { - smoothlevel = ob->smoothlevel; - if (smoothlevel && !(ns->faces_sent[ob->face->number] & NS_FACESENT_SMOOTH)) - SendSmooth(ns, ob->face->number); - } /* else not already head object or blank face */ - - /* We've gotten what face we want to use for the object. Now see if - * if it has changed since we last sent it to the client. - */ - if (smoothlevel>255) - smoothlevel=255; - else if (smoothlevel<0) - smoothlevel=0; - if (ns->lastmap.cells[sx][sy].smooth[layer] != smoothlevel) { - ns->lastmap.cells[sx][sy].smooth[layer] = smoothlevel; - SockList_AddChar(sl, (uint8) (smoothlevel&0xFF)); - return 1; + /* If there is no object for this space, or if the face for the object + * is the blank face, set the smoothlevel to zero. + */ + if (!ob || ob->face == blank_face || MAP_NOSMOOTH (mp)) + smoothlevel = 0; + else + { + smoothlevel = ob->smoothlevel; + if (smoothlevel && !(ns->faces_sent[ob->face->number] & NS_FACESENT_SMOOTH)) + SendSmooth (ns, ob->face->number); + } /* else not already head object or blank face */ + + /* We've gotten what face we want to use for the object. Now see if + * if it has changed since we last sent it to the client. + */ + if (smoothlevel > 255) + smoothlevel = 255; + else if (smoothlevel < 0) + smoothlevel = 0; + if (ns->lastmap.cells[sx][sy].smooth[layer] != smoothlevel) + { + ns->lastmap.cells[sx][sy].smooth[layer] = smoothlevel; + SockList_AddChar (sl, (uint8) (smoothlevel & 0xFF)); + return 1; } - /* Nothing changed */ - return 0; + /* Nothing changed */ + return 0; } /** @@ -1607,14 +1798,19 @@ * mapextended. There are CLIENTMAPX*CLIENTMAPY*LAYERS entries * available. */ -int getExtendedMapInfoSize(NewSocket* ns){ - int result=0; - if (ns->ext_mapinfos){ - if (ns->EMI_smooth) - result+=1; /*One byte for smoothlevel*/ +int +getExtendedMapInfoSize (NewSocket * ns) +{ + int result = 0; + + if (ns->ext_mapinfos) + { + if (ns->EMI_smooth) + result += 1; /*One byte for smoothlevel */ } - return result; + return result; } + /** * This function uses the new map1 protocol command to send the map * to the client. It is necessary because the old map command supports @@ -1637,623 +1833,711 @@ * we use faces[0] faces[1] faces[2] to hold what the three layers * look like. */ -void draw_client_map1(object *pl) +void +draw_client_map1 (object *pl) { - int x,y,ax, ay, d, startlen, max_x, max_y, oldlen; - sint16 nx, ny; - int estartlen, eoldlen; - SockList sl; - SockList esl; /*For extended Map info*/ - uint16 mask,emask; - uint8 eentrysize; - uint16 ewhatstart,ewhatflag; - uint8 extendedinfos; - mapstruct *m; - NewSocket &socket = pl->contr->socket; - - check_map_change (pl->contr); - - sl.buf=(unsigned char*)malloc(MAXSOCKBUF); - if (socket.mapmode == Map1Cmd) - strcpy((char*)sl.buf,"map1 "); - else - strcpy((char*)sl.buf,"map1a "); - sl.len=strlen((char*)sl.buf); - startlen = sl.len; - /*Extendedmapinfo structure initialisation*/ - if (socket.ext_mapinfos){ - esl.buf=(unsigned char*)malloc(MAXSOCKBUF); - strcpy((char*)esl.buf,"mapextended "); - esl.len=strlen((char*)esl.buf); - extendedinfos=EMI_NOREDRAW; - if (socket.EMI_smooth) - extendedinfos|=EMI_SMOOTH; - ewhatstart=esl.len; - ewhatflag=extendedinfos; /*The EMI_NOREDRAW bit - could need to be taken away*/ - SockList_AddChar(&esl, extendedinfos); - eentrysize=getExtendedMapInfoSize(&socket); - SockList_AddChar(&esl, eentrysize); - estartlen = esl.len; - } else { - /* suppress compiler warnings */ - ewhatstart = 0; - ewhatflag = 0; - estartlen = 0; - } - /* Init data to zero */ - memset(heads, 0, sizeof(object *) * MAX_HEAD_POS * MAX_HEAD_POS * MAX_LAYERS); - - /* x,y are the real map locations. ax, ay are viewport relative - * locations. - */ - ay=0; - - /* We could do this logic as conditionals in the if statement, - * but that started to get a bit messy to look at. - */ - max_x = pl->x+(socket.mapx+1)/2; - max_y = pl->y+(socket.mapy+1)/2; - if (socket.mapmode == Map1aCmd) { - max_x += MAX_HEAD_OFFSET; - max_y += MAX_HEAD_OFFSET; - } - - for(y=pl->y-socket.mapy/2; yx-socket.mapx/2;x= socket.mapx || ay >= socket.mapy) { - int i, got_one; + int x, y, ax, ay, d, startlen, max_x, max_y, oldlen; + sint16 nx, ny; + int estartlen, eoldlen; + SockList sl; + SockList esl; /*For extended Map info */ + uint16 mask, emask; + uint8 eentrysize; + uint16 ewhatstart, ewhatflag; + uint8 extendedinfos; + mapstruct *m; + + NewSocket & socket = pl->contr->socket; + + check_map_change (pl->contr); + + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + if (socket.mapmode == Map1Cmd) + strcpy ((char *) sl.buf, "map1 "); + else + strcpy ((char *) sl.buf, "map1a "); + sl.len = strlen ((char *) sl.buf); + startlen = sl.len; + /*Extendedmapinfo structure initialisation */ + if (socket.ext_mapinfos) + { + esl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) esl.buf, "mapextended "); + esl.len = strlen ((char *) esl.buf); + extendedinfos = EMI_NOREDRAW; + if (socket.EMI_smooth) + extendedinfos |= EMI_SMOOTH; + ewhatstart = esl.len; + ewhatflag = extendedinfos; /*The EMI_NOREDRAW bit + could need to be taken away */ + SockList_AddChar (&esl, extendedinfos); + eentrysize = getExtendedMapInfoSize (&socket); + SockList_AddChar (&esl, eentrysize); + estartlen = esl.len; + } + else + { + /* suppress compiler warnings */ + ewhatstart = 0; + ewhatflag = 0; + estartlen = 0; + } + /* Init data to zero */ + memset (heads, 0, sizeof (object *) * MAX_HEAD_POS * MAX_HEAD_POS * MAX_LAYERS); + + /* x,y are the real map locations. ax, ay are viewport relative + * locations. + */ + ay = 0; + + /* We could do this logic as conditionals in the if statement, + * but that started to get a bit messy to look at. + */ + max_x = pl->x + (socket.mapx + 1) / 2; + max_y = pl->y + (socket.mapy + 1) / 2; + if (socket.mapmode == Map1aCmd) + { + max_x += MAX_HEAD_OFFSET; + max_y += MAX_HEAD_OFFSET; + } - oldlen = sl.len; + for (y = pl->y - socket.mapy / 2; y < max_y; y++, ay++) + { + ax = 0; + for (x = pl->x - socket.mapx / 2; x < max_x; x++, ax++) + { - SockList_AddShort(&sl, mask); + emask = mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; - if (check_head (sl, socket, ax, ay, 2)) - mask |= 0x4; - if (check_head (sl, socket, ax, ay, 1)) - mask |= 0x2; - if (check_head (sl, socket, ax, ay, 0)) - mask |= 0x1; + /* If this space is out of the normal viewable area, we only check + * the heads value ax or ay will only be greater than what + * the client wants if using the map1a command - this is because + * if the map1a command is not used, max_x and max_y will be + * set to lower values. + */ + if (ax >= socket.mapx || ay >= socket.mapy) + { + int i, got_one; + + oldlen = sl.len; - /* If all we are doing is sending 0 (blank) faces, we don't - * actually need to send that - just the coordinates - * with no faces tells the client to blank out the - * space. - */ - got_one=0; - for (i=oldlen+2; icontr->blocked_los[ax][ay]; - - /* If the coordinates are not valid, or it is too dark to see, - * we tell the client as such - */ - nx=x; - ny=y; - m = get_map_from_coord(pl->map, &nx, &ny); - if (!m) { - /* space is out of map. Update space and clear values - * if this hasn't already been done. If the space is out - * of the map, it shouldn't have a head - */ - if (lastcell.count != -1) { - SockList_AddShort(&sl, mask); - map_clearcell(&lastcell,0,0,0,-1); + else + { /*either all faces blank, either no face at all */ + if (mask & 0xf) /*at least 1 face, we know it's blank, only send coordinates */ + sl.len = oldlen + 2; + else + sl.len = oldlen; } - } else if (d>3) { - int need_send=0, count; - /* This block deals with spaces that are not visible for whatever - * reason. Still may need to send the head for this space. - */ - - oldlen = sl.len; - - SockList_AddShort(&sl, mask); - if (lastcell.count != -1) need_send=1; - count = -1; - - if (socket.mapmode == Map1aCmd && have_head(ax, ay)) { - /* Now check to see if any heads need to be sent */ - - if (check_head (sl, socket, ax, ay, 2)) - mask |= 0x4; - if (check_head (sl, socket, ax, ay, 1)) - mask |= 0x2; - if (check_head (sl, socket, ax, ay, 0)) - mask |= 0x1; - - lastcell.count = count; - - } else { - struct MapCell *cell = &lastcell; - /* properly clear a previously sent big face */ - if(cell->faces[0] != 0 - || cell->faces[1] != 0 - || cell->faces[2] != 0) - need_send = 1; - map_clearcell(&lastcell, 0, 0, 0, count); + /*What concerns extendinfos, nothing to be done for now + * (perhaps effects layer later) + */ + continue; /* don't do processing below */ + } + + MapCell & lastcell = socket.lastmap.cells[ax][ay]; + + d = pl->contr->blocked_los[ax][ay]; + + /* If the coordinates are not valid, or it is too dark to see, + * we tell the client as such + */ + nx = x; + ny = y; + m = get_map_from_coord (pl->map, &nx, &ny); + if (!m) + { + /* space is out of map. Update space and clear values + * if this hasn't already been done. If the space is out + * of the map, it shouldn't have a head + */ + if (lastcell.count != -1) + { + SockList_AddShort (&sl, mask); + map_clearcell (&lastcell, 0, 0, 0, -1); } + } + else if (d > 3) + { + int need_send = 0, count; - if ((mask & 0xf) || need_send) { - sl.buf[oldlen+1] = mask & 0xff; - } else { - sl.len = oldlen; - } - } else { - /* In this block, the space is visible or there are head objects - * we need to send. - */ - - /* Rather than try to figure out what everything that we might - * need to send is, then form the packet after that, - * we presume that we will in fact form a packet, and update - * the bits by what we do actually send. If we send nothing, - * we just back out sl.len to the old value, and no harm - * is done. - * I think this is simpler than doing a bunch of checks to see - * what if anything we need to send, setting the bits, then - * doing those checks again to add the real data. - */ - oldlen = sl.len; - mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; - eoldlen = esl.len; - emask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; - SockList_AddShort(&sl, mask); - - if (socket.ext_mapinfos) - SockList_AddShort(&esl, emask); - - unsigned char dummy; - unsigned char *last_ext = &dummy; - - /* Darkness changed */ - if (lastcell.count != d && socket.darkness) { - mask |= 0x8; + /* This block deals with spaces that are not visible for whatever + * reason. Still may need to send the head for this space. + */ - if (socket.extmap) - { - *last_ext |= 0x80; last_ext = sl.buf + sl.len; SockList_AddChar (&sl, d); - } - else - SockList_AddChar (&sl, 255 - 64 * d); - } + oldlen = sl.len; - lastcell.count = d; + SockList_AddShort (&sl, mask); + if (lastcell.count != -1) + need_send = 1; + count = -1; - if (socket.extmap) - { - uint8 stat_hp = 0; - uint8 stat_width = 0; - tag_t player = 0; + if (socket.mapmode == Map1aCmd && have_head (ax, ay)) + { + /* Now check to see if any heads need to be sent */ - // send hp information, if applicable - if (object *op = GET_MAP_FACE_OBJ (m, nx, ny, 0)) - { - if (op->head || op->invisible) - ; // do not show - else if (op->type == PLAYER - || QUERY_FLAG (op, FLAG_MONSTER) - || QUERY_FLAG (op, FLAG_ALIVE) - || QUERY_FLAG (op, FLAG_GENERATOR)) - { - if (op->stats.maxhp > 0 - && (unsigned)op->stats.maxhp > (unsigned)op->stats.hp) - { - stat_hp = 255 - (op->stats.hp * 255 + 254) / op->stats.maxhp; - stat_width = op->arch->tail_x; - } - } + if (check_head (sl, socket, ax, ay, 2)) + mask |= 0x4; + if (check_head (sl, socket, ax, ay, 1)) + mask |= 0x2; + if (check_head (sl, socket, ax, ay, 0)) + mask |= 0x1; - if (op->type == PLAYER && op != pl) - player = op->count; - } + lastcell.count = count; - if (lastcell.stat_hp != stat_hp) - { - lastcell.stat_hp = stat_hp; + } + else + { + struct MapCell *cell = &lastcell; + + /* properly clear a previously sent big face */ + if (cell->faces[0] != 0 || cell->faces[1] != 0 || cell->faces[2] != 0) + need_send = 1; + map_clearcell (&lastcell, 0, 0, 0, count); + } - mask |= 0x8; - *last_ext |= 0x80; last_ext = sl.buf + sl.len; SockList_AddChar (&sl, 5); - SockList_AddChar (&sl, stat_hp); - - if (stat_width > 1) - { - *last_ext |= 0x80; last_ext = sl.buf + sl.len; SockList_AddChar (&sl, 6); - SockList_AddChar (&sl, stat_width); - } - } + if ((mask & 0xf) || need_send) + { + sl.buf[oldlen + 1] = mask & 0xff; + } + else + { + sl.len = oldlen; + } + } + else + { + /* In this block, the space is visible or there are head objects + * we need to send. + */ + + /* Rather than try to figure out what everything that we might + * need to send is, then form the packet after that, + * we presume that we will in fact form a packet, and update + * the bits by what we do actually send. If we send nothing, + * we just back out sl.len to the old value, and no harm + * is done. + * I think this is simpler than doing a bunch of checks to see + * what if anything we need to send, setting the bits, then + * doing those checks again to add the real data. + */ + oldlen = sl.len; + mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; + eoldlen = esl.len; + emask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; + SockList_AddShort (&sl, mask); + + if (socket.ext_mapinfos) + SockList_AddShort (&esl, emask); + + unsigned char dummy; + unsigned char *last_ext = &dummy; + + /* Darkness changed */ + if (lastcell.count != d && socket.darkness) + { + mask |= 0x8; + + if (socket.extmap) + { + *last_ext |= 0x80; + last_ext = sl.buf + sl.len; + SockList_AddChar (&sl, d); + } + else + SockList_AddChar (&sl, 255 - 64 * d); + } - if (lastcell.player != player) - { - lastcell.player = player; - mask |= 0x8; - *last_ext |= 0x80; last_ext = sl.buf + sl.len; SockList_AddChar (&sl, 0x47); - SockList_AddChar (&sl, 4); - SockList_AddInt (&sl, player); - } - } + lastcell.count = d; - /* Floor face */ - if (update_space(&sl, &socket, m, nx, ny, ax, ay, 2)) - mask |= 0x4; + if (socket.extmap) + { + uint8 stat_hp = 0; + uint8 stat_width = 0; + tag_t player = 0; + + // send hp information, if applicable + if (object *op = GET_MAP_FACE_OBJ (m, nx, ny, 0)) + { + if (op->head || op->invisible) + ; // do not show + else if (op->type == PLAYER + || QUERY_FLAG (op, FLAG_MONSTER) || QUERY_FLAG (op, FLAG_ALIVE) || QUERY_FLAG (op, FLAG_GENERATOR)) + { + if (op->stats.maxhp > 0 && (unsigned) op->stats.maxhp > (unsigned) op->stats.hp) + { + stat_hp = 255 - (op->stats.hp * 255 + 254) / op->stats.maxhp; + stat_width = op->arch->tail_x; + } + } - if (socket.EMI_smooth) - if (update_smooth(&esl, &socket, m, nx, ny, ax, ay, 2)) - emask |= 0x4; + if (op->type == PLAYER && op != pl) + player = op->count; + } - /* Middle face */ - if (update_space(&sl, &socket, m, nx, ny, ax, ay, 1)) - mask |= 0x2; + if (lastcell.stat_hp != stat_hp) + { + lastcell.stat_hp = stat_hp; + + mask |= 0x8; + *last_ext |= 0x80; + last_ext = sl.buf + sl.len; + SockList_AddChar (&sl, 5); + SockList_AddChar (&sl, stat_hp); + + if (stat_width > 1) + { + *last_ext |= 0x80; + last_ext = sl.buf + sl.len; + SockList_AddChar (&sl, 6); + SockList_AddChar (&sl, stat_width); + } + } - if (socket.EMI_smooth) - if (update_smooth(&esl, &socket, m, nx, ny, ax, ay, 1)) - emask |= 0x2; - - if(nx == pl->x && ny == pl->y && pl->invisible & (pl->invisible < 50 ? 4 : 1)) { - if (lastcell.faces[0] != pl->face->number) { - lastcell.faces[0] = pl->face->number; - mask |= 0x1; - if (!(socket.faces_sent[pl->face->number] &NS_FACESENT_FACE)) - esrv_send_face(&socket, pl->face->number, 0); - SockList_AddShort(&sl, pl->face->number); + if (lastcell.player !=player) + { + lastcell.player = player; + + mask |= 0x8; + *last_ext |= 0x80; + last_ext = sl.buf + sl.len; + SockList_AddChar (&sl, 0x47); + SockList_AddChar (&sl, 4); + SockList_AddInt (&sl, player); } } - /* Top face */ - else { - if (update_space(&sl, &socket, m, nx, ny, ax, ay, 0)) - mask |= 0x1; - if (socket.EMI_smooth) - if (update_smooth(&esl, &socket, m, nx, ny, ax, ay, 0)){ - emask |= 0x1; - } + + /* Floor face */ + if (update_space (&sl, &socket, m, nx, ny, ax, ay, 2)) + mask |= 0x4; + + if (socket.EMI_smooth) + if (update_smooth (&esl, &socket, m, nx, ny, ax, ay, 2)) + emask |= 0x4; + + /* Middle face */ + if (update_space (&sl, &socket, m, nx, ny, ax, ay, 1)) + mask |= 0x2; + + if (socket.EMI_smooth) + if (update_smooth (&esl, &socket, m, nx, ny, ax, ay, 1)) + emask |= 0x2; + + if (nx == pl->x && ny == pl->y && pl->invisible & (pl->invisible < 50 ? 4 : 1)) + { + if (lastcell.faces[0] != pl->face->number) + { + lastcell.faces[0] = pl->face->number; + mask |= 0x1; + if (!(socket.faces_sent[pl->face->number] & NS_FACESENT_FACE)) + esrv_send_face (&socket, pl->face->number, 0); + SockList_AddShort (&sl, pl->face->number); + } } - /* Check to see if we are in fact sending anything for this - * space by checking the mask. If so, update the mask. - * if not, reset the len to that from before adding the mask - * value, so we don't send those bits. - */ - if (mask & 0xf) { - sl.buf[oldlen+1] = mask & 0xff; - } else { - sl.len = oldlen; + /* Top face */ + else + { + if (update_space (&sl, &socket, m, nx, ny, ax, ay, 0)) + mask |= 0x1; + if (socket.EMI_smooth) + if (update_smooth (&esl, &socket, m, nx, ny, ax, ay, 0)) + { + emask |= 0x1; + } } - if (emask & 0xf) { - esl.buf[eoldlen+1] = emask & 0xff; - } else { - esl.len = eoldlen; + /* Check to see if we are in fact sending anything for this + * space by checking the mask. If so, update the mask. + * if not, reset the len to that from before adding the mask + * value, so we don't send those bits. + */ + if (mask & 0xf) + { + sl.buf[oldlen + 1] = mask & 0xff; } - } /* else this is a viewable space */ - } /* for x loop */ - } /* for y loop */ - - /* Verify that we in fact do need to send this */ - if (socket.ext_mapinfos){ - if (!(sl.len>startlen || socket.sent_scroll)){ - /* No map data will follow, so don't say the client - * it doesn't need draw! - */ - ewhatflag&=(~EMI_NOREDRAW); - esl.buf[ewhatstart+1] = ewhatflag & 0xff; - } - if (esl.len>estartlen) { - Send_With_Handling(&socket, &esl); - } - free(esl.buf); - } - if (sl.len>startlen || socket.sent_scroll) { - Send_With_Handling(&socket, &sl); - socket.sent_scroll = 0; + else + { + sl.len = oldlen; + } + if (emask & 0xf) + { + esl.buf[eoldlen + 1] = emask & 0xff; + } + else + { + esl.len = eoldlen; + } + } /* else this is a viewable space */ + } /* for x loop */ + } /* for y loop */ + + /* Verify that we in fact do need to send this */ + if (socket.ext_mapinfos) + { + if (!(sl.len > startlen || socket.sent_scroll)) + { + /* No map data will follow, so don't say the client + * it doesn't need draw! + */ + ewhatflag &= (~EMI_NOREDRAW); + esl.buf[ewhatstart + 1] = ewhatflag & 0xff; + } + if (esl.len > estartlen) + { + Send_With_Handling (&socket, &esl); + } + free (esl.buf); + } + if (sl.len > startlen || socket.sent_scroll) + { + Send_With_Handling (&socket, &sl); + socket.sent_scroll = 0; } - free(sl.buf); + free (sl.buf); } /** * Draws client map. */ -void draw_client_map(object *pl) +void +draw_client_map (object *pl) { - int i,j; - sint16 ax, ay, nx, ny;/* ax and ay goes from 0 to max-size of arrays */ - New_Face *face,*floor; - New_Face *floor2; - int d, mflags; - struct Map newmap; - mapstruct *m, *pm; - - if (pl->type != PLAYER) { - LOG(llevError,"draw_client_map called with non player/non eric-server\n"); - return; - } - - pm = pl->map; - - /* If player is just joining the game, he isn't here yet, so the map - * can get swapped out. If so, don't try to send them a map. All will - * be OK once they really log in. - */ - if (pm==NULL || pm->in_memory!=MAP_IN_MEMORY) return; - - memset(&newmap, 0, sizeof(struct Map)); - - for(j = (pl->y - pl->contr->socket.mapy/2) ; j < (pl->y + (pl->contr->socket.mapy+1)/2); j++) { - for(i = (pl->x - pl->contr->socket.mapx/2) ; i < (pl->x + (pl->contr->socket.mapx+1)/2); i++) { - ax=i; - ay=j; - m = pm; - mflags = get_map_flags(m, &m, ax, ay, &ax, &ay); - if (mflags & P_OUT_OF_MAP) - continue; - if (mflags & P_NEED_UPDATE) - update_position(m, ax, ay); - /* If a map is visible to the player, we don't want to swap it out - * just to reload it. This should really call something like - * swap_map, but this is much more efficient and 'good enough' - */ - if (mflags & P_NEW_MAP) - m->timeout = 50; - } - } - /* do LOS after calls to update_position */ - if(pl->contr->do_los) { - update_los(pl); - pl->contr->do_los = 0; - } - - if (pl->contr->socket.mapmode == Map1Cmd || pl->contr->socket.mapmode == Map1aCmd) { - /* Big maps need a different drawing mechanism to work */ - draw_client_map1(pl); - return; - } - - if(pl->invisible & (pl->invisible < 50 ? 4 : 1)) { - esrv_map_setbelow(&pl->contr->socket,pl->contr->socket.mapx/2, - pl->contr->socket.mapy/2,pl->face->number,&newmap); - } - - /* j and i are the y and x coordinates of the real map (which is - * basically some number of spaces around the player) - * ax and ay are values from within the viewport (ie, 0, 0 is upper - * left corner) and are thus disconnected from the map values. - * Subtract 1 from the max values so that we properly handle cases where - * player has specified an even map. Otherwise, we try to send them too - * much, ie, if mapx is 10, we would try to send from -5 to 5, which is actually - * 11 spaces. Now, we would send from -5 to 4, which is properly. If mapx is - * odd, this still works fine. - */ - ay=0; - for(j=pl->y-pl->contr->socket.mapy/2; j<=pl->y+(pl->contr->socket.mapy-1)/2;j++, ay++) { - ax=0; - for(i=pl->x-pl->contr->socket.mapx/2;i<=pl->x+(pl->contr->socket.mapx-1)/2;i++, ax++) { - - d = pl->contr->blocked_los[ax][ay]; - /* note the out_of_map and d>3 checks are both within the same - * negation check. - */ - nx = i; - ny = j; - m = get_map_from_coord(pm, &nx, &ny); - if (m && d<4) { - face = GET_MAP_FACE(m, nx, ny,0); - floor2 = GET_MAP_FACE(m, nx, ny,1); - floor = GET_MAP_FACE(m, nx, ny,2); - - /* If all is blank, send a blank face. */ - if ((!face || face == blank_face) && - (!floor2 || floor2 == blank_face) && - (!floor || floor == blank_face)) { - esrv_map_setbelow(&pl->contr->socket,ax,ay, - blank_face->number,&newmap); - } else { /* actually have something interesting */ + int i, j; + sint16 ax, ay, nx, ny; /* ax and ay goes from 0 to max-size of arrays */ + New_Face *face, *floor; + New_Face *floor2; + int d, mflags; + struct Map newmap; + mapstruct *m, *pm; + + if (pl->type != PLAYER) + { + LOG (llevError, "draw_client_map called with non player/non eric-server\n"); + return; + } + + pm = pl->map; + + /* If player is just joining the game, he isn't here yet, so the map + * can get swapped out. If so, don't try to send them a map. All will + * be OK once they really log in. + */ + if (pm == NULL || pm->in_memory != MAP_IN_MEMORY) + return; + + memset (&newmap, 0, sizeof (struct Map)); + + for (j = (pl->y - pl->contr->socket.mapy / 2); j < (pl->y + (pl->contr->socket.mapy + 1) / 2); j++) + { + for (i = (pl->x - pl->contr->socket.mapx / 2); i < (pl->x + (pl->contr->socket.mapx + 1) / 2); i++) + { + ax = i; + ay = j; + m = pm; + mflags = get_map_flags (m, &m, ax, ay, &ax, &ay); + if (mflags & P_OUT_OF_MAP) + continue; + if (mflags & P_NEED_UPDATE) + update_position (m, ax, ay); + /* If a map is visible to the player, we don't want to swap it out + * just to reload it. This should really call something like + * swap_map, but this is much more efficient and 'good enough' + */ + if (mflags & P_NEW_MAP) + m->timeout = 50; + } + } + /* do LOS after calls to update_position */ + if (pl->contr->do_los) + { + update_los (pl); + pl->contr->do_los = 0; + } + + if (pl->contr->socket.mapmode == Map1Cmd || pl->contr->socket.mapmode == Map1aCmd) + { + /* Big maps need a different drawing mechanism to work */ + draw_client_map1 (pl); + return; + } + + if (pl->invisible & (pl->invisible < 50 ? 4 : 1)) + { + esrv_map_setbelow (&pl->contr->socket, pl->contr->socket.mapx / 2, pl->contr->socket.mapy / 2, pl->face->number, &newmap); + } + + /* j and i are the y and x coordinates of the real map (which is + * basically some number of spaces around the player) + * ax and ay are values from within the viewport (ie, 0, 0 is upper + * left corner) and are thus disconnected from the map values. + * Subtract 1 from the max values so that we properly handle cases where + * player has specified an even map. Otherwise, we try to send them too + * much, ie, if mapx is 10, we would try to send from -5 to 5, which is actually + * 11 spaces. Now, we would send from -5 to 4, which is properly. If mapx is + * odd, this still works fine. + */ + ay = 0; + for (j = pl->y - pl->contr->socket.mapy / 2; j <= pl->y + (pl->contr->socket.mapy - 1) / 2; j++, ay++) + { + ax = 0; + for (i = pl->x - pl->contr->socket.mapx / 2; i <= pl->x + (pl->contr->socket.mapx - 1) / 2; i++, ax++) + { + + d = pl->contr->blocked_los[ax][ay]; + /* note the out_of_map and d>3 checks are both within the same + * negation check. + */ + nx = i; + ny = j; + m = get_map_from_coord (pm, &nx, &ny); + if (m && d < 4) + { + face = GET_MAP_FACE (m, nx, ny, 0); + floor2 = GET_MAP_FACE (m, nx, ny, 1); + floor = GET_MAP_FACE (m, nx, ny, 2); + + /* If all is blank, send a blank face. */ + if ((!face || face == blank_face) && (!floor2 || floor2 == blank_face) && (!floor || floor == blank_face)) + { + esrv_map_setbelow (&pl->contr->socket, ax, ay, blank_face->number, &newmap); + } + else + { /* actually have something interesting */ /* send the darkness mask, if any. */ - if (d && pl->contr->socket.darkness) - esrv_map_setbelow(&pl->contr->socket,ax,ay, - dark_faces[d-1]->number,&newmap); - - if (face && face != blank_face) - esrv_map_setbelow(&pl->contr->socket,ax,ay, - face->number,&newmap); - if (floor2 && floor2 != blank_face) - esrv_map_setbelow(&pl->contr->socket,ax,ay, - floor2->number,&newmap); - if (floor && floor != blank_face) - esrv_map_setbelow(&pl->contr->socket,ax,ay, - floor->number,&newmap); - } - } /* Is a valid space */ + if (d && pl->contr->socket.darkness) + esrv_map_setbelow (&pl->contr->socket, ax, ay, dark_faces[d - 1]->number, &newmap); + + if (face && face != blank_face) + esrv_map_setbelow (&pl->contr->socket, ax, ay, face->number, &newmap); + if (floor2 && floor2 != blank_face) + esrv_map_setbelow (&pl->contr->socket, ax, ay, floor2->number, &newmap); + if (floor && floor != blank_face) + esrv_map_setbelow (&pl->contr->socket, ax, ay, floor->number, &newmap); + } + } /* Is a valid space */ } } - esrv_map_doneredraw(&pl->contr->socket, &newmap); + esrv_map_doneredraw (&pl->contr->socket, &newmap); - check_map_change (pl->contr); + check_map_change (pl->contr); } /*****************************************************************************/ + /* GROS: The following one is used to allow a plugin to send a generic cmd to*/ + /* a player. Of course, the client need to know the command to be able to */ + /* manage it ! */ + /*****************************************************************************/ -void send_plugin_custom_message(object *pl, char *buf) +void +send_plugin_custom_message (object *pl, char *buf) { - cs_write_string(&pl->contr->socket,buf,strlen(buf)); + cs_write_string (&pl->contr->socket, buf, strlen (buf)); } /** * This sends the skill number to name mapping. We ignore * the params - we always send the same info no matter what. */ -void send_skill_info(NewSocket *ns, char *params) +void +send_skill_info (NewSocket * ns, char *params) { - SockList sl; - int i; + SockList sl; + int i; - sl.buf = (unsigned char*) malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"replyinfo skill_info\n"); - for (i=1; i< NUM_SKILLS; i++) { - sprintf((char*)sl.buf + strlen((char*)sl.buf), "%d:%s\n", i + CS_STAT_SKILLINFO, - &skill_names[i]); - } - sl.len = strlen((char*)sl.buf); - if (sl.len >= MAXSOCKBUF) { - LOG(llevError,"Buffer overflow in send_skill_info!\n"); - fatal(0); + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "replyinfo skill_info\n"); + for (i = 1; i < NUM_SKILLS; i++) + { + sprintf ((char *) sl.buf + strlen ((char *) sl.buf), "%d:%s\n", i + CS_STAT_SKILLINFO, &skill_names[i]); + } + sl.len = strlen ((char *) sl.buf); + if (sl.len >= MAXSOCKBUF) + { + LOG (llevError, "Buffer overflow in send_skill_info!\n"); + fatal (0); } - Send_With_Handling(ns, &sl); - free(sl.buf); + Send_With_Handling (ns, &sl); + free (sl.buf); } /** * This sends the spell path to name mapping. We ignore * the params - we always send the same info no matter what. */ -void send_spell_paths (NewSocket *ns, char *params) { - SockList sl; - int i; - - sl.buf = (unsigned char*) malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"replyinfo spell_paths\n"); - for(i=0; i= MAXSOCKBUF) { - LOG(llevError,"Buffer overflow in send_spell_paths!\n"); - fatal(0); +void +send_spell_paths (NewSocket * ns, char *params) +{ + SockList sl; + int i; + + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "replyinfo spell_paths\n"); + for (i = 0; i < NRSPELLPATHS; i++) + sprintf ((char *) sl.buf + strlen ((char *) sl.buf), "%d:%s\n", 1 << i, spellpathnames[i]); + sl.len = strlen ((char *) sl.buf); + if (sl.len >= MAXSOCKBUF) + { + LOG (llevError, "Buffer overflow in send_spell_paths!\n"); + fatal (0); } - Send_With_Handling(ns, &sl); - free(sl.buf); + Send_With_Handling (ns, &sl); + free (sl.buf); } /** * This looks for any spells the player may have that have changed their stats. * it then sends an updspell packet for each spell that has changed in this way */ -void esrv_update_spells(player *pl) { - SockList sl; - int flags=0; - object *spell; - if (!pl->socket.monitor_spells) return; - for (spell=pl->ob->inv; spell!=NULL; spell=spell->below) { - if (spell->type == SPELL) { - /* check if we need to update it*/ - if (spell->last_sp != SP_level_spellpoint_cost(pl->ob, spell, SPELL_MANA)) { - spell->last_sp = SP_level_spellpoint_cost(pl->ob, spell, SPELL_MANA); - flags |= UPD_SP_MANA; - } - if (spell->last_grace != SP_level_spellpoint_cost(pl->ob, spell, SPELL_GRACE)) { - spell->last_grace = SP_level_spellpoint_cost(pl->ob, spell, SPELL_GRACE); - flags |= UPD_SP_GRACE; - } - if (spell->last_eat != spell->stats.dam+SP_level_dam_adjust(pl->ob, spell)) { - spell->last_eat = spell->stats.dam+SP_level_dam_adjust(pl->ob, spell); - flags |= UPD_SP_DAMAGE; - } - if (flags !=0) { - sl.buf =(unsigned char*) malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"updspell "); - sl.len=strlen((char*)sl.buf); - SockList_AddChar(&sl, flags); - SockList_AddInt(&sl, spell->count); - if (flags & UPD_SP_MANA) SockList_AddShort(&sl, spell->last_sp); - if (flags & UPD_SP_GRACE) SockList_AddShort(&sl, spell->last_grace); - if (flags & UPD_SP_DAMAGE) SockList_AddShort(&sl, spell->last_eat); - flags = 0; - Send_With_Handling(&pl->socket, &sl); - free(sl.buf); +void +esrv_update_spells (player *pl) +{ + SockList sl; + int flags = 0; + object *spell; + + if (!pl->socket.monitor_spells) + return; + for (spell = pl->ob->inv; spell != NULL; spell = spell->below) + { + if (spell->type == SPELL) + { + /* check if we need to update it */ + if (spell->last_sp != SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA)) + { + spell->last_sp = SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA); + flags |= UPD_SP_MANA; + } + if (spell->last_grace != SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE)) + { + spell->last_grace = SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE); + flags |= UPD_SP_GRACE; + } + if (spell->last_eat != spell->stats.dam + SP_level_dam_adjust (pl->ob, spell)) + { + spell->last_eat = spell->stats.dam + SP_level_dam_adjust (pl->ob, spell); + flags |= UPD_SP_DAMAGE; + } + if (flags != 0) + { + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "updspell "); + sl.len = strlen ((char *) sl.buf); + SockList_AddChar (&sl, flags); + SockList_AddInt (&sl, spell->count); + if (flags & UPD_SP_MANA) + SockList_AddShort (&sl, spell->last_sp); + if (flags & UPD_SP_GRACE) + SockList_AddShort (&sl, spell->last_grace); + if (flags & UPD_SP_DAMAGE) + SockList_AddShort (&sl, spell->last_eat); + flags = 0; + Send_With_Handling (&pl->socket, &sl); + free (sl.buf); } } } } -void esrv_remove_spell(player *pl, object *spell) { - SockList sl; - - if (!pl->socket.monitor_spells) return; - if (!pl || !spell || spell->env != pl->ob) { - LOG(llevError, "Invalid call to esrv_remove_spell"); - return; - } - sl.buf = (unsigned char*) malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"delspell "); - sl.len=strlen((char*)sl.buf); - SockList_AddInt(&sl, spell->count); - Send_With_Handling(&pl->socket, &sl); - free(sl.buf); +void +esrv_remove_spell (player *pl, object *spell) +{ + SockList sl; + + if (!pl->socket.monitor_spells) + return; + if (!pl || !spell || spell->env != pl->ob) + { + LOG (llevError, "Invalid call to esrv_remove_spell"); + return; + } + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "delspell "); + sl.len = strlen ((char *) sl.buf); + SockList_AddInt (&sl, spell->count); + Send_With_Handling (&pl->socket, &sl); + free (sl.buf); } /* appends the spell *spell to the Socklist we will send the data to. */ -static void append_spell (player *pl, SockList *sl, object *spell) { - int len, i, skill=0; +static void +append_spell (player *pl, SockList * sl, object *spell) +{ + int len, i, skill = 0; - if (!(spell->name)) { - LOG(llevError, "item number %d is a spell with no name.\n", spell->count); - return; - } - SockList_AddInt(sl, spell->count); - SockList_AddShort(sl, spell->level); - SockList_AddShort(sl, spell->casting_time); - /* store costs and damage in the object struct, to compare to later */ - spell->last_sp = SP_level_spellpoint_cost(pl->ob, spell, SPELL_MANA); - spell->last_grace = SP_level_spellpoint_cost(pl->ob, spell, SPELL_GRACE); - spell->last_eat = spell->stats.dam+SP_level_dam_adjust(pl->ob, spell); - /* send the current values */ - SockList_AddShort(sl, spell->last_sp); - SockList_AddShort(sl, spell->last_grace); - SockList_AddShort(sl, spell->last_eat); - - /* figure out which skill it uses, if it uses one */ - if (spell->skill) { - for (i=1; i< NUM_SKILLS; i++) - if (!strcmp(spell->skill, skill_names[i])) { - skill = i+CS_STAT_SKILLINFO; - break; - } + if (!(spell->name)) + { + LOG (llevError, "item number %d is a spell with no name.\n", spell->count); + return; + } + SockList_AddInt (sl, spell->count); + SockList_AddShort (sl, spell->level); + SockList_AddShort (sl, spell->casting_time); + /* store costs and damage in the object struct, to compare to later */ + spell->last_sp = SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA); + spell->last_grace = SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE); + spell->last_eat = spell->stats.dam + SP_level_dam_adjust (pl->ob, spell); + /* send the current values */ + SockList_AddShort (sl, spell->last_sp); + SockList_AddShort (sl, spell->last_grace); + SockList_AddShort (sl, spell->last_eat); + + /* figure out which skill it uses, if it uses one */ + if (spell->skill) + { + for (i = 1; i < NUM_SKILLS; i++) + if (!strcmp (spell->skill, skill_names[i])) + { + skill = i + CS_STAT_SKILLINFO; + break; + } } - SockList_AddChar(sl, skill); + SockList_AddChar (sl, skill); - SockList_AddInt(sl, spell->path_attuned); - SockList_AddInt(sl, (spell->face)?spell->face->number:0); + SockList_AddInt (sl, spell->path_attuned); + SockList_AddInt (sl, (spell->face) ? spell->face->number : 0); - len = strlen(spell->name); - SockList_AddChar(sl, (char)len); - memcpy(sl->buf+sl->len, spell->name, len); - sl->len+=len; - - if (!spell->msg) { - SockList_AddShort(sl, 0); - } - else { - len = strlen(spell->msg); - SockList_AddShort(sl, len); - memcpy(sl->buf+sl->len, spell->msg, len); - sl->len+=len; + len = strlen (spell->name); + SockList_AddChar (sl, (char) len); + memcpy (sl->buf + sl->len, spell->name, len); + sl->len += len; + + if (!spell->msg) + { + SockList_AddShort (sl, 0); + } + else + { + len = strlen (spell->msg); + SockList_AddShort (sl, len); + memcpy (sl->buf + sl->len, spell->msg, len); + sl->len += len; } } @@ -2261,52 +2545,62 @@ * This tells the client to add the spell *ob, if *ob is NULL, then add * all spells in the player's inventory. */ -void esrv_add_spells(player *pl, object *spell) { - SockList sl; - if (!pl) { - LOG(llevError, "esrv_add_spells, tried to add a spell to a NULL player"); - return; - } - if (!pl->socket.monitor_spells) return; - sl.buf = (unsigned char*) malloc(MAXSOCKBUF); - strcpy((char*)sl.buf,"addspell "); - sl.len=strlen((char*)sl.buf); - if (!spell) { - for (spell=pl->ob->inv; spell!=NULL; spell=spell->below) { - /* were we to simply keep appending data here, we could exceed - * MAXSOCKBUF if the player has enough spells to add, we know that - * append_spells will always append 19 data bytes, plus 4 length - * bytes and 3 strings (because that is the spec) so we need to - * check that the length of those 3 strings, plus the 23 bytes, - * won't take us over the length limit for the socket, if it does, - * we need to send what we already have, and restart packet formation - */ - /* Seeing crashes by overflowed buffers. Quick arithemetic seems - * to show add_spell is 26 bytes + 2 strings. However, the overun - * is hundreds of bytes off, so correcting 22 vs 26 doesn't seem - * like it will fix this - */ - if (spell->type != SPELL) continue; - if (sl.len >= (MAXSOCKBUF - (26 + strlen(spell->name) + - (spell->msg?strlen(spell->msg):0)))) { - Send_With_Handling(&pl->socket, &sl); - strcpy((char*)sl.buf,"addspell "); - sl.len=strlen((char*)sl.buf); - } - append_spell(pl, &sl, spell); - } - } - else if (spell->type != SPELL) { - LOG(llevError, "Asked to send a non-spell object as a spell"); - return; - } - else append_spell(pl, &sl, spell); - if (sl.len >= MAXSOCKBUF) { - LOG(llevError,"Buffer overflow in esrv_add_spells!\n"); - fatal(0); - } - /* finally, we can send the packet */ - Send_With_Handling(&pl->socket, &sl); - free(sl.buf); -} +void +esrv_add_spells (player *pl, object *spell) +{ + SockList sl; + if (!pl) + { + LOG (llevError, "esrv_add_spells, tried to add a spell to a NULL player"); + return; + } + if (!pl->socket.monitor_spells) + return; + sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + strcpy ((char *) sl.buf, "addspell "); + sl.len = strlen ((char *) sl.buf); + if (!spell) + { + for (spell = pl->ob->inv; spell != NULL; spell = spell->below) + { + /* were we to simply keep appending data here, we could exceed + * MAXSOCKBUF if the player has enough spells to add, we know that + * append_spells will always append 19 data bytes, plus 4 length + * bytes and 3 strings (because that is the spec) so we need to + * check that the length of those 3 strings, plus the 23 bytes, + * won't take us over the length limit for the socket, if it does, + * we need to send what we already have, and restart packet formation + */ + /* Seeing crashes by overflowed buffers. Quick arithemetic seems + * to show add_spell is 26 bytes + 2 strings. However, the overun + * is hundreds of bytes off, so correcting 22 vs 26 doesn't seem + * like it will fix this + */ + if (spell->type != SPELL) + continue; + if (sl.len >= (MAXSOCKBUF - (26 + strlen (spell->name) + (spell->msg ? strlen (spell->msg) : 0)))) + { + Send_With_Handling (&pl->socket, &sl); + strcpy ((char *) sl.buf, "addspell "); + sl.len = strlen ((char *) sl.buf); + } + append_spell (pl, &sl, spell); + } + } + else if (spell->type != SPELL) + { + LOG (llevError, "Asked to send a non-spell object as a spell"); + return; + } + else + append_spell (pl, &sl, spell); + if (sl.len >= MAXSOCKBUF) + { + LOG (llevError, "Buffer overflow in esrv_add_spells!\n"); + fatal (0); + } + /* finally, we can send the packet */ + Send_With_Handling (&pl->socket, &sl); + free (sl.buf); +}