1 | /* |
1 | /* |
2 | * static char *rcsid_init_c = |
2 | * static char *rcsid_init_c = |
3 | * "$Id: request.C,v 1.1 2006/08/13 17:16:06 elmex Exp $"; |
3 | * "$Id: request.C,v 1.3 2006/08/18 02:06:58 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
104 | -1, /* Internal */ |
104 | -1, /* Internal */ |
105 | -1, /* life stealing */ |
105 | -1, /* life stealing */ |
106 | -1 /* Disease - not fully done yet */ |
106 | -1 /* Disease - not fully done yet */ |
107 | }; |
107 | }; |
108 | |
108 | |
|
|
109 | static void |
|
|
110 | socket_map_scroll (NewSocket *ns, int dx, int dy) |
|
|
111 | { |
|
|
112 | struct Map newmap; |
|
|
113 | int x,y, mx, my; |
|
|
114 | |
|
|
115 | { |
|
|
116 | char buf[MAXSOCKBUF]; |
|
|
117 | |
|
|
118 | sprintf(buf,"map_scroll %d %d", dx, dy); |
|
|
119 | Write_String_To_Socket(ns, buf, strlen (buf)); |
|
|
120 | } |
|
|
121 | |
|
|
122 | /* If we are using the Map1aCmd, we may in fact send |
|
|
123 | * head information that is outside the viewable map. |
|
|
124 | * So set the mx,my to the max value we want to |
|
|
125 | * look for. Removed code to do so - it caused extra |
|
|
126 | * complexities for the client, and probably doesn't make |
|
|
127 | * that much difference in bandwidth. |
|
|
128 | */ |
|
|
129 | mx = ns->mapx; |
|
|
130 | my = ns->mapy; |
|
|
131 | |
|
|
132 | if (ns->mapmode == Map1aCmd) { |
|
|
133 | mx += MAX_HEAD_OFFSET; |
|
|
134 | my += MAX_HEAD_OFFSET; |
|
|
135 | } |
|
|
136 | |
|
|
137 | /* the x and y here are coordinates for the new map, i.e. if we moved |
|
|
138 | * (dx,dy), newmap[x][y] = oldmap[x-dx][y-dy]. For this reason, |
|
|
139 | * if the destination x or y coordinate is outside the viewable |
|
|
140 | * area, we clear the values - otherwise, the old values |
|
|
141 | * are preserved, and the check_head thinks it needs to clear them. |
|
|
142 | */ |
|
|
143 | for(x=0; x<mx; x++) { |
|
|
144 | for(y=0; y<my; y++) { |
|
|
145 | if(x >= ns->mapx || y >= ns->mapy) { |
|
|
146 | /* clear cells outside the viewable area */ |
|
|
147 | memset(&newmap.cells[x][y], 0, sizeof(struct MapCell)); |
|
|
148 | } |
|
|
149 | else if ((x+dx) < 0 || (x+dx) >= ns->mapx || (y+dy) < 0 || (y + dy) >= ns->mapy) { |
|
|
150 | /* clear newly visible tiles within the viewable area */ |
|
|
151 | memset(&(newmap.cells[x][y]), 0, sizeof(struct MapCell)); |
|
|
152 | } |
|
|
153 | else { |
|
|
154 | memcpy(&(newmap.cells[x][y]), |
|
|
155 | &(ns->lastmap.cells[x+dx][y+dy]),sizeof(struct MapCell)); |
|
|
156 | } |
|
|
157 | } |
|
|
158 | } |
|
|
159 | |
|
|
160 | memcpy(&(ns->lastmap), &newmap,sizeof(struct Map)); |
|
|
161 | |
|
|
162 | /* Make sure that the next "map1" command will be sent (even if it is |
|
|
163 | * empty). |
|
|
164 | */ |
|
|
165 | ns->sent_scroll = 1; |
|
|
166 | } |
|
|
167 | |
109 | /** check for map change and send new map data */ |
168 | /** check for map change and send new map data */ |
110 | static void |
169 | static void |
111 | check_map_change (player *pl) |
170 | check_map_change (player *pl) |
112 | { |
171 | { |
|
|
172 | NewSocket &socket = pl->socket; |
|
|
173 | object *ob = pl->ob; |
113 | char buf[MAX_BUF]; /* eauugggh */ |
174 | char buf[MAX_BUF]; /* eauugggh */ |
114 | |
175 | |
115 | object *ob = pl->ob; |
|
|
116 | |
|
|
117 | if (!pl->socket.mapinfocmd) |
|
|
118 | return; |
|
|
119 | |
|
|
120 | if (pl->socket.current_map != ob->map) |
176 | if (socket.current_map != ob->map) |
121 | { |
177 | { |
122 | pl->socket.current_map = ob->map; |
178 | socket.current_map = ob->map; |
|
|
179 | memset (&socket.lastmap, 0, sizeof(socket.lastmap)); |
123 | |
180 | |
124 | if (ob->map && ob->map->path [0]) |
181 | if (socket.newmapcmd == 1) |
|
|
182 | Write_String_To_Socket (&socket, "newmap", 6); |
|
|
183 | |
|
|
184 | socket.update_look = 1; |
|
|
185 | socket.look_position =0; |
|
|
186 | |
|
|
187 | if (socket.mapinfocmd) |
125 | { |
188 | { |
|
|
189 | if (ob->map && ob->map->path [0]) |
|
|
190 | { |
126 | int flags = 0; |
191 | int flags = 0; |
127 | |
192 | |
128 | if (ob->map->tile_path [0]) flags |= 1; |
193 | if (ob->map->tile_path [0]) flags |= 1; |
129 | if (ob->map->tile_path [1]) flags |= 2; |
194 | if (ob->map->tile_path [1]) flags |= 2; |
130 | if (ob->map->tile_path [2]) flags |= 4; |
195 | if (ob->map->tile_path [2]) flags |= 4; |
131 | if (ob->map->tile_path [3]) flags |= 8; |
196 | if (ob->map->tile_path [3]) flags |= 8; |
132 | |
197 | |
133 | snprintf (buf, MAX_BUF, "mapinfo - spatial %d %d %d %d %d %s", |
198 | snprintf (buf, MAX_BUF, "mapinfo - spatial %d %d %d %d %d %s", |
134 | flags, pl->socket.mapx / 2 - ob->x, pl->socket.mapy / 2 - ob->y, |
199 | flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y, |
135 | ob->map->width, ob->map->height, ob->map->path); |
200 | ob->map->width, ob->map->height, ob->map->path); |
136 | } |
201 | } |
137 | else |
202 | else |
138 | snprintf (buf, MAX_BUF, "mapinfo current"); |
203 | snprintf (buf, MAX_BUF, "mapinfo current"); |
139 | |
204 | |
140 | Write_String_To_Socket (&pl->socket, buf, strlen (buf)); |
205 | Write_String_To_Socket (&socket, buf, strlen (buf)); |
|
|
206 | } |
|
|
207 | } |
|
|
208 | else if (socket.current_x != ob->x || socket.current_y != ob->y) |
141 | } |
209 | { |
|
|
210 | socket_map_scroll (&socket, ob->x - socket.current_x, ob->y - socket.current_y); |
|
|
211 | socket.update_look = 1; |
|
|
212 | socket.look_position = 0; |
|
|
213 | } |
|
|
214 | |
|
|
215 | socket.current_x = ob->x; |
|
|
216 | socket.current_y = ob->y; |
142 | } |
217 | } |
143 | |
218 | |
144 | void ExtCmd (char *buf, int len, player *pl) |
219 | void ExtCmd (char *buf, int len, player *pl) |
145 | { |
220 | { |
146 | execute_global_event (EVENT_EXTCMD, pl, buf, len); |
221 | execute_global_event (EVENT_EXTCMD, pl, buf, len); |
… | |
… | |
293 | ns->mapinfocmd = atoi(param); |
368 | ns->mapinfocmd = atoi(param); |
294 | safe_strcat(cmdback, "1", &slen, HUGE_BUF); |
369 | safe_strcat(cmdback, "1", &slen, HUGE_BUF); |
295 | } else if (!strcmp(cmd,"extcmd")) { |
370 | } else if (!strcmp(cmd,"extcmd")) { |
296 | ns->extcmd = atoi(param); |
371 | ns->extcmd = atoi(param); |
297 | safe_strcat(cmdback, "1", &slen, HUGE_BUF); |
372 | safe_strcat(cmdback, "1", &slen, HUGE_BUF); |
|
|
373 | } else if (!strcmp(cmd,"extmap")) { |
|
|
374 | ns->extmap = atoi(param); |
|
|
375 | safe_strcat(cmdback, "1", &slen, HUGE_BUF); |
298 | } else if (!strcmp(cmd,"facecache")) { |
376 | } else if (!strcmp(cmd,"facecache")) { |
299 | ns->facecache = atoi(param); |
377 | ns->facecache = atoi(param); |
300 | safe_strcat(cmdback, param, &slen, HUGE_BUF); |
378 | safe_strcat(cmdback, param, &slen, HUGE_BUF); |
301 | } else if (!strcmp(cmd,"faceset")) { |
379 | } else if (!strcmp(cmd,"faceset")) { |
302 | char tmpbuf[20]; |
380 | char tmpbuf[20]; |
… | |
… | |
788 | memset(&pl->socket.lastmap, 0, sizeof(struct Map)); |
866 | memset(&pl->socket.lastmap, 0, sizeof(struct Map)); |
789 | draw_client_map(pl->ob); |
867 | draw_client_map(pl->ob); |
790 | #endif |
868 | #endif |
791 | } |
869 | } |
792 | |
870 | |
793 | /** Newmap command */ |
|
|
794 | void MapNewmapCmd( player *pl) |
|
|
795 | { |
|
|
796 | if( pl->socket.newmapcmd == 1) { |
|
|
797 | memset(&pl->socket.lastmap, 0, sizeof(pl->socket.lastmap)); |
|
|
798 | Write_String_To_Socket( &pl->socket, "newmap", 6); |
|
|
799 | } |
|
|
800 | pl->socket.current_map = 0; |
|
|
801 | } |
|
|
802 | |
|
|
803 | |
|
|
804 | |
|
|
805 | /** |
871 | /** |
806 | * Moves an object (typically, container to inventory). |
872 | * Moves an object (typically, container to inventory). |
807 | * syntax is: move (to) (tag) (nrof) |
873 | * syntax is: move (to) (tag) (nrof) |
808 | */ |
874 | */ |
809 | void MoveCmd(char *buf, int len,player *pl) |
875 | void MoveCmd(char *buf, int len,player *pl) |
… | |
… | |
1202 | |
1268 | |
1203 | |
1269 | |
1204 | /** Clears a map cell */ |
1270 | /** Clears a map cell */ |
1205 | static void map_clearcell(struct MapCell *cell, int face0, int face1, int face2, int count) |
1271 | static void map_clearcell(struct MapCell *cell, int face0, int face1, int face2, int count) |
1206 | { |
1272 | { |
1207 | cell->count=count; |
|
|
1208 | cell->faces[0] = face0; |
1273 | cell->faces[0] = face0; |
1209 | cell->faces[1] = face1; |
1274 | cell->faces[1] = face1; |
1210 | cell->faces[2] = face2; |
1275 | cell->faces[2] = face2; |
|
|
1276 | cell->count = count; |
|
|
1277 | cell->stat_hp = 255; |
1211 | } |
1278 | } |
1212 | |
1279 | |
1213 | #define MAX_HEAD_POS MAX(MAX_CLIENT_X, MAX_CLIENT_Y) |
1280 | #define MAX_HEAD_POS MAX(MAX_CLIENT_X, MAX_CLIENT_Y) |
1214 | #define MAX_LAYERS 3 |
1281 | #define MAX_LAYERS 3 |
1215 | |
1282 | |
… | |
… | |
1240 | * basically, it only checks the that the head on space ax,ay at layer |
1307 | * basically, it only checks the that the head on space ax,ay at layer |
1241 | * needs to get sent - if so, it adds the data, sending the head |
1308 | * needs to get sent - if so, it adds the data, sending the head |
1242 | * if needed, and returning 1. If this no data needs to get |
1309 | * if needed, and returning 1. If this no data needs to get |
1243 | * sent, it returns zero. |
1310 | * sent, it returns zero. |
1244 | */ |
1311 | */ |
1245 | static inline int check_head(SockList *sl, NewSocket *ns, int ax, int ay, int layer) |
1312 | static int check_head (SockList &sl, NewSocket &ns, int ax, int ay, int layer) |
1246 | { |
1313 | { |
1247 | short face_num; |
1314 | short face_num; |
1248 | |
1315 | |
1249 | if (heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]) |
1316 | if (heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]) |
1250 | face_num = heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]->face->number; |
1317 | face_num = heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer]->face->number; |
1251 | else |
1318 | else |
1252 | face_num = 0; |
1319 | face_num = 0; |
1253 | |
1320 | |
1254 | if (face_num != ns->lastmap.cells[ax][ay].faces[layer]) { |
1321 | if (face_num != ns.lastmap.cells[ax][ay].faces[layer]) { |
1255 | SockList_AddShort(sl, face_num); |
1322 | SockList_AddShort (&sl, face_num); |
1256 | if (face_num && !(ns->faces_sent[face_num] & NS_FACESENT_FACE)) |
1323 | if (face_num && !(ns.faces_sent[face_num] & NS_FACESENT_FACE)) |
1257 | esrv_send_face(ns, face_num, 0); |
1324 | esrv_send_face (&ns, face_num, 0); |
1258 | heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer] = NULL; |
1325 | heads[(ay * MAX_HEAD_POS + ax) * MAX_LAYERS + layer] = NULL; |
1259 | ns->lastmap.cells[ax][ay].faces[layer] = face_num; |
1326 | ns.lastmap.cells[ax][ay].faces[layer] = face_num; |
1260 | return 1; |
1327 | return 1; |
1261 | } |
1328 | } |
1262 | |
1329 | |
1263 | return 0; /* No change */ |
1330 | return 0; /* No change */ |
1264 | } |
1331 | } |
… | |
… | |
1281 | * the map command, where the faces stack up. Sinces that is no longer |
1348 | * the map command, where the faces stack up. Sinces that is no longer |
1282 | * the case, it seems to make more sense to have these layer values |
1349 | * the case, it seems to make more sense to have these layer values |
1283 | * actually match. |
1350 | * actually match. |
1284 | */ |
1351 | */ |
1285 | |
1352 | |
1286 | static inline int update_space(SockList *sl, NewSocket *ns, mapstruct *mp, int mx, int my, int sx, int sy, int layer) |
1353 | static int update_space(SockList *sl, NewSocket *ns, mapstruct *mp, int mx, int my, int sx, int sy, int layer) |
1287 | { |
1354 | { |
1288 | object *ob, *head; |
1355 | object *ob, *head; |
1289 | uint16 face_num; |
1356 | uint16 face_num; |
1290 | int bx, by,i; |
1357 | int bx, by,i; |
1291 | |
1358 | |
… | |
… | |
1560 | uint16 mask,emask; |
1627 | uint16 mask,emask; |
1561 | uint8 eentrysize; |
1628 | uint8 eentrysize; |
1562 | uint16 ewhatstart,ewhatflag; |
1629 | uint16 ewhatstart,ewhatflag; |
1563 | uint8 extendedinfos; |
1630 | uint8 extendedinfos; |
1564 | mapstruct *m; |
1631 | mapstruct *m; |
|
|
1632 | NewSocket &socket = pl->contr->socket; |
|
|
1633 | |
|
|
1634 | check_map_change (pl->contr); |
1565 | |
1635 | |
1566 | sl.buf=(unsigned char*)malloc(MAXSOCKBUF); |
1636 | sl.buf=(unsigned char*)malloc(MAXSOCKBUF); |
1567 | if (pl->contr->socket.mapmode == Map1Cmd) |
1637 | if (socket.mapmode == Map1Cmd) |
1568 | strcpy((char*)sl.buf,"map1 "); |
1638 | strcpy((char*)sl.buf,"map1 "); |
1569 | else |
1639 | else |
1570 | strcpy((char*)sl.buf,"map1a "); |
1640 | strcpy((char*)sl.buf,"map1a "); |
1571 | sl.len=strlen((char*)sl.buf); |
1641 | sl.len=strlen((char*)sl.buf); |
1572 | startlen = sl.len; |
1642 | startlen = sl.len; |
1573 | /*Extendedmapinfo structure initialisation*/ |
1643 | /*Extendedmapinfo structure initialisation*/ |
1574 | if (pl->contr->socket.ext_mapinfos){ |
1644 | if (socket.ext_mapinfos){ |
1575 | esl.buf=(unsigned char*)malloc(MAXSOCKBUF); |
1645 | esl.buf=(unsigned char*)malloc(MAXSOCKBUF); |
1576 | strcpy((char*)esl.buf,"mapextended "); |
1646 | strcpy((char*)esl.buf,"mapextended "); |
1577 | esl.len=strlen((char*)esl.buf); |
1647 | esl.len=strlen((char*)esl.buf); |
1578 | extendedinfos=EMI_NOREDRAW; |
1648 | extendedinfos=EMI_NOREDRAW; |
1579 | if (pl->contr->socket.EMI_smooth) |
1649 | if (socket.EMI_smooth) |
1580 | extendedinfos|=EMI_SMOOTH; |
1650 | extendedinfos|=EMI_SMOOTH; |
1581 | ewhatstart=esl.len; |
1651 | ewhatstart=esl.len; |
1582 | ewhatflag=extendedinfos; /*The EMI_NOREDRAW bit |
1652 | ewhatflag=extendedinfos; /*The EMI_NOREDRAW bit |
1583 | could need to be taken away*/ |
1653 | could need to be taken away*/ |
1584 | SockList_AddChar(&esl, extendedinfos); |
1654 | SockList_AddChar(&esl, extendedinfos); |
1585 | eentrysize=getExtendedMapInfoSize(&(pl->contr->socket)); |
1655 | eentrysize=getExtendedMapInfoSize(&socket); |
1586 | SockList_AddChar(&esl, eentrysize); |
1656 | SockList_AddChar(&esl, eentrysize); |
1587 | estartlen = esl.len; |
1657 | estartlen = esl.len; |
1588 | } else { |
1658 | } else { |
1589 | /* suppress compiler warnings */ |
1659 | /* suppress compiler warnings */ |
1590 | ewhatstart = 0; |
1660 | ewhatstart = 0; |
… | |
… | |
1600 | ay=0; |
1670 | ay=0; |
1601 | |
1671 | |
1602 | /* We could do this logic as conditionals in the if statement, |
1672 | /* We could do this logic as conditionals in the if statement, |
1603 | * but that started to get a bit messy to look at. |
1673 | * but that started to get a bit messy to look at. |
1604 | */ |
1674 | */ |
1605 | max_x = pl->x+(pl->contr->socket.mapx+1)/2; |
1675 | max_x = pl->x+(socket.mapx+1)/2; |
1606 | max_y = pl->y+(pl->contr->socket.mapy+1)/2; |
1676 | max_y = pl->y+(socket.mapy+1)/2; |
1607 | if (pl->contr->socket.mapmode == Map1aCmd) { |
1677 | if (socket.mapmode == Map1aCmd) { |
1608 | max_x += MAX_HEAD_OFFSET; |
1678 | max_x += MAX_HEAD_OFFSET; |
1609 | max_y += MAX_HEAD_OFFSET; |
1679 | max_y += MAX_HEAD_OFFSET; |
1610 | } |
1680 | } |
1611 | |
1681 | |
1612 | for(y=pl->y-pl->contr->socket.mapy/2; y<max_y; y++,ay++) { |
1682 | for(y=pl->y-socket.mapy/2; y<max_y; y++,ay++) { |
1613 | ax=0; |
1683 | ax=0; |
1614 | for(x=pl->x-pl->contr->socket.mapx/2;x<max_x;x++,ax++) { |
1684 | for(x=pl->x-socket.mapx/2;x<max_x;x++,ax++) { |
1615 | |
1685 | |
1616 | emask = mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; |
1686 | emask = mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; |
1617 | |
1687 | |
1618 | /* If this space is out of the normal viewable area, we only check |
1688 | /* If this space is out of the normal viewable area, we only check |
1619 | * the heads value ax or ay will only be greater than what |
1689 | * the heads value ax or ay will only be greater than what |
1620 | * the client wants if using the map1a command - this is because |
1690 | * the client wants if using the map1a command - this is because |
1621 | * if the map1a command is not used, max_x and max_y will be |
1691 | * if the map1a command is not used, max_x and max_y will be |
1622 | * set to lower values. |
1692 | * set to lower values. |
1623 | */ |
1693 | */ |
1624 | if (ax >= pl->contr->socket.mapx || ay >= pl->contr->socket.mapy) { |
1694 | if (ax >= socket.mapx || ay >= socket.mapy) { |
1625 | int i, got_one; |
1695 | int i, got_one; |
1626 | |
1696 | |
1627 | oldlen = sl.len; |
1697 | oldlen = sl.len; |
1628 | |
1698 | |
1629 | |
|
|
1630 | SockList_AddShort(&sl, mask); |
1699 | SockList_AddShort(&sl, mask); |
1631 | |
1700 | |
1632 | if (check_head(&sl, &pl->contr->socket, ax, ay, 2)) |
1701 | if (check_head (sl, socket, ax, ay, 2)) |
1633 | mask |= 0x4; |
1702 | mask |= 0x4; |
1634 | if (check_head(&sl, &pl->contr->socket, ax, ay, 1)) |
1703 | if (check_head (sl, socket, ax, ay, 1)) |
1635 | mask |= 0x2; |
1704 | mask |= 0x2; |
1636 | if (check_head(&sl, &pl->contr->socket, ax, ay, 0)) |
1705 | if (check_head (sl, socket, ax, ay, 0)) |
1637 | mask |= 0x1; |
1706 | mask |= 0x1; |
1638 | |
1707 | |
1639 | /* If all we are doing is sending 0 (blank) faces, we don't |
1708 | /* If all we are doing is sending 0 (blank) faces, we don't |
1640 | * actually need to send that - just the coordinates |
1709 | * actually need to send that - just the coordinates |
1641 | * with no faces tells the client to blank out the |
1710 | * with no faces tells the client to blank out the |
… | |
… | |
1647 | } |
1716 | } |
1648 | |
1717 | |
1649 | if (got_one && (mask & 0xf)) { |
1718 | if (got_one && (mask & 0xf)) { |
1650 | sl.buf[oldlen+1] = mask & 0xff; |
1719 | sl.buf[oldlen+1] = mask & 0xff; |
1651 | } else { /*either all faces blank, either no face at all*/ |
1720 | } else { /*either all faces blank, either no face at all*/ |
1652 | if (mask & 0xf) /*at least 1 face, we know it's blank, only send coordinates*/ |
1721 | if (mask & 0xf) /*at least 1 face, we know it's blank, only send coordinates*/ |
1653 | sl.len = oldlen + 2; |
1722 | sl.len = oldlen + 2; |
1654 | else |
1723 | else |
1655 | sl.len = oldlen; |
1724 | sl.len = oldlen; |
1656 | } |
1725 | } |
1657 | /*What concerns extendinfos, nothing to be done for now |
1726 | /*What concerns extendinfos, nothing to be done for now |
1658 | * (perhaps effects layer later) |
1727 | * (perhaps effects layer later) |
1659 | */ |
1728 | */ |
1660 | continue; /* don't do processing below */ |
1729 | continue; /* don't do processing below */ |
1661 | } |
1730 | } |
|
|
1731 | |
|
|
1732 | MapCell &lastcell = socket.lastmap.cells[ax][ay]; |
1662 | |
1733 | |
1663 | d = pl->contr->blocked_los[ax][ay]; |
1734 | d = pl->contr->blocked_los[ax][ay]; |
1664 | |
1735 | |
1665 | /* If the coordinates are not valid, or it is too dark to see, |
1736 | /* If the coordinates are not valid, or it is too dark to see, |
1666 | * we tell the client as such |
1737 | * we tell the client as such |
… | |
… | |
1671 | if (!m) { |
1742 | if (!m) { |
1672 | /* space is out of map. Update space and clear values |
1743 | /* space is out of map. Update space and clear values |
1673 | * if this hasn't already been done. If the space is out |
1744 | * if this hasn't already been done. If the space is out |
1674 | * of the map, it shouldn't have a head |
1745 | * of the map, it shouldn't have a head |
1675 | */ |
1746 | */ |
1676 | if (pl->contr->socket.lastmap.cells[ax][ay].count != -1) { |
1747 | if (lastcell.count != -1) { |
1677 | SockList_AddShort(&sl, mask); |
1748 | SockList_AddShort(&sl, mask); |
1678 | map_clearcell(&pl->contr->socket.lastmap.cells[ax][ay],0,0,0,-1); |
1749 | map_clearcell(&lastcell,0,0,0,-1); |
1679 | } |
1750 | } |
1680 | } else if (d>3) { |
1751 | } else if (d>3) { |
1681 | int need_send=0, count; |
1752 | int need_send=0, count; |
1682 | /* This block deals with spaces that are not visible for whatever |
1753 | /* This block deals with spaces that are not visible for whatever |
1683 | * reason. Still may need to send the head for this space. |
1754 | * reason. Still may need to send the head for this space. |
1684 | */ |
1755 | */ |
1685 | |
1756 | |
1686 | oldlen = sl.len; |
1757 | oldlen = sl.len; |
1687 | #if 0 |
1758 | |
1688 | /* First thing we do is blank out this space (clear it) |
|
|
1689 | * if not already done. If the client is using darkness, and |
|
|
1690 | * this space is at the edge, we also include the darkness. |
|
|
1691 | */ |
|
|
1692 | if (d==4) { |
|
|
1693 | if (pl->contr->socket.darkness && pl->contr->socket.lastmap.cells[ax][ay].count != d) { |
|
|
1694 | mask |= 8; |
|
|
1695 | SockList_AddShort(&sl, mask); |
|
|
1696 | SockList_AddChar(&sl, 0); |
|
|
1697 | } |
|
|
1698 | count = d; |
|
|
1699 | } else |
|
|
1700 | #endif |
|
|
1701 | { |
|
|
1702 | SockList_AddShort(&sl, mask); |
1759 | SockList_AddShort(&sl, mask); |
1703 | if (pl->contr->socket.lastmap.cells[ax][ay].count != -1) need_send=1; |
1760 | if (lastcell.count != -1) need_send=1; |
1704 | count = -1; |
1761 | count = -1; |
1705 | } |
|
|
1706 | |
1762 | |
1707 | if (pl->contr->socket.mapmode == Map1aCmd && have_head(ax, ay)) { |
1763 | if (socket.mapmode == Map1aCmd && have_head(ax, ay)) { |
1708 | /* Now check to see if any heads need to be sent */ |
1764 | /* Now check to see if any heads need to be sent */ |
1709 | |
1765 | |
1710 | if (check_head(&sl, &pl->contr->socket, ax, ay, 2)) |
1766 | if (check_head (sl, socket, ax, ay, 2)) |
1711 | mask |= 0x4; |
1767 | mask |= 0x4; |
1712 | if (check_head(&sl, &pl->contr->socket, ax, ay, 1)) |
1768 | if (check_head (sl, socket, ax, ay, 1)) |
1713 | mask |= 0x2; |
1769 | mask |= 0x2; |
1714 | if (check_head(&sl, &pl->contr->socket, ax, ay, 0)) |
1770 | if (check_head (sl, socket, ax, ay, 0)) |
1715 | mask |= 0x1; |
1771 | mask |= 0x1; |
1716 | pl->contr->socket.lastmap.cells[ax][ay].count = count; |
1772 | |
|
|
1773 | lastcell.count = count; |
1717 | |
1774 | |
1718 | } else { |
1775 | } else { |
1719 | struct MapCell *cell = &pl->contr->socket.lastmap.cells[ax][ay]; |
1776 | struct MapCell *cell = &lastcell; |
1720 | /* properly clear a previously sent big face */ |
1777 | /* properly clear a previously sent big face */ |
1721 | if(cell->faces[0] != 0 |
1778 | if(cell->faces[0] != 0 |
1722 | || cell->faces[1] != 0 |
1779 | || cell->faces[1] != 0 |
1723 | || cell->faces[2] != 0) |
1780 | || cell->faces[2] != 0) |
1724 | need_send = 1; |
1781 | need_send = 1; |
1725 | map_clearcell(&pl->contr->socket.lastmap.cells[ax][ay], 0, 0, 0, count); |
1782 | map_clearcell(&lastcell, 0, 0, 0, count); |
1726 | } |
1783 | } |
1727 | |
1784 | |
1728 | if ((mask & 0xf) || need_send) { |
1785 | if ((mask & 0xf) || need_send) { |
1729 | sl.buf[oldlen+1] = mask & 0xff; |
1786 | sl.buf[oldlen+1] = mask & 0xff; |
1730 | } else { |
1787 | } else { |
… | |
… | |
1749 | mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; |
1806 | mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; |
1750 | eoldlen = esl.len; |
1807 | eoldlen = esl.len; |
1751 | emask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; |
1808 | emask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; |
1752 | SockList_AddShort(&sl, mask); |
1809 | SockList_AddShort(&sl, mask); |
1753 | |
1810 | |
1754 | if (pl->contr->socket.ext_mapinfos) |
1811 | if (socket.ext_mapinfos) |
1755 | SockList_AddShort(&esl, emask); |
1812 | SockList_AddShort(&esl, emask); |
1756 | |
1813 | |
|
|
1814 | unsigned char dummy; |
|
|
1815 | unsigned char *last_ext = &dummy; |
|
|
1816 | |
1757 | /* Darkness changed */ |
1817 | /* Darkness changed */ |
1758 | if (pl->contr->socket.lastmap.cells[ax][ay].count != d && pl->contr->socket.darkness) { |
1818 | if (lastcell.count != d && socket.darkness) { |
1759 | pl->contr->socket.lastmap.cells[ax][ay].count = d; |
1819 | mask |= 0x8; |
1760 | mask |= 0x8; /* darkness bit */ |
|
|
1761 | |
1820 | |
1762 | /* Protocol defines 255 full bright, 0 full dark. |
1821 | if (socket.extmap) |
1763 | * We currently don't have that many darkness ranges, |
1822 | { |
1764 | * so we current what limited values we do have. |
1823 | *last_ext |= 0x80; last_ext = sl.buf + sl.len; SockList_AddChar (&sl, d); |
1765 | */ |
1824 | } |
1766 | if (d==0) SockList_AddChar(&sl, 255); |
1825 | else |
1767 | else if (d==1) SockList_AddChar(&sl, 191); |
1826 | SockList_AddChar (&sl, 255 - 64 * d); |
1768 | else if (d==2) SockList_AddChar(&sl, 127); |
|
|
1769 | else if (d==3) SockList_AddChar(&sl, 63); |
|
|
1770 | } |
1827 | } |
1771 | else { |
1828 | |
1772 | /* need to reset from -1 so that if it does become blocked again, |
1829 | lastcell.count = d; |
1773 | * the code that deals with that can detect that it needs to tell |
1830 | |
1774 | * the client that this space is now blocked. |
1831 | if (socket.extmap) |
1775 | */ |
1832 | { |
1776 | pl->contr->socket.lastmap.cells[ax][ay].count = d; |
1833 | uint8 stat_hp = 0; |
1777 | } |
1834 | |
|
|
1835 | // send hp information, if applicable |
|
|
1836 | if (object *op = GET_MAP_FACE_OBJ (m, nx, ny, 0)) |
|
|
1837 | if (op->stats.maxhp > 0 |
|
|
1838 | && (unsigned)op->stats.maxhp + 1 > (unsigned)op->stats.hp |
|
|
1839 | && IS_LIVE (op)) |
|
|
1840 | stat_hp = 255 - op->stats.hp * 255 / op->stats.maxhp; |
|
|
1841 | |
|
|
1842 | if (lastcell.stat_hp != stat_hp) |
|
|
1843 | { |
|
|
1844 | lastcell.stat_hp = stat_hp; |
|
|
1845 | |
|
|
1846 | mask |= 0x8; |
|
|
1847 | *last_ext |= 0x80; last_ext = sl.buf + sl.len; SockList_AddChar (&sl, 5); |
|
|
1848 | SockList_AddChar (&sl, stat_hp); |
|
|
1849 | } |
|
|
1850 | } |
1778 | |
1851 | |
1779 | /* Floor face */ |
1852 | /* Floor face */ |
1780 | if (update_space(&sl, &pl->contr->socket, m, nx, ny, ax, ay, 2)) |
1853 | if (update_space(&sl, &socket, m, nx, ny, ax, ay, 2)) |
1781 | mask |= 0x4; |
1854 | mask |= 0x4; |
1782 | |
1855 | |
1783 | if (pl->contr->socket.EMI_smooth) |
1856 | if (socket.EMI_smooth) |
1784 | if (update_smooth(&esl, &pl->contr->socket, m, nx, ny, ax, ay, 2)){ |
1857 | if (update_smooth(&esl, &socket, m, nx, ny, ax, ay, 2)) |
1785 | emask |= 0x4; |
1858 | emask |= 0x4; |
1786 | } |
|
|
1787 | |
1859 | |
1788 | /* Middle face */ |
1860 | /* Middle face */ |
1789 | if (update_space(&sl, &pl->contr->socket, m, nx, ny, ax, ay, 1)) |
1861 | if (update_space(&sl, &socket, m, nx, ny, ax, ay, 1)) |
1790 | mask |= 0x2; |
1862 | mask |= 0x2; |
1791 | |
1863 | |
1792 | if (pl->contr->socket.EMI_smooth) |
1864 | if (socket.EMI_smooth) |
1793 | if (update_smooth(&esl, &pl->contr->socket, m, nx, ny, ax, ay, 1)){ |
1865 | if (update_smooth(&esl, &socket, m, nx, ny, ax, ay, 1)) |
1794 | emask |= 0x2; |
1866 | emask |= 0x2; |
1795 | } |
|
|
1796 | |
|
|
1797 | |
1867 | |
1798 | if(nx == pl->x && ny == pl->y && pl->invisible & (pl->invisible < 50 ? 4 : 1)) { |
1868 | if(nx == pl->x && ny == pl->y && pl->invisible & (pl->invisible < 50 ? 4 : 1)) { |
1799 | if (pl->contr->socket.lastmap.cells[ax][ay].faces[0] != pl->face->number) { |
1869 | if (lastcell.faces[0] != pl->face->number) { |
1800 | pl->contr->socket.lastmap.cells[ax][ay].faces[0] = pl->face->number; |
1870 | lastcell.faces[0] = pl->face->number; |
1801 | mask |= 0x1; |
1871 | mask |= 0x1; |
1802 | if (!(pl->contr->socket.faces_sent[pl->face->number] &NS_FACESENT_FACE)) |
1872 | if (!(socket.faces_sent[pl->face->number] &NS_FACESENT_FACE)) |
1803 | esrv_send_face(&pl->contr->socket, pl->face->number, 0); |
1873 | esrv_send_face(&socket, pl->face->number, 0); |
1804 | SockList_AddShort(&sl, pl->face->number); |
1874 | SockList_AddShort(&sl, pl->face->number); |
1805 | } |
1875 | } |
1806 | } |
1876 | } |
1807 | /* Top face */ |
1877 | /* Top face */ |
1808 | else { |
1878 | else { |
1809 | if (update_space(&sl, &pl->contr->socket, m, nx, ny, ax, ay, 0)) |
1879 | if (update_space(&sl, &socket, m, nx, ny, ax, ay, 0)) |
1810 | mask |= 0x1; |
1880 | mask |= 0x1; |
1811 | if (pl->contr->socket.EMI_smooth) |
1881 | if (socket.EMI_smooth) |
1812 | if (update_smooth(&esl, &pl->contr->socket, m, nx, ny, ax, ay, 0)){ |
1882 | if (update_smooth(&esl, &socket, m, nx, ny, ax, ay, 0)){ |
1813 | emask |= 0x1; |
1883 | emask |= 0x1; |
1814 | } |
1884 | } |
1815 | } |
1885 | } |
1816 | /* Check to see if we are in fact sending anything for this |
1886 | /* Check to see if we are in fact sending anything for this |
1817 | * space by checking the mask. If so, update the mask. |
1887 | * space by checking the mask. If so, update the mask. |
… | |
… | |
1831 | } /* else this is a viewable space */ |
1901 | } /* else this is a viewable space */ |
1832 | } /* for x loop */ |
1902 | } /* for x loop */ |
1833 | } /* for y loop */ |
1903 | } /* for y loop */ |
1834 | |
1904 | |
1835 | /* Verify that we in fact do need to send this */ |
1905 | /* Verify that we in fact do need to send this */ |
1836 | if (pl->contr->socket.ext_mapinfos){ |
1906 | if (socket.ext_mapinfos){ |
1837 | if (!(sl.len>startlen || pl->contr->socket.sent_scroll)){ |
1907 | if (!(sl.len>startlen || socket.sent_scroll)){ |
1838 | /* No map data will follow, so don't say the client |
1908 | /* No map data will follow, so don't say the client |
1839 | * it doesn't need draw! |
1909 | * it doesn't need draw! |
1840 | */ |
1910 | */ |
1841 | ewhatflag&=(~EMI_NOREDRAW); |
1911 | ewhatflag&=(~EMI_NOREDRAW); |
1842 | esl.buf[ewhatstart+1] = ewhatflag & 0xff; |
1912 | esl.buf[ewhatstart+1] = ewhatflag & 0xff; |
1843 | } |
1913 | } |
1844 | if (esl.len>estartlen) { |
1914 | if (esl.len>estartlen) { |
1845 | Send_With_Handling(&pl->contr->socket, &esl); |
1915 | Send_With_Handling(&socket, &esl); |
1846 | } |
1916 | } |
1847 | free(esl.buf); |
1917 | free(esl.buf); |
1848 | } |
1918 | } |
1849 | if (sl.len>startlen || pl->contr->socket.sent_scroll) { |
1919 | if (sl.len>startlen || socket.sent_scroll) { |
1850 | Send_With_Handling(&pl->contr->socket, &sl); |
1920 | Send_With_Handling(&socket, &sl); |
1851 | pl->contr->socket.sent_scroll = 0; |
1921 | socket.sent_scroll = 0; |
1852 | } |
1922 | } |
1853 | free(sl.buf); |
1923 | free(sl.buf); |
1854 | |
|
|
1855 | check_map_change (pl->contr); |
|
|
1856 | } |
1924 | } |
1857 | |
1925 | |
1858 | /** |
1926 | /** |
1859 | * Draws client map. |
1927 | * Draws client map. |
1860 | */ |
1928 | */ |
… | |
… | |
1977 | esrv_map_doneredraw(&pl->contr->socket, &newmap); |
2045 | esrv_map_doneredraw(&pl->contr->socket, &newmap); |
1978 | |
2046 | |
1979 | check_map_change (pl->contr); |
2047 | check_map_change (pl->contr); |
1980 | } |
2048 | } |
1981 | |
2049 | |
1982 | |
|
|
1983 | void esrv_map_scroll(NewSocket *ns,int dx,int dy) |
|
|
1984 | { |
|
|
1985 | struct Map newmap; |
|
|
1986 | int x,y, mx, my; |
|
|
1987 | char buf[MAXSOCKBUF]; |
|
|
1988 | |
|
|
1989 | sprintf(buf,"map_scroll %d %d", dx, dy); |
|
|
1990 | Write_String_To_Socket(ns, buf, strlen(buf)); |
|
|
1991 | |
|
|
1992 | /* If we are using the Map1aCmd, we may in fact send |
|
|
1993 | * head information that is outside the viewable map. |
|
|
1994 | * So set the mx,my to the max value we want to |
|
|
1995 | * look for. Removed code to do so - it caused extra |
|
|
1996 | * complexities for the client, and probably doesn't make |
|
|
1997 | * that much difference in bandwidth. |
|
|
1998 | */ |
|
|
1999 | mx = ns->mapx; |
|
|
2000 | my = ns->mapy; |
|
|
2001 | |
|
|
2002 | if (ns->mapmode == Map1aCmd) { |
|
|
2003 | mx += MAX_HEAD_OFFSET; |
|
|
2004 | my += MAX_HEAD_OFFSET; |
|
|
2005 | } |
|
|
2006 | |
|
|
2007 | /* the x and y here are coordinates for the new map, i.e. if we moved |
|
|
2008 | * (dx,dy), newmap[x][y] = oldmap[x-dx][y-dy]. For this reason, |
|
|
2009 | * if the destination x or y coordinate is outside the viewable |
|
|
2010 | * area, we clear the values - otherwise, the old values |
|
|
2011 | * are preserved, and the check_head thinks it needs to clear them. |
|
|
2012 | */ |
|
|
2013 | for(x=0; x<mx; x++) { |
|
|
2014 | for(y=0; y<my; y++) { |
|
|
2015 | if(x >= ns->mapx || y >= ns->mapy) { |
|
|
2016 | /* clear cells outside the viewable area */ |
|
|
2017 | memset(&newmap.cells[x][y], 0, sizeof(struct MapCell)); |
|
|
2018 | } |
|
|
2019 | else if ((x+dx) < 0 || (x+dx) >= ns->mapx || (y+dy) < 0 || (y + dy) >= ns->mapy) { |
|
|
2020 | /* clear newly visible tiles within the viewable area */ |
|
|
2021 | memset(&(newmap.cells[x][y]), 0, sizeof(struct MapCell)); |
|
|
2022 | } |
|
|
2023 | else { |
|
|
2024 | memcpy(&(newmap.cells[x][y]), |
|
|
2025 | &(ns->lastmap.cells[x+dx][y+dy]),sizeof(struct MapCell)); |
|
|
2026 | } |
|
|
2027 | } |
|
|
2028 | } |
|
|
2029 | |
|
|
2030 | memcpy(&(ns->lastmap), &newmap,sizeof(struct Map)); |
|
|
2031 | |
|
|
2032 | /* Make sure that the next "map1" command will be sent (even if it is |
|
|
2033 | * empty). |
|
|
2034 | */ |
|
|
2035 | ns->sent_scroll = 1; |
|
|
2036 | } |
|
|
2037 | |
2050 | |
2038 | /*****************************************************************************/ |
2051 | /*****************************************************************************/ |
2039 | /* GROS: The following one is used to allow a plugin to send a generic cmd to*/ |
2052 | /* GROS: The following one is used to allow a plugin to send a generic cmd to*/ |
2040 | /* a player. Of course, the client need to know the command to be able to */ |
2053 | /* a player. Of course, the client need to know the command to be able to */ |
2041 | /* manage it ! */ |
2054 | /* manage it ! */ |