Atrinik Server  4.0
request.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
36 #include <global.h>
37 #include <toolkit/packet.h>
38 #include <toolkit/string.h>
39 #include <monster_data.h>
40 #include <plugin.h>
41 #include <monster_guard.h>
42 #include <player.h>
43 #include <object.h>
44 #include <exp.h>
45 #include <arrow.h>
46 #include <bow.h>
47 #include <magic_mirror.h>
48 #include <sound_ambient.h>
49 #include <object_methods.h>
50 #include <resources.h>
51 #include <toolkit/socket_crypto.h>
52 
53 #define GET_CLIENT_FLAGS(_O_) ((_O_)->flags[0] & 0x7f)
54 #define NO_FACE_SEND (-1)
55 
56 void socket_command_setup(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
57 {
58  packet_struct *packet;
59  uint8_t type;
60 
61  packet = packet_new(CLIENT_CMD_SETUP, 256, 256);
62 
63  while (pos < len) {
64  type = packet_to_uint8(data, len, &pos);
65  packet_debug_data(packet, 0, "Setup type");
66  packet_append_uint8(packet, type);
67 
68  if (type == CMD_SETUP_SOUND) {
69  ns->sound = packet_to_uint8(data, len, &pos);
70  packet_debug_data(packet, 0, "Sound");
71  packet_append_uint8(packet, ns->sound);
72  } else if (type == CMD_SETUP_MAPSIZE) {
73  int x, y;
74 
75  x = packet_to_uint8(data, len, &pos);
76  y = packet_to_uint8(data, len, &pos);
77 
78  if (x < 9 || y < 9 || x > MAP_CLIENT_X || y > MAP_CLIENT_Y) {
79  LOG(PACKET, "X/Y not in range: %d, %d", x, y);
80  x = MAP_CLIENT_X;
81  y = MAP_CLIENT_Y;
82  }
83 
84  ns->mapx = x;
85  ns->mapy = y;
86  ns->mapx_2 = x / 2;
87  ns->mapy_2 = y / 2;
88 
89  packet_debug_data(packet, 0, "Map width");
90  packet_append_uint8(packet, x);
91  packet_debug_data(packet, 0, "Map height");
92  packet_append_uint8(packet, y);
93  } else if (type == CMD_SETUP_BOT) {
94  ns->is_bot = packet_to_uint8(data, len, &pos);
95 
96  if (ns->is_bot != 0 && ns->is_bot != 1) {
97  ns->is_bot = 0;
98  }
99 
100  packet_debug_data(packet, 0, "Bot");
101  packet_append_uint8(packet, ns->is_bot);
102  } else if (type == CMD_SETUP_DATA_URL) {
103  char url[MAX_BUF];
104 
105  packet_to_string(data, len, &pos, url, sizeof(url));
106  packet_debug_data(packet, 0, "Data URL");
107 
108  if (!string_isempty(url)) {
109  packet_append_string_terminated(packet, url);
110  } else {
111  packet_append_string_terminated(packet, settings.http_url);
112  }
113  } else {
114  LOG(PACKET, "Unknown type: %d", type);
115  }
116  }
117 
118  socket_send_packet(ns, packet);
119 }
120 
121 void socket_command_player_cmd(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
122 {
123  char command[MAX_BUF];
124 
125  if (pl->cs->state != ST_PLAYING) {
126  LOG(PACKET, "Received player command while not playing.");
127  return;
128  }
129 
130  packet_to_string(data, len, &pos, command, sizeof(command));
131  commands_handle(pl->ob, command);
132 }
133 
134 void socket_command_version(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
135 {
136  uint32_t ver;
137  packet_struct *packet;
138 
139  /* Ignore multiple version commands. */
140  if (ns->socket_version != 0) {
141  LOG(PACKET, "Received extraneous version command.");
142  return;
143  }
144 
145  ver = packet_to_uint32(data, len, &pos);
146 
147  if (ver == 0 || ver == 991017 || ver == 1055) {
148  draw_info_send(CHAT_TYPE_GAME, NULL, COLOR_RED, ns, "Your client is "
149  "outdated!\nGo to http://www.atrinik.org/ and download the latest "
150  "Atrinik client.");
151  ns->state = ST_ZOMBIE;
152  return;
153  }
154 
155  ns->socket_version = ver;
156 
157  packet = packet_new(CLIENT_CMD_VERSION, 4, 4);
158  packet_debug_data(packet, 0, "Socket version");
159  packet_append_uint32(packet, SOCKET_VERSION);
160  socket_send_packet(ns, packet);
161 }
162 
163 void socket_command_item_move(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
164 {
165  tag_t to, tag;
166  uint32_t nrof;
167 
168  to = packet_to_uint32(data, len, &pos);
169  tag = packet_to_uint32(data, len, &pos);
170  nrof = packet_to_uint32(data, len, &pos);
171 
172  if (tag == 0) {
173  LOG(PACKET, "Tag is zero.");
174  return;
175  }
176 
177  esrv_move_object(pl->ob, to, tag, nrof);
178 }
179 
188 {
189  HARD_ASSERT(pl != NULL);
190 
191  SOFT_ASSERT(pl->ob != NULL, "Player has no object!");
192 
193 #define _Add(_old, _new, _type, _bitsize) \
194  if (packet == NULL) { \
195  packet = packet_new(CLIENT_CMD_STATS, 32, 128); \
196  } \
197  (_old) = (_new); \
198  packet_debug_data(packet, 0, "Stats command type"); \
199  packet_append_uint8(packet, (_type)); \
200  packet_debug_data(packet, 0, "%s", #_new); \
201  packet_append_ ## _bitsize(packet, (_new));
202 #define AddIf(_old, _new, _type, _bitsize) \
203  if ((_old) != (_new)) { \
204  _Add(_old, _new, _type, _bitsize); \
205  }
206 #define AddIfFloat(_old, _new, _type) \
207  if (!FLT_EQUAL(_old, _new)) { \
208  _Add(_old, _new, _type, float); \
209  }
210 #define AddIfDouble(_old, _new, _type) \
211  if (!DBL_EQUAL(_old, _new)) { \
212  _Add(_old, _new, _type, double); \
213  }
214 
215  packet_struct *packet = NULL;
216 
217  if (pl->target_object && pl->target_object != pl->ob) {
218  uint8_t hp = MAX(1, (((float) pl->target_object->stats.hp /
219  (float) pl->target_object->stats.maxhp) * 100.0f));
220  AddIf(pl->target_hp, hp, CS_STAT_TARGET_HP, uint8);
221  }
222 
223  AddIf(pl->last_gen_hp, pl->gen_client_hp, CS_STAT_REG_HP, uint16);
224  AddIf(pl->last_gen_sp, pl->gen_client_sp, CS_STAT_REG_MANA, uint16);
225  AddIfFloat(pl->last_action_timer, pl->action_timer, CS_STAT_ACTION_TIME);
226  AddIf(pl->last_level, pl->ob->level, CS_STAT_LEVEL, uint8);
227  AddIfDouble(pl->last_speed, pl->ob->speed, CS_STAT_SPEED);
228  AddIfDouble(pl->last_weapon_speed, pl->ob->weapon_speed / MAX_TICKS,
229  CS_STAT_WEAPON_SPEED);
230  AddIf(pl->last_weight_limit, weight_limit[pl->ob->stats.Str],
231  CS_STAT_WEIGHT_LIM, uint32);
232  AddIf(pl->last_stats.hp, pl->ob->stats.hp, CS_STAT_HP, int32);
233  AddIf(pl->last_stats.maxhp, pl->ob->stats.maxhp, CS_STAT_MAXHP, int32);
234  AddIf(pl->last_stats.sp, pl->ob->stats.sp, CS_STAT_SP, int16);
235  AddIf(pl->last_stats.maxsp, pl->ob->stats.maxsp, CS_STAT_MAXSP, int16);
236  AddIf(pl->last_stats.Str, pl->ob->stats.Str, CS_STAT_STR, uint8);
237  AddIf(pl->last_stats.Dex, pl->ob->stats.Dex, CS_STAT_DEX, uint8);
238  AddIf(pl->last_stats.Con, pl->ob->stats.Con, CS_STAT_CON, uint8);
239  AddIf(pl->last_stats.Int, pl->ob->stats.Int, CS_STAT_INT, uint8);
240  AddIf(pl->last_stats.Pow, pl->ob->stats.Pow, CS_STAT_POW, uint8);
241  AddIf(pl->last_stats.exp, pl->ob->stats.exp, CS_STAT_EXP, uint64);
242  AddIf(pl->last_stats.wc, pl->ob->stats.wc, CS_STAT_WC, uint16);
243  AddIf(pl->last_stats.ac, pl->ob->stats.ac, CS_STAT_AC, uint16);
244  AddIf(pl->last_stats.dam, pl->ob->stats.dam, CS_STAT_DAM, uint16);
245  AddIf(pl->last_stats.food, pl->ob->stats.food, CS_STAT_FOOD, uint16);
246  AddIf(pl->last_path_attuned, pl->ob->path_attuned,
247  CS_STAT_PATH_ATTUNED, uint32);
248  AddIf(pl->last_path_repelled, pl->ob->path_repelled,
249  CS_STAT_PATH_REPELLED, uint32);
250  AddIf(pl->last_path_denied, pl->ob->path_denied,
251  CS_STAT_PATH_DENIED, uint32);
252 
253  object *ranged_weapon = pl->equipment[PLAYER_EQUIP_WEAPON_RANGED];
254  object *arrow = NULL;
255  if (ranged_weapon != NULL && ranged_weapon->type == BOW) {
256  arrow = arrow_find(pl->ob, ranged_weapon->race);
257  }
258 
259  int16_t ranged_dam, ranged_wc;
260  float ranged_ws;
261  if (arrow != NULL) {
262  HARD_ASSERT(ranged_weapon != NULL);
263  ranged_dam = arrow_get_damage(pl->ob, ranged_weapon, arrow);
264  ranged_wc = arrow_get_wc(pl->ob, ranged_weapon, arrow);
265  ranged_ws = bow_get_ws(ranged_weapon, arrow);
266  } else if (ranged_weapon != NULL && ranged_weapon->type == SPELL) {
267  ranged_dam = SP_level_dam_adjust(pl->ob, ranged_weapon->stats.sp, true);
268  ranged_wc = 200;
269  ranged_ws = spells[ranged_weapon->stats.sp].time / MAX_TICKS;
270  } else {
271  ranged_dam = ranged_wc = ranged_ws = 0;
272  }
273 
274  AddIf(pl->last_ranged_dam, ranged_dam, CS_STAT_RANGED_DAM, uint16);
275  AddIf(pl->last_ranged_wc, ranged_wc, CS_STAT_RANGED_WC, uint16);
276  AddIfFloat(pl->last_ranged_ws, ranged_ws, CS_STAT_RANGED_WS);
277 
278  uint16_t flags = 0;
279 
280  if (pl->run_on) {
281  flags |= SF_RUNON;
282  }
283 
284  /* we add additional player status flags - in old style, you got a msg
285  * in the text windows when you get xray of get blinded - we will skip
286  * this and add the info here, so the client can track it down and make
287  * it the user visible in it own, server independent way. */
288 
289  /* player is blind */
290  if (QUERY_FLAG(pl->ob, FLAG_BLIND)) {
291  flags |= SF_BLIND;
292  }
293 
294  /* player has xray */
295  if (QUERY_FLAG(pl->ob, FLAG_XRAYS)) {
296  flags |= SF_XRAYS;
297  }
298 
299  /* player has infravision */
300  if (QUERY_FLAG(pl->ob, FLAG_SEE_IN_DARK)) {
301  flags |= SF_INFRAVISION;
302  }
303 
304  AddIf(pl->last_flags, flags, CS_STAT_FLAGS, uint16);
305 
306  for (int i = 0; i < NROFATTACKS; i++) {
307  /* If there are more attacks, but we reached CS_STAT_PROT_END,
308  * we stop now. */
309  if (CS_STAT_PROT_START + i > CS_STAT_PROT_END) {
310  break;
311  }
312 
313  AddIf(pl->last_protection[i], pl->ob->protection[i],
314  CS_STAT_PROT_START + i, int8);
315  }
316 
317  for (int i = 0; i < PLAYER_EQUIP_MAX; i++) {
318  AddIf(pl->last_equipment[i], pl->equipment[i] != NULL ?
319  pl->equipment[i]->count : 0, CS_STAT_EQUIP_START + i, uint32);
320  }
321 
322  AddIf(pl->last_gender, object_get_gender(pl->ob), CS_STAT_GENDER, uint8);
323 
324  if (packet != NULL) {
325  socket_send_packet(pl->cs, packet);
326  }
327 
328 #undef AddIf
329 #undef _Add
330 #undef AddIfFloat
331 #undef AddIfDouble
332 }
333 
337 void esrv_new_player(player *pl, uint32_t weight)
338 {
339  packet_struct *packet;
340 
341  packet = packet_new(CLIENT_CMD_PLAYER, 12, 0);
342  packet_debug_data(packet, 0, "Player object ID");
343  packet_append_uint32(packet, pl->ob->count);
344  packet_debug_data(packet, 0, "Weight");
345  packet_append_uint32(packet, weight);
346  packet_debug_data(packet, 0, "Face number");
347  packet_append_uint32(packet, pl->ob->face->number);
348  packet_debug_data(packet, 0, "Name");
349  packet_append_string_terminated(packet, pl->ob->name);
350  socket_send_packet(pl->cs, packet);
351 }
352 
362 static inline int get_tiled_map_id(player *pl, struct mapdef *map)
363 {
364  int i;
365 
366  if (!pl->last_update) {
367  return 0;
368  }
369 
370  for (i = 0; i < TILED_NUM_DIR; i++) {
371  if (pl->last_update->tile_path[i] == map->path) {
372  return i + 1;
373  }
374  }
375 
376  return 0;
377 }
378 
388 static inline void copy_lastmap(socket_struct *ns, int dx, int dy)
389 {
390  struct Map newmap;
391  int x, y;
392 
393  for (x = 0; x < ns->mapx; x++) {
394  for (y = 0; y < ns->mapy; y++) {
395  if (x + dx < 0 || x + dx >= ns->mapx || y + dy < 0 || y + dy >= ns->mapy) {
396  memset(&(newmap.cells[x][y]), 0, sizeof(MapCell));
397  continue;
398  }
399 
400  memcpy(&(newmap.cells[x][y]), &(ns->lastmap.cells[x + dx][y + dy]), sizeof(MapCell));
401  }
402  }
403 
404  memcpy(&(ns->lastmap), &newmap, sizeof(struct Map));
405 }
406 
407 void draw_map_text_anim(object *pl, const char *color, const char *text)
408 {
409  packet_struct *packet;
410 
411  packet = packet_new(CLIENT_CMD_MAPSTATS, 64, 64);
412  packet_debug_data(packet, 0, "Mapstats command type");
413  packet_append_uint8(packet, CMD_MAPSTATS_TEXT_ANIM);
414  packet_debug_data(packet, 0, "Color");
415  packet_append_string_terminated(packet, color);
416  packet_debug_data(packet, 0, "Text");
417  packet_append_string_terminated(packet, text);
418  socket_send_packet(CONTR(pl)->cs, packet);
419 }
420 
426 void draw_client_map(object *pl)
427 {
428  int redraw_below = 0;
429 
430  if (pl->type != PLAYER) {
431  LOG(BUG, "Called with non-player: %s", pl->name);
432  return;
433  }
434 
435  /* IF player is just joining the game, he isn't on a map,
436  * If so, don't try to send them a map. All will
437  * be OK once they really log in. */
438  if (!pl->map || pl->map->in_memory != MAP_IN_MEMORY) {
439  return;
440  }
441 
442  CONTR(pl)->map_update_cmd = MAP_UPDATE_CMD_SAME;
443 
444  /* If we changed somewhere the map, prepare map data */
445  if (CONTR(pl)->last_update != pl->map) {
446  int tile_map = get_tiled_map_id(CONTR(pl), pl->map);
447 
448  /* Are we on a new map? */
449  if (!CONTR(pl)->last_update || !tile_map) {
450  CONTR(pl)->map_update_cmd = MAP_UPDATE_CMD_NEW;
451  memset(&(CONTR(pl)->cs->lastmap), 0, sizeof(struct Map));
452  CONTR(pl)->last_update = pl->map;
453  redraw_below = 1;
454  } else {
455  CONTR(pl)->map_update_cmd = MAP_UPDATE_CMD_CONNECTED;
456  CONTR(pl)->map_update_tile = tile_map;
457  redraw_below = 1;
458 
459  /* We have moved to a tiled map. Let's calculate the offsets. */
460  switch (tile_map - 1) {
461  case 0:
462  CONTR(pl)->map_off_x = pl->x - CONTR(pl)->map_tile_x;
463  CONTR(pl)->map_off_y = -(CONTR(pl)->map_tile_y + (MAP_HEIGHT(pl->map) - pl->y));
464  break;
465 
466  case 1:
467  CONTR(pl)->map_off_y = pl->y - CONTR(pl)->map_tile_y;
468  CONTR(pl)->map_off_x = (MAP_WIDTH(pl->map) - CONTR(pl)->map_tile_x) + pl->x;
469  break;
470 
471  case 2:
472  CONTR(pl)->map_off_x = pl->x - CONTR(pl)->map_tile_x;
473  CONTR(pl)->map_off_y = (MAP_HEIGHT(pl->map) - CONTR(pl)->map_tile_y) + pl->y;
474  break;
475 
476  case 3:
477  CONTR(pl)->map_off_y = pl->y - CONTR(pl)->map_tile_y;
478  CONTR(pl)->map_off_x = -(CONTR(pl)->map_tile_x + (MAP_WIDTH(pl->map) - pl->x));
479  break;
480 
481  case 4:
482  CONTR(pl)->map_off_y = -(CONTR(pl)->map_tile_y + (MAP_HEIGHT(pl->map) - pl->y));
483  CONTR(pl)->map_off_x = (MAP_WIDTH(pl->map) - CONTR(pl)->map_tile_x) + pl->x;
484  break;
485 
486  case 5:
487  CONTR(pl)->map_off_x = (MAP_WIDTH(pl->map) - CONTR(pl)->map_tile_x) + pl->x;
488  CONTR(pl)->map_off_y = (MAP_HEIGHT(pl->map) - CONTR(pl)->map_tile_y) + pl->y;
489  break;
490 
491  case 6:
492  CONTR(pl)->map_off_y = (MAP_HEIGHT(pl->map) - CONTR(pl)->map_tile_y) + pl->y;
493  CONTR(pl)->map_off_x = -(CONTR(pl)->map_tile_x + (MAP_WIDTH(pl->map) - pl->x));
494  break;
495 
496  case 7:
497  CONTR(pl)->map_off_x = -(CONTR(pl)->map_tile_x + (MAP_WIDTH(pl->map) - pl->x));
498  CONTR(pl)->map_off_y = -(CONTR(pl)->map_tile_y + (MAP_HEIGHT(pl->map) - pl->y));
499  break;
500  }
501 
502  copy_lastmap(CONTR(pl)->cs, CONTR(pl)->map_off_x, CONTR(pl)->map_off_y);
503  CONTR(pl)->last_update = pl->map;
504  }
505  } else {
506  if (CONTR(pl)->map_tile_x != pl->x || CONTR(pl)->map_tile_y != pl->y) {
507  copy_lastmap(CONTR(pl)->cs, pl->x - CONTR(pl)->map_tile_x, pl->y - CONTR(pl)->map_tile_y);
508  redraw_below = 1;
509  }
510  }
511 
512  /* Redraw below window and backbuffer new positions? */
513  if (redraw_below) {
514  /* Backbuffer position so we can determine whether we have moved or not
515  * */
516  CONTR(pl)->map_tile_x = pl->x;
517  CONTR(pl)->map_tile_y = pl->y;
518  CONTR(pl)->cs->below_clear = 1;
519  /* Redraw it */
520  CONTR(pl)->cs->update_tile = 0;
521  CONTR(pl)->cs->look_position = 0;
522  }
523 
524  /* Do LOS after calls to update_position */
525  if (CONTR(pl)->update_los) {
526  update_los(pl);
527  CONTR(pl)->update_los = 0;
528  }
529 
530  draw_client_map2(pl);
531 
532  /* If we moved on the same map, check for map name/music to update. */
533  if (redraw_below && CONTR(pl)->map_update_cmd == MAP_UPDATE_CMD_SAME) {
534  MapSpace *msp;
535  packet_struct *packet;
536  object *map_info;
537 
538  msp = GET_MAP_SPACE_PTR(pl->map, pl->x, pl->y);
539  map_info = msp->map_info && OBJECT_VALID(msp->map_info, msp->map_info_count) ? msp->map_info : NULL;
540 
541  packet = packet_new(CLIENT_CMD_MAPSTATS, 256, 256);
542 
543  if ((map_info && map_info->race && strcmp(map_info->race, CONTR(pl)->map_info_name) != 0) || (!map_info && CONTR(pl)->map_info_name[0] != '\0')) {
544  packet_debug_data(packet, 0, "\nMapstats command type");
545  packet_append_uint8(packet, CMD_MAPSTATS_NAME);
546  packet_append_map_name(packet, pl, map_info);
547 
548  if (map_info) {
549  strncpy(CONTR(pl)->map_info_name, map_info->race, sizeof(CONTR(pl)->map_info_name) - 1);
550  CONTR(pl)->map_info_name[sizeof(CONTR(pl)->map_info_name) - 1] = '\0';
551  } else {
552  CONTR(pl)->map_info_name[0] = '\0';
553  }
554  }
555 
556  if ((map_info && map_info->slaying && strcmp(map_info->slaying, CONTR(pl)->map_info_music) != 0) || (!map_info && CONTR(pl)->map_info_music[0] != '\0')) {
557  packet_debug_data(packet, 0, "\nMapstats command type");
558  packet_append_uint8(packet, CMD_MAPSTATS_MUSIC);
559  packet_append_map_music(packet, pl, map_info);
560 
561  if (map_info) {
562  strncpy(CONTR(pl)->map_info_music, map_info->slaying, sizeof(CONTR(pl)->map_info_music) - 1);
563  CONTR(pl)->map_info_music[sizeof(CONTR(pl)->map_info_music) - 1] = '\0';
564  } else {
565  CONTR(pl)->map_info_music[0] = '\0';
566  }
567  }
568 
569  if ((map_info && map_info->title && strcmp(map_info->title, CONTR(pl)->map_info_weather) != 0) || (!map_info && CONTR(pl)->map_info_weather[0] != '\0')) {
570  packet_debug_data(packet, 0, "\nMapstats command type");
571  packet_append_uint8(packet, CMD_MAPSTATS_WEATHER);
572  packet_append_map_weather(packet, pl, map_info);
573 
574  if (map_info) {
575  strncpy(CONTR(pl)->map_info_weather, map_info->title, sizeof(CONTR(pl)->map_info_weather) - 1);
576  CONTR(pl)->map_info_weather[sizeof(CONTR(pl)->map_info_weather) - 1] = '\0';
577  } else {
578  CONTR(pl)->map_info_weather[0] = '\0';
579  }
580  }
581 
582  /* Anything to send? */
583  if (packet->len >= 1) {
584  socket_send_packet(CONTR(pl)->cs, packet);
585  } else {
586  packet_free(packet);
587  }
588  }
589 }
590 
603 static const char *get_playername_color(object *pl, object *op)
604 {
605  if (CONTR(pl)->party != NULL && CONTR(op)->party != NULL && CONTR(pl)->party == CONTR(op)->party) {
606  return COLOR_GREEN;
607  } else if (pl != op && pvp_area(pl, op)) {
608  return COLOR_RED;
609  }
610 
611  return COLOR_WHITE;
612 }
613 
614 void packet_append_map_name(struct packet_struct *packet, object *op, object *map_info)
615 {
616  packet_debug_data(packet, 0, "Map name");
617  packet_append_string(packet, "[b][o=#000000]");
618  packet_append_string(packet, map_info && map_info->race ? map_info->race : op->map->name);
619  packet_append_string_terminated(packet, "[/o][/b]");
620 }
621 
622 void packet_append_map_music(struct packet_struct *packet, object *op, object *map_info)
623 {
624  packet_debug_data(packet, 0, "Map music");
625  packet_append_string_terminated(packet, map_info && map_info->slaying ? map_info->slaying : (op->map->bg_music ? op->map->bg_music : "no_music"));
626 }
627 
628 void packet_append_map_weather(struct packet_struct *packet, object *op, object *map_info)
629 {
630  packet_debug_data(packet, 0, "Map weather");
631  packet_append_string_terminated(packet, map_info && map_info->title ? map_info->title : (op->map->weather ? op->map->weather : "none"));
632 }
633 
635 #define map_clearcell(_cell_) \
636  { \
637  memset((void *) ((char *) (_cell_) + offsetof(MapCell, cleared)), 0, sizeof(MapCell) - offsetof(MapCell, cleared)); \
638  (_cell_)->cleared = 1; \
639  }
640 
642 #define map_if_clearcell() \
643  { \
644  if (CONTR(pl)->cs->lastmap.cells[ax][ay].cleared != 1) \
645  { \
646  packet_debug_data(packet, 0, "Clearing tile %d,%d, mask", ax, ay); \
647  packet_append_uint16(packet, mask | MAP2_MASK_CLEAR); \
648  map_clearcell(&CONTR(pl)->cs->lastmap.cells[ax][ay]); \
649  } \
650  }
651 
653 void draw_client_map2(object *pl)
654 {
655  static uint32_t map2_count = 0;
656  MapCell *mp;
657  MapSpace *msp, *msp_pl, *msp_tmp;
658  mapstruct *m, *tiled;
659  int x, y, ax, ay, d, nx, ny;
660  int have_down, draw_up, blocksview;
661  int special_vision, is_building_wall;
662  uint16_t mask;
663  int layer, dark[NUM_SUB_LAYERS], dark_set[NUM_SUB_LAYERS];
664  int ext_flags, anim_num;
665  int num_layers;
666  object *mirror = NULL, *tmp, *tmp2;
667  uint8_t have_sound_ambient;
668  packet_struct *packet, *packet_layer, *packet_sound;
669  uint8_t floor_z_down, floor_z_up;
670  int sub_layer, sub_layer2, socket_layer, tiled_dir, tiled_depth, zadj;
671  int force_draw_double, priority, tiled_z, is_in_building;
672  packet_save_t packet_save_buf;
673 
674  /* Any kind of special vision? */
675  special_vision = (QUERY_FLAG(pl, FLAG_XRAYS) ? 1 : 0) | (QUERY_FLAG(pl, FLAG_SEE_IN_DARK) ? 2 : 0);
676  map2_count++;
677 
678  packet = packet_new(CLIENT_CMD_MAP, 0, 512);
679  packet_sound = packet_new(CLIENT_CMD_SOUND_AMBIENT, 0, 256);
680 
681  packet_enable_ndelay(packet);
682  packet_debug_data(packet, 0, "Map update command type");
683  packet_append_uint8(packet, CONTR(pl)->map_update_cmd);
684 
685  if (CONTR(pl)->map_update_cmd != MAP_UPDATE_CMD_SAME) {
686  object *map_info;
687  const region_struct *region;
688 
689  msp = GET_MAP_SPACE_PTR(pl->map, pl->x, pl->y);
690  map_info = msp->map_info && OBJECT_VALID(msp->map_info, msp->map_info_count) ? msp->map_info : NULL;
691 
692  packet_append_map_name(packet, pl, map_info);
693  packet_append_map_music(packet, pl, map_info);
694  packet_append_map_weather(packet, pl, map_info);
695  packet_debug_data(packet, 0, "Map height diff");
696  packet_append_uint8(packet, MAP_HEIGHT_DIFF(pl->map) != 0);
697 
698  if (map_info) {
699  if (map_info->race) {
700  strncpy(CONTR(pl)->map_info_name, map_info->race, sizeof(CONTR(pl)->map_info_name) - 1);
701  CONTR(pl)->map_info_name[sizeof(CONTR(pl)->map_info_name) - 1] = '\0';
702  }
703 
704  if (map_info->slaying) {
705  strncpy(CONTR(pl)->map_info_music, map_info->slaying, sizeof(CONTR(pl)->map_info_music) - 1);
706  CONTR(pl)->map_info_music[sizeof(CONTR(pl)->map_info_music) - 1] = '\0';
707  }
708 
709  if (map_info->title) {
710  strncpy(CONTR(pl)->map_info_weather, map_info->title, sizeof(CONTR(pl)->map_info_weather) - 1);
711  CONTR(pl)->map_info_weather[sizeof(CONTR(pl)->map_info_weather) - 1] = '\0';
712  }
713  }
714 
715  region = pl->map->region != NULL ?
716  region_find_with_map(pl->map->region) : NULL;
717 
718  if (CONTR(pl)->cs->socket_version >= 1059) {
719  bool has_map;
720 
721  has_map = false;
722 
723  /* TODO: This should be improved once maps have a real basename */
724  if (region != NULL && (pl->map->region->map_first != NULL ||
725  pl->map->coords[2] >= 0)) {
726  char *basename, *underscore, *basename_region;
727 
728  basename = strrchr(pl->map->path, '/') + 1;
729  underscore = basename ? strchr(basename, '_') : NULL;
730  basename_region = strrchr(region->map_first, '/') + 1;
731 
732  if (basename != NULL && basename_region != NULL &&
733  underscore != NULL && strncmp(basename, basename_region,
734  underscore - basename) == 0) {
735  has_map = true;
736  }
737  }
738 
739  packet_debug_data(packet, 0, "Display region map");
740  packet_append_uint8(packet, has_map);
741  packet_debug_data(packet, 0, "Region name");
742  packet_append_string_terminated(packet,
743  region != NULL ? region->name : "");
744  packet_debug_data(packet, 0, "Region long name");
745  packet_append_string_terminated(packet,
746  region != NULL ? region_get_longname(region) : "");
747  packet_debug_data(packet, 0, "Map path");
748  packet_append_string_terminated(packet, pl->map->path);
749  }
750 
751  if (CONTR(pl)->map_update_cmd == MAP_UPDATE_CMD_CONNECTED) {
752  packet_debug_data(packet, 0, "Map update tile");
753  packet_append_uint8(packet, CONTR(pl)->map_update_tile);
754  packet_debug_data(packet, 0, "Map X offset");
755  packet_append_int8(packet, CONTR(pl)->map_off_x);
756  packet_debug_data(packet, 0, "Map Y offset");
757  packet_append_int8(packet, CONTR(pl)->map_off_y);
758  } else {
759  packet_debug_data(packet, 0, "Map width");
760  packet_append_uint8(packet, pl->map->width);
761  packet_debug_data(packet, 0, "Map height");
762  packet_append_uint8(packet, pl->map->height);
763  }
764  }
765 
766  msp_pl = GET_MAP_SPACE_PTR(pl->map, pl->x, pl->y);
767  /* Figure out whether the player is in a building, but not on a balcony. */
768  is_in_building = (msp_pl->extra_flags & (MSP_EXTRA_IS_BUILDING |
770 
771  packet_debug_data(packet, 0, "Player's X coordinate");
772  packet_append_uint8(packet, pl->x);
773  packet_debug_data(packet, 0, "Player's Y coordinate");
774  packet_append_uint8(packet, pl->y);
775  packet_debug_data(packet, 0, "Player's sub-layer");
776  packet_append_uint8(packet, pl->sub_layer);
777  packet_debug_data(packet, 0, "Player is in building");
778  packet_append_uint8(packet, is_in_building);
779 
780  for (ay = CONTR(pl)->cs->mapy - 1, y = (pl->y + (CONTR(pl)->cs->mapy + 1) / 2) - 1; y >= pl->y - CONTR(pl)->cs->mapy_2; y--, ay--) {
781  ax = CONTR(pl)->cs->mapx - 1;
782 
783  for (x = (pl->x + (CONTR(pl)->cs->mapx + 1) / 2) - 1; x >= pl->x - CONTR(pl)->cs->mapx_2; x--, ax--) {
784  d = CONTR(pl)->blocked_los[ax][ay];
785  /* Form the data packet for x and y positions. */
786  mask = (ax & 0x1f) << 11 | (ay & 0x1f) << 6;
787  mp = &(CONTR(pl)->cs->lastmap.cells[ax][ay]);
788 
789  /* Space is out of map or blocked. Update space and clear values if
790  * needed. */
791  if (d & BLOCKED_LOS_OUT_OF_MAP) {
793  continue;
794  }
795 
796  nx = x;
797  ny = y;
798 
799  if (!(m = get_map_from_coord(pl->map, &nx, &ny))) {
801  continue;
802  }
803 
804  msp = GET_MAP_SPACE_PTR(m, nx, ny);
805  /* Check whether there is ambient sound effect on this tile. */
806  have_sound_ambient = msp->sound_ambient && OBJECT_VALID(msp->sound_ambient, msp->sound_ambient_count);
807 
808  /* If there is an ambient sound effect but it cannot be heard
809  * through walls due to its configuration, we will pretend
810  * there is no sound effect here. */
811  if (have_sound_ambient && ((!QUERY_FLAG(msp->sound_ambient,
812  FLAG_XRAYS) && d & BLOCKED_LOS_BLOCKED) ||
814  have_sound_ambient = 0;
815  }
816 
817  /* If there is an ambient sound effect and we haven't sent it
818  * before, or there isn't one but it was sent before, send an
819  * update. */
820  if ((have_sound_ambient && mp->sound_ambient_count !=
821  msp->sound_ambient->count) || (!have_sound_ambient &&
822  mp->sound_ambient_count)) {
823  packet_debug(packet_sound, 0, "\nSound tile data:");
824  packet_debug_data(packet_sound, 1, "X coordinate");
825  packet_append_uint8(packet_sound, ax);
826  packet_debug_data(packet_sound, 1, "Y coordinate");
827  packet_append_uint8(packet_sound, ay);
828  packet_debug_data(packet_sound, 1, "Last sound object ID");
829  packet_append_uint32(packet_sound, mp->sound_ambient_count);
830  packet_debug_data(packet_sound, 1, "Sound object ID");
831 
832  if (have_sound_ambient) {
833  packet_append_uint32(packet_sound,
834  msp->sound_ambient->count);
835  packet_debug_data(packet_sound, 1, "Sound filename");
836  packet_append_string_terminated(packet_sound,
837  msp->sound_ambient->race);
838  packet_debug_data(packet_sound, 1, "Volume");
839  packet_append_uint8(packet_sound,
841  packet_debug_data(packet_sound, 1, "Max range");
842  packet_append_uint8(packet_sound,
843  msp->sound_ambient->item_level);
844 
846  } else {
847  packet_append_uint32(packet_sound, 0);
848 
849  mp->sound_ambient_count = 0;
850  }
851  }
852 
853  blocksview = d & BLOCKED_LOS_BLOCKED;
854 
855  if (blocksview && (is_in_building || !(msp->extra_flags &
857  (msp->map_info != NULL &&
859  msp_pl->map_info != NULL &&
860  (msp_pl->extra_flags & MSP_EXTRA_IS_BUILDING) &&
861  msp->map_info->name != msp_pl->map_info->name))) {
863  continue;
864  }
865 
866  /* Any map_if_clearcell() calls should go above this line. */
867  mp->cleared = 0;
868 
869  /* Border tile, we can ignore every LOS change */
870  if (!(d & BLOCKED_LOS_IGNORE)) {
871  /* Tile has blocksview set? */
872  if (msp->flags & P_BLOCKSVIEW) {
873  if (!d) {
874  CONTR(pl)->update_los = 1;
875  }
876  } else {
877  if (d & BLOCKED_LOS_BLOCKSVIEW) {
878  CONTR(pl)->update_los = 1;
879  }
880  }
881  }
882 
883  map_get_darkness(m, nx, ny, &mirror);
884 
885  for (sub_layer = 0; sub_layer < NUM_SUB_LAYERS; sub_layer++) {
886  dark_set[sub_layer] = 0;
887  }
888 
889  /* Initialize default values for some variables. */
890  ext_flags = 0;
891  packet_save(packet, &packet_save_buf);
892  anim_num = 0;
893  have_down = 0;
894  floor_z_down = floor_z_up = 0;
895  zadj = 0;
896 
897  uint8_t anim_type[NUM_SUB_LAYERS] = {0};
898  int16_t anim_value[NUM_SUB_LAYERS] = {0};
899 
900  /* Check if we have a map under this tile. */
901  if (get_map_from_tiled(m, TILED_DOWN) != NULL &&
902  MAP_TILE_IS_SAME_LEVEL(m, -1)) {
903  have_down = 1;
904  }
905 
906  bool override_rendering = true;
907  mapstruct *bottom_map = NULL;
908  int bottom_map_depth = 0;
909 
910  for (tiled_dir = TILED_DOWN; tiled_dir >= TILED_UP; tiled_dir--) {
911  tiled = m;
912  tiled_depth = 0;
913 
914  do {
915  if (m != tiled) {
916  tiled_depth += tiled_dir == TILED_UP ? 1 : -1;
917 
918  if (!MAP_TILE_IS_SAME_LEVEL(m, tiled_depth)) {
919  break;
920  }
921  }
922 
923  msp_tmp = GET_MAP_SPACE_PTR(tiled, nx, ny);
924 
925  if (OBJECT_VALID(msp_tmp->map_info,
926  msp_tmp->map_info_count) && msp_tmp->extra_flags &
929  override_rendering = false;
930  }
931 
932  if (tiled_dir == TILED_DOWN) {
933  if (m != tiled) {
934  bottom_map = tiled;
935  bottom_map_depth--;
936  }
937 
938  for (sub_layer = 0; sub_layer < NUM_SUB_LAYERS;
939  sub_layer++) {
940  tmp = GET_MAP_OB_LAYER(tiled, nx, ny, LAYER_FLOOR,
941  sub_layer);
942 
943  if (tmp == NULL) {
944  continue;
945  }
946 
947  if (tmp->z > zadj) {
948  zadj = tmp->z;
949  }
950  }
951  }
952 
953  tiled = get_map_from_tiled(tiled, tiled_dir);
954  } while (tiled != NULL);
955  }
956 
957  if (override_rendering) {
958  tiled_dir = TILED_DOWN;
959  tiled_depth = bottom_map_depth;
960  }
961 
962  draw_up = m->tile_map[TILED_UP] != NULL;
963 
964  /* If the player is inside a building, and we're currently on the
965  * map square that is part of that building, do not send objects
966  * on the upper floors.
967  *
968  * This means that if a player is for example on the ground floor,
969  * anything above that will not be visible while they're in the
970  * building, *but*, only for that building - other buildings will
971  * have the upper floors. */
972  if (!MAP_TILE_IS_SAME_LEVEL(m, 1) || (
973  OBJECT_VALID(msp_pl->map_info, msp_pl->map_info_count) &&
974  OBJECT_VALID(msp->map_info, msp->map_info_count) &&
977  MSP_EXTRA_IS_BALCONY) && (!(msp_pl->extra_flags &
979  msp_pl->map_info == msp->map_info))) {
980  draw_up = 0;
981  }
982 
983  packet_layer = packet_new(0, 0, 128);
984  num_layers = 0;
985 
986  /* Go through the visible layers. */
987  for (layer = LAYER_FLOOR; layer <= NUM_LAYERS; layer++) {
988  if (!override_rendering) {
989  tiled_depth = 0;
990  tiled_dir = TILED_UP;
991  }
992 
993  tiled = m;
994 
995  for (int sub_layer_tmp = 0; sub_layer_tmp < NUM_SUB_LAYERS;
996  sub_layer_tmp++) {
997  if (override_rendering) {
998  sub_layer = sub_layer_tmp;
999  } else {
1000  sub_layer = NUM_SUB_LAYERS - 1 - sub_layer_tmp;
1001  }
1002 
1003  tmp = NULL;
1004  priority = 0;
1005  is_building_wall = 0;
1006  tiled_z = 0;
1007  /* Force drawing of double faces for walls and such if we're
1008  * sending the upper floors of a building. */
1009  force_draw_double = draw_up;
1010 
1011  if (sub_layer != 0 && tiled != NULL &&
1012  !override_rendering) {
1013  tiled = get_map_from_tiled(tiled, tiled_dir);
1014 
1015  if (tiled == NULL && tiled_dir == TILED_UP) {
1016  tiled_depth = 0;
1017  tiled_dir = TILED_DOWN;
1018  tiled = get_map_from_tiled(m, tiled_dir);
1019  }
1020 
1021  if (tiled != NULL && !MAP_TILE_IS_SAME_LEVEL(m,
1022  tiled_depth + (tiled_dir == TILED_UP ?
1023  1 : -1))) {
1024  tiled = NULL;
1025  }
1026 
1027  if (tiled != NULL && (draw_up ||
1028  tiled_dir == TILED_DOWN)) {
1029  msp_tmp = GET_MAP_SPACE_PTR(tiled, nx, ny);
1030 
1031  if (layer == LAYER_EFFECT) {
1032  tmp = GET_MAP_SPACE_LAYER(msp_tmp, LAYER_WALL,
1033  0);
1034  }
1035 
1036  if (tmp != NULL && layer == LAYER_EFFECT &&
1037  tmp->type != WALL && tmp->type != DOOR) {
1038  tmp = NULL;
1039  }
1040 
1041  if (tmp == NULL) {
1042  for (sub_layer2 = NUM_SUB_LAYERS - 1;
1043  sub_layer2 >= 0; sub_layer2--) {
1044  tmp = GET_MAP_SPACE_LAYER(msp_tmp, layer,
1045  sub_layer2);
1046 
1047  if (tmp != NULL) {
1048  break;
1049  }
1050  }
1051  }
1052 
1053  tiled_depth += tiled_dir == TILED_UP ? 1 : -1;
1054  force_draw_double = 1;
1055 
1056  if (tmp != NULL && layer == LAYER_WALL &&
1057  (tmp->type == WALL || tmp->type == DOOR) &&
1058  tmp->sub_layer == 0 && (tmp->map != m ||
1059  !(msp->extra_flags &
1061  ((msp_tmp->extra_flags &
1064  QUERY_FLAG(tmp, FLAG_HIDDEN))) {
1065  tmp = NULL;
1066  }
1067 
1068  if (tmp != NULL && layer == LAYER_FLOOR &&
1069  tiled_dir == TILED_UP &&
1070  (msp_tmp->extra_flags &
1074  tmp = NULL;
1075  }
1076 
1077  if (tmp != NULL && layer == LAYER_FLOOR &&
1078  QUERY_FLAG(tmp, FLAG_HIDDEN)) {
1079  tmp = NULL;
1080  }
1081 
1082  if (tmp != NULL && tiled_dir == TILED_UP &&
1083  is_in_building && (msp_tmp->extra_flags &
1085  !(msp_pl->extra_flags &
1087  tmp = NULL;
1088  }
1089 
1090  if (tmp != NULL && (msp_tmp->extra_flags &
1094  priority = 1;
1095  }
1096  }
1097  }
1098 
1099  if (bottom_map != NULL && override_rendering) {
1100  tmp = GET_MAP_SPACE_LAYER(GET_MAP_SPACE_PTR(bottom_map,
1101  nx, ny), layer, sub_layer);
1102  }
1103 
1104  if (tmp != NULL && layer == LAYER_FLOOR) {
1105  if (tiled_dir == TILED_DOWN) {
1106  floor_z_down |= 1 << sub_layer;
1107  } else {
1108  floor_z_up |= 1 << sub_layer;
1109  }
1110  }
1111 
1112  if (tmp != NULL && (layer != LAYER_WALL ||
1113  tmp->sub_layer != 0 || override_rendering)) {
1114  tiled_z = 1;
1115 
1116  if (layer != LAYER_FLOOR) {
1117  if (tiled_dir == TILED_UP &&
1118  (floor_z_up & (1 << sub_layer))) {
1119  tiled_z = 0;
1120  } else if (layer != LAYER_EFFECT &&
1121  layer != LAYER_LIVING &&
1122  layer != LAYER_ITEM &&
1123  layer != LAYER_ITEM2 &&
1124  tiled_dir == TILED_DOWN &&
1125  (floor_z_down & (1 << sub_layer))) {
1126  tiled_z = 0;
1127  }
1128  }
1129  }
1130 
1131  if (tmp == NULL) {
1132  tmp = GET_MAP_SPACE_LAYER(msp, layer, sub_layer);
1133 
1134  if (tmp != NULL) {
1135  if (have_down) {
1136  priority = 1;
1137  }
1138  }
1139  }
1140 
1141  /* This is done so that the player image is always shown
1142  * to the player, even if they are standing on top of
1143  * another
1144  * player or monster. */
1145  if (tmp != NULL && layer == pl->layer &&
1146  sub_layer == pl->sub_layer &&
1147  pl->x == nx && pl->y == ny) {
1148  tmp = pl;
1149  }
1150 
1151  /* Still nothing, but there's a magic mirror on this tile?
1152  * */
1153  if (!tmp && mirror) {
1154  magic_mirror_struct *m_data = MMIRROR(mirror);
1155  mapstruct *mirror_map;
1156 
1157  if (m_data && (mirror_map = magic_mirror_get_map(mirror)) && !OUT_OF_MAP(mirror_map, m_data->x, m_data->y)) {
1158  tmp = GET_MAP_SPACE_LAYER(GET_MAP_SPACE_PTR(mirror_map, m_data->x, m_data->y), layer, sub_layer);
1159  }
1160  }
1161 
1162  /* If the object is invisible but the player cannot see
1163  * invisible tiles, attempt to find a different object
1164  * that is not invisible on the same layer and sub-layer. */
1165  if (tmp != NULL && QUERY_FLAG(tmp, FLAG_IS_INVISIBLE) &&
1167  for (tmp2 = tmp, tmp = NULL; tmp2 != NULL &&
1168  tmp2->layer == layer &&
1169  tmp2->sub_layer == sub_layer;
1170  tmp2 = tmp2->above) {
1171  if (!QUERY_FLAG(tmp2, FLAG_IS_INVISIBLE)) {
1172  tmp = tmp2;
1173  break;
1174  }
1175  }
1176  }
1177 
1178  if (tmp != NULL && tmp->layer != LAYER_WALL &&
1179  QUERY_FLAG(tmp, FLAG_HIDDEN)) {
1180  tmp = NULL;
1181  }
1182 
1183  /* Handle objects that are shown based on their direction
1184  * and the player's position. */
1185  if (tmp && QUERY_FLAG(tmp, FLAG_DRAW_DIRECTION)) {
1186  /* If the object is dir [0124568] and not in the top
1187  * or right quadrant or on the central square, do not
1188  * show it. */
1189  if ((!tmp->direction || tmp->direction == NORTH || tmp->direction == NORTHEAST || tmp->direction == SOUTHEAST || tmp->direction == SOUTH || tmp->direction == SOUTHWEST || tmp->direction == NORTHWEST) && !((ax <= CONTR(pl)->cs->mapx_2) && (ay <= CONTR(pl)->cs->mapy_2)) && !((ax > CONTR(pl)->cs->mapx_2) && (ay < CONTR(pl)->cs->mapy_2))) {
1190  tmp = NULL;
1191  } else if ((!tmp->direction || tmp->direction == NORTHEAST || tmp->direction == EAST || tmp->direction == SOUTHEAST || tmp->direction == SOUTHWEST || tmp->direction == WEST || tmp->direction == NORTHWEST) && !((ax <= CONTR(pl)->cs->mapx_2) && (ay <= CONTR(pl)->cs->mapy_2)) && !((ax < CONTR(pl)->cs->mapx_2) && (ay > CONTR(pl)->cs->mapy_2))) {
1192  /* If the object is dir [0234768] and not in the top
1193  * or left quadrant or on the central square, do not
1194  * show it. */
1195  tmp = NULL;
1196  }
1197  }
1198 
1199  if (tmp != NULL && (msp_tmp = GET_MAP_SPACE_PTR(tmp->map,
1200  tmp->x, tmp->y))->extra_flags &
1202  OBJECT_VALID(msp_tmp->map_info,
1203  msp_tmp->map_info_count)) {
1204  int match_x, match_y, match_x2, match_y2, match_x3,
1205  match_y3;
1206 
1207  match_x = tmp->x >= msp_tmp->map_info->x && tmp->x <=
1208  msp_tmp->map_info->x +
1209  msp_tmp->map_info->stats.hp;
1210  match_y = tmp->y >= msp_tmp->map_info->y && tmp->y <=
1211  msp_tmp->map_info->y +
1212  msp_tmp->map_info->stats.sp;
1213  match_x2 = tmp->x == msp_tmp->map_info->x +
1214  msp_tmp->map_info->stats.hp;
1215  match_y2 = tmp->y == msp_tmp->map_info->y +
1216  msp_tmp->map_info->stats.sp;
1217  match_x3 = tmp->x == msp_tmp->map_info->x;
1218  match_y3 = tmp->y == msp_tmp->map_info->y;
1219 
1220  if (match_x == match_y2 || match_y == match_x2 ||
1221  match_x == match_y3 || match_y == match_x3) {
1222  is_building_wall = 1;
1223  }
1224 
1225  if (is_building_wall) {
1226  int idx;
1227  mapstruct *m2;
1228  int x2, y2;
1229 
1230  for (idx = 1; idx <= SIZEOFFREE1; idx++) {
1231  x2 = tmp->x + freearr_x[idx];
1232  y2 = tmp->y + freearr_y[idx];
1233  m2 = get_map_from_coord2(tmp->map, &x2, &y2);
1234 
1235  if (m2 == NULL) {
1236  break;
1237  }
1238 
1239  msp_tmp = GET_MAP_SPACE_PTR(m2, x2, y2);
1240 
1241  if (!(msp_tmp->extra_flags &
1243  msp_tmp->extra_flags &
1245  break;
1246  }
1247  }
1248 
1249  if (idx > SIZEOFFREE1) {
1250  is_building_wall = 0;
1251  }
1252  }
1253  }
1254 
1255  if (tmp != NULL && blocksview && tmp->map == m &&
1256  (layer != LAYER_FLOOR || !is_building_wall) &&
1257  ((layer != LAYER_WALL && tmp->type != WALL) ||
1258  !is_building_wall) && (layer != LAYER_EFFECT ||
1259  sub_layer == 0) && !(GET_MAP_SPACE_PTR(tmp->map,
1260  tmp->x, tmp->y)->extra_flags &
1262  tmp = NULL;
1263  }
1264 
1265  if (tmp != NULL && ((tiled_depth > 0 && is_in_building) ||
1266  blocksview || (tiled_depth < 0 && GET_MAP_SPACE_PTR(
1267  tmp->map, tmp->x, tmp->y)->map_info != NULL &&
1268  QUERY_FLAG(GET_MAP_SPACE_PTR(tmp->map, tmp->x,
1269  tmp->y)->map_info, FLAG_CURSED))) &&
1270  !QUERY_FLAG(tmp, FLAG_HIDDEN) &&
1271  !(GET_MAP_SPACE_PTR(tmp->map, tmp->x,
1272  tmp->y)->extra_flags & (MSP_EXTRA_IS_BUILDING |
1274  tmp = NULL;
1275  }
1276 
1277  if (tmp != NULL && tiled_depth != 0 && !is_building_wall &&
1278  (tmp->type == WALL || tmp->type == DOOR) &&
1279  layer == LAYER_EFFECT && sub_layer != 0 &&
1280  !QUERY_FLAG(tmp, FLAG_HIDDEN) &&
1281  !(GET_MAP_SPACE_PTR(tmp->map, tmp->x,
1282  tmp->y)->extra_flags & MSP_EXTRA_IS_BALCONY) &&
1283  !(msp->extra_flags & MSP_EXTRA_IS_OVERLOOK)) {
1284  tmp = NULL;
1285  }
1286 
1287  if (tmp != NULL && layer != LAYER_EFFECT &&
1288  sub_layer != 0 && (!is_building_wall ||
1289  (tmp->type != WALL && tmp->type != DOOR)) &&
1290  (tmp->type != FLOOR || !is_building_wall) &&
1291  tmp->map != m && (GET_MAP_SPACE_PTR(tmp->map,
1292  tmp->x, tmp->y)->extra_flags &
1296  tmp = NULL;
1297  }
1298 
1299  if (tmp != NULL && (!dark_set[sub_layer] ||
1300  (layer == LAYER_EFFECT && sub_layer > 0))) {
1301  dark_set[sub_layer] = 1;
1302  dark[sub_layer] = map_get_darkness(tmp->map, tmp->x,
1303  tmp->y, NULL);
1304 
1305  if (CONTR(pl)->tli) {
1306  dark[sub_layer] +=
1307  global_darkness_table[MAX_DARKNESS];
1308  }
1309 
1310  if (dark[sub_layer] < 100) {
1311  if (QUERY_FLAG(tmp, FLAG_HIDDEN) ||
1312  special_vision & 1) {
1313  dark[sub_layer] = 100;
1314  }
1315  }
1316 
1317  msp_tmp = GET_MAP_SPACE_PTR(tmp->map, tmp->x, tmp->y);
1318 
1319  if ((tmp->map->coords[2] != 0 || !is_building_wall) &&
1320  (msp_tmp->extra_flags & (MSP_EXTRA_IS_BUILDING |
1323  msp_tmp->map_info != NULL &&
1324  msp_tmp->map_info->item_power == -1) {
1325  if (is_building_wall) {
1326  d = MAX(world_darkness,
1328  } else {
1330  }
1331 
1332  dark[sub_layer] -=
1333  global_darkness_table[world_darkness];
1334  dark[sub_layer] += global_darkness_table[d];
1335  }
1336  }
1337 
1338  if (tmp != NULL && dark[sub_layer] <= 0) {
1339  tmp = NULL;
1340  }
1341 
1342  if (tmp != NULL && dark[sub_layer] !=
1343  mp->darkness[sub_layer]) {
1344  if (sub_layer == 0) {
1345  mask |= MAP2_MASK_DARKNESS;
1346  } else {
1347  mask |= MAP2_MASK_DARKNESS_MORE;
1348  }
1349 
1350  mp->darkness[sub_layer] = dark[sub_layer];
1351  }
1352 
1353  if (tmp != NULL && tmp->map != m &&
1354  anim_type[sub_layer] == 0 && GET_MAP_RTAG(tmp->map,
1355  tmp->x, tmp->y, sub_layer) == global_round_tag) {
1356  anim_type[sub_layer] = ANIM_KILL;
1357  anim_value[sub_layer] = GET_MAP_DAMAGE(tmp->map, tmp->x,
1358  tmp->y, sub_layer);
1359  anim_num++;
1360  }
1361 
1362  if (tmp == NULL && layer == LAYER_FLOOR && sub_layer != 0) {
1363  if (tiled_dir == TILED_DOWN) {
1364  floor_z_down &= ~(1 << sub_layer);
1365  } else {
1366  floor_z_up &= ~(1 << sub_layer);
1367  }
1368  }
1369 
1370  socket_layer = NUM_LAYERS * sub_layer + layer - 1;
1371 
1372  /* Found something. */
1373  if (tmp) {
1374  int16_t face;
1375  uint8_t quick_pos = tmp->quick_pos;
1376  uint8_t flags = 0, probe_val = 0;
1377  uint32_t flags2 = 0;
1378  object *head = tmp->head ? tmp->head : tmp, *face_obj;
1379  tag_t target_object_count = 0;
1380  uint8_t anim_speed, anim_facing, anim_flags;
1381  uint8_t client_flags;
1382  int is_friend = 0;
1383 
1384  face_obj = NULL;
1385  anim_speed = anim_facing = anim_flags = 0;
1386 
1387  /* If we have a multi-arch object. */
1388  if (quick_pos) {
1389  flags |= MAP2_FLAG_MULTI;
1390 
1391  /* Tail? */
1392  if (tmp->head) {
1393  /* If true, we have sent a part of this in this
1394  * map
1395  * update before, so skip it. */
1396  if (head->update_tag == map2_count) {
1397  face = 0;
1398  } else {
1399  /* Mark this object as sent. */
1400  head->update_tag = map2_count;
1401  face_obj = head;
1402  }
1403  } else {
1404  /* Head. */
1405 
1406  if (tmp->update_tag == map2_count) {
1407  face = 0;
1408  } else {
1409  tmp->update_tag = map2_count;
1410  face_obj = tmp;
1411  }
1412  }
1413  } else {
1414  face_obj = tmp;
1415  }
1416 
1417  if (face_obj != NULL) {
1418  if (QUERY_FLAG(face_obj, FLAG_ANIMATE)) {
1419  flags |= MAP2_FLAG_ANIMATION;
1420  face = face_obj->animation_id;
1421  anim_speed = face_obj->anim_speed;
1422  anim_facing = face_obj->direction + 1;
1423  anim_flags = face_obj->anim_flags & ~ANIM_FLAG_STOP_MOVING;
1424  } else {
1425  face = face_obj->face->number;
1426  }
1427  }
1428 
1429  client_flags = GET_CLIENT_FLAGS(head);
1430 
1431  /* Player? So we want to send their name. */
1432  if (tmp->type == PLAYER) {
1433  flags |= MAP2_FLAG_NAME;
1434  }
1435 
1436  /* If our player has this object as their target, we
1437  * want to
1438  * know its HP percent. */
1439  if (head->count == CONTR(pl)->target_object_count) {
1440  flags2 |= MAP2_FLAG2_PROBE;
1441  probe_val = MAX(1, ((double) head->stats.hp / ((double) head->stats.maxhp / 100.0)));
1442  }
1443 
1444  /* Z position set? */
1445  if (head->z != 0 || tiled_z || (zadj != 0 &&
1446  tmp->map->coords[2] != m->level_min &&
1447  (layer == LAYER_FLOOR || (QUERY_FLAG(head,
1448  FLAG_HIDDEN) && sub_layer == 0)) &&
1449  !override_rendering)) {
1450  flags |= MAP2_FLAG_HEIGHT;
1451  }
1452 
1453  if (QUERY_FLAG(pl, FLAG_SEE_IN_DARK) && ((head->layer == LAYER_LIVING && dark[sub_layer] < 150) || (head->type == CONTAINER && head->sub_type == ST1_CONTAINER_CORPSE && QUERY_FLAG(head, FLAG_IS_USED_UP) && (float) head->stats.food / head->last_eat >= CORPSE_INFRAVISION_PERCENT / 100.0))) {
1454  flags |= MAP2_FLAG_INFRAVISION;
1455  }
1456 
1457  if (head->align || (mirror && mirror->align)) {
1458  flags |= MAP2_FLAG_ALIGN;
1459  }
1460 
1461  /* Draw the object twice if set, but only if it's not
1462  * in the bottom quadrant of the map. */
1463  if ((QUERY_FLAG(tmp, FLAG_DRAW_DOUBLE) && (force_draw_double || (ax < CONTR(pl)->cs->mapx_2 || ay < CONTR(pl)->cs->mapy_2))) || QUERY_FLAG(tmp, FLAG_DRAW_DOUBLE_ALWAYS)) {
1464  flags |= MAP2_FLAG_DOUBLE;
1465  }
1466 
1467  if (head->alpha) {
1468  flags2 |= MAP2_FLAG2_ALPHA;
1469  }
1470 
1471  if (head->rotate) {
1472  flags2 |= MAP2_FLAG2_ROTATE;
1473  }
1474 
1475  /* Check if the object has zoom, or check if the magic
1476  * mirror
1477  * should affect the zoom value of this layer. */
1478  if ((head->zoom_x && head->zoom_x != 100) || (head->zoom_y && head->zoom_y != 100) || (mirror && mirror->last_heal && mirror->last_heal != 100 && mirror->path_attuned & (1U << (layer - 1)))) {
1479  flags2 |= MAP2_FLAG2_ZOOM;
1480  }
1481 
1482  if (head != pl && layer == LAYER_LIVING && IS_LIVE(head)) {
1483  flags2 |= MAP2_FLAG2_TARGET;
1484  target_object_count = head->count;
1485  is_friend = is_friend_of(pl, head);
1486  }
1487 
1488  if (priority) {
1489  flags2 |= MAP2_FLAG2_PRIORITY;
1490  }
1491 
1492  if (head->type == DOOR || (layer == LAYER_LIVING &&
1493  !(GET_MAP_SPACE_PTR(head->map, head->x,
1494  head->y)->extra_flags &
1496  flags2 |= MAP2_FLAG2_SECONDPASS;
1497  }
1498 
1499  if (head->glow != NULL &&
1500  CONTR(pl)->cs->socket_version >= 1060) {
1501  flags2 |= MAP2_FLAG2_GLOW;
1502  }
1503 
1504  if (flags2) {
1505  flags |= MAP2_FLAG_MORE;
1506  }
1507 
1508  /* Damage animation? Store it for later. */
1509  if (tmp->last_damage && tmp->damage_round_tag ==
1510  global_round_tag) {
1511  if (anim_type[sub_layer] == 0) {
1512  anim_num++;
1513  }
1514 
1515  anim_type[sub_layer] = ANIM_DAMAGE;
1516  anim_value[sub_layer] = tmp->last_damage;
1517  }
1518 
1519  /* Now, check if we have cached this. */
1520  if (mp->faces[socket_layer] == face &&
1521  mp->quick_pos[socket_layer] == quick_pos &&
1522  mp->flags[socket_layer] == flags && (layer !=
1523  LAYER_LIVING || !IS_LIVE(head) || (mp->probe ==
1524  probe_val && mp->target_object_count ==
1525  target_object_count)) &&
1526  mp->anim_speed[socket_layer] == anim_speed &&
1527  mp->anim_facing[socket_layer] == anim_facing &&
1528  (layer != LAYER_LIVING ||
1529  (mp->anim_flags[sub_layer] == anim_flags &&
1530  mp->client_flags[sub_layer] == client_flags)) &&
1531  (!(flags & MAP2_FLAG_NAME) ||
1532  !CONTR(tmp)->cs->ext_title_flag) &&
1533  (!(flags2 & MAP2_FLAG2_TARGET) ||
1534  ((mp->is_friend & (1 << sub_layer)) != 0) ==
1535  is_friend)) {
1536  continue;
1537  }
1538 
1539  /* Different from cache, add it to the cache now. */
1540  mp->faces[socket_layer] = face;
1541  mp->quick_pos[socket_layer] = quick_pos;
1542  mp->flags[socket_layer] = flags;
1543  mp->anim_speed[socket_layer] = anim_speed;
1544  mp->anim_facing[socket_layer] = anim_facing;
1545 
1546  if (layer == LAYER_LIVING) {
1547  mp->anim_flags[sub_layer] = anim_flags;
1548  mp->client_flags[sub_layer] = client_flags;
1549  }
1550 
1551  if (layer == LAYER_LIVING) {
1552  mp->probe = probe_val;
1553  mp->target_object_count = target_object_count;
1554 
1555  if (flags2 & MAP2_FLAG2_TARGET) {
1556  if (is_friend) {
1557  mp->is_friend |= 1 << sub_layer;
1558  } else {
1559  mp->is_friend &= ~(1 << sub_layer);
1560  }
1561  }
1562  }
1563 
1564  if (OBJECT_IS_HIDDEN(pl, head)) {
1565  /* Update target if applicable. */
1566  if (flags2 & MAP2_FLAG2_PROBE) {
1567  CONTR(pl)->target_object = NULL;
1568  CONTR(pl)->target_object_count = 0;
1569  send_target_command(CONTR(pl));
1570  }
1571 
1572  if (mp->faces[socket_layer]) {
1573  packet_debug_data(packet_layer, 1,
1574  "Socket layer ID (clear)");
1575  packet_append_uint8(packet_layer,
1576  MAP2_LAYER_CLEAR);
1577  packet_debug_data(packet_layer, 1,
1578  "Actual socket layer");
1579  packet_append_uint8(packet_layer,
1580  socket_layer);
1581  num_layers++;
1582  }
1583 
1584  continue;
1585  }
1586 
1587  num_layers++;
1588 
1589  packet_debug_data(packet_layer, 1,
1590  "Socket layer (layer: %d, sub-layer: %d)",
1591  layer, sub_layer);
1592  packet_append_uint8(packet_layer, socket_layer);
1593  packet_debug_data(packet_layer, 2, "Face ID");
1594  packet_append_uint16(packet_layer, face);
1595  packet_debug_data(packet_layer, 2, "Client flags");
1596  packet_append_uint8(packet_layer, client_flags);
1597  packet_debug_data(packet_layer, 2, "Socket flags");
1598  packet_append_uint8(packet_layer, flags);
1599 
1600  /* Multi-arch? Add it's quick pos. */
1601  if (flags & MAP2_FLAG_MULTI) {
1602  packet_debug_data(packet_layer, 2, "Quick pos");
1603  packet_append_uint8(packet_layer, quick_pos);
1604  }
1605 
1606  /* Player name? Add the player's name, and their player
1607  * name color. */
1608  if (flags & MAP2_FLAG_NAME) {
1609  packet_debug_data(packet_layer, 2, "Player name");
1610  packet_append_string_terminated(packet_layer,
1611  CONTR(tmp)->quick_name);
1612  packet_debug_data(packet_layer, 2,
1613  "Player name color");
1614  packet_append_string_terminated(packet_layer,
1615  get_playername_color(pl, tmp));
1616  }
1617 
1618  if (flags & MAP2_FLAG_ANIMATION) {
1619  packet_debug(packet_layer, 2, "Animation\n");
1620  packet_debug_data(packet_layer, 3, "Speed");
1621  packet_append_uint8(packet_layer, anim_speed);
1622  packet_debug_data(packet_layer, 3, "Facing");
1623  packet_append_uint8(packet_layer, anim_facing);
1624  packet_debug_data(packet_layer, 3, "Flags");
1625  packet_append_uint8(packet_layer, anim_flags);
1626 
1627  if (anim_flags & ANIM_FLAG_MOVING) {
1628  packet_debug_data(packet_layer, 3, "State");
1629  packet_append_uint8(packet_layer,
1630  face_obj->state);
1631  }
1632  }
1633 
1634  /* Z position. */
1635  if (flags & MAP2_FLAG_HEIGHT) {
1636  int16_t z;
1637 
1638  z = head->z;
1639 
1640  if (tmp->map->coords[2] != m->level_min &&
1641  (layer == LAYER_FLOOR || (QUERY_FLAG(head,
1642  FLAG_HIDDEN) && sub_layer == 0)) &&
1643  !override_rendering) {
1644  z += zadj;
1645  }
1646 
1647  if (mirror && mirror->last_eat) {
1648  z += mirror->last_eat;
1649  }
1650 
1651  if (tiled_z) {
1652  z += 46 * tiled_depth;
1653 
1654  if (layer != LAYER_FLOOR &&
1655  (layer != LAYER_WALL ||
1656  !override_rendering)) {
1657  if (tiled_depth < 0) {
1658  z += MIN(zadj, 46 * -tiled_depth);
1659  } else {
1660  z += zadj;
1661  }
1662  }
1663  }
1664 
1665  packet_debug_data(packet_layer, 2, "Z");
1666  packet_append_int16(packet_layer, z);
1667  }
1668 
1669  if (flags & MAP2_FLAG_ALIGN) {
1670  packet_debug_data(packet_layer, 2, "Align");
1671 
1672  if (mirror && mirror->align) {
1673  packet_append_int16(packet_layer, head->align + mirror->align);
1674  } else {
1675  packet_append_int16(packet_layer, head->align);
1676  }
1677  }
1678 
1679  if (flags & MAP2_FLAG_MORE) {
1680  packet_debug(packet_layer, 2, "Extended info:\n");
1681  packet_debug_data(packet_layer, 3, "Flags");
1682  packet_append_uint32(packet_layer, flags2);
1683 
1684  if (flags2 & MAP2_FLAG2_ALPHA) {
1685  packet_debug_data(packet_layer, 3, "Alpha");
1686  packet_append_uint8(packet_layer, head->alpha);
1687  }
1688 
1689  if (flags2 & MAP2_FLAG2_ROTATE) {
1690  packet_debug_data(packet_layer, 3, "Rotate");
1691  packet_append_int16(packet_layer, head->rotate);
1692  }
1693 
1694  if (flags2 & MAP2_FLAG2_ZOOM) {
1695  /* First check mirror, even if the object *does*
1696  * have custom zoom. */
1697  if (mirror && mirror->last_heal) {
1698  packet_debug_data(packet_layer, 3,
1699  "X zoom");
1700  packet_append_uint16(packet_layer,
1701  mirror->last_heal);
1702  packet_debug_data(packet_layer, 3,
1703  "Y zoom");
1704  packet_append_uint16(packet_layer,
1705  mirror->last_heal);
1706  } else {
1707  packet_debug_data(packet_layer, 3,
1708  "X zoom");
1709  packet_append_uint16(packet_layer,
1710  head->zoom_x);
1711  packet_debug_data(packet_layer, 3,
1712  "Y zoom");
1713  packet_append_uint16(packet_layer,
1714  head->zoom_y);
1715  }
1716  }
1717 
1718  if (flags2 & MAP2_FLAG2_TARGET) {
1719  packet_debug_data(packet_layer, 3,
1720  "Target object ID");
1721  packet_append_uint32(packet_layer,
1722  target_object_count);
1723  packet_debug_data(packet_layer, 3,
1724  "Target is friend");
1725  packet_append_uint8(packet_layer,
1726  is_friend);
1727  }
1728 
1729  /* Target's HP bar. */
1730  if (flags2 & MAP2_FLAG2_PROBE) {
1731  packet_debug_data(packet_layer, 3,
1732  "HP percentage");
1733  packet_append_uint8(packet_layer, probe_val);
1734  }
1735 
1736  /* Target's HP bar. */
1737  if (flags2 & MAP2_FLAG2_GLOW) {
1738  packet_debug_data(packet_layer, 3,
1739  "Glow color");
1740  packet_append_string_terminated(packet_layer,
1741  head->glow);
1742  packet_debug_data(packet_layer, 3,
1743  "Glow speed");
1744  packet_append_uint8(packet_layer,
1745  head->glow_speed);
1746  }
1747  }
1748  } else if (mp->faces[socket_layer]) {
1749  /* Didn't find anything. Now, if we have previously seen
1750  * a face on this layer, we will want the client to
1751  * clear it. */
1752  mp->faces[socket_layer] = 0;
1753  mp->quick_pos[socket_layer] = 0;
1754  mp->anim_speed[socket_layer] = 0;
1755  mp->anim_facing[socket_layer] = 0;
1756 
1757  if (layer == LAYER_LIVING) {
1758  mp->anim_flags[sub_layer] = 0;
1759  }
1760 
1761  packet_debug_data(packet_layer, 1,
1762  "Socket layer ID (clear)");
1763  packet_append_uint8(packet_layer, MAP2_LAYER_CLEAR);
1764  packet_debug_data(packet_layer, 1,
1765  "Actual socket layer");
1766  packet_append_uint8(packet_layer, socket_layer);
1767  num_layers++;
1768  }
1769  }
1770  }
1771 
1772  /* Add the mask. Any mask changes should go above this line. */
1773  packet_debug_data(packet, 0, "Tile %d,%d data, mask", ax, ay);
1774  packet_append_uint16(packet, mask);
1775 
1776  for (sub_layer = 0; sub_layer < NUM_SUB_LAYERS; sub_layer++) {
1777  if ((sub_layer == 0 && !(mask & MAP2_MASK_DARKNESS)) || (
1778  sub_layer != 0 && !(mask & MAP2_MASK_DARKNESS_MORE))) {
1779  if (!dark_set[sub_layer] && mp->darkness[sub_layer] != 0) {
1780  mp->darkness[sub_layer] = 0;
1781  }
1782 
1783  continue;
1784  }
1785 
1786  if (!dark_set[sub_layer]) {
1787  d = 0;
1788  } else if (dark[sub_layer] > 640) {
1789  d = 210;
1790  } else if (dark[sub_layer] > 320) {
1791  d = 180;
1792  } else if (dark[sub_layer] > 160) {
1793  d = 150;
1794  } else if (dark[sub_layer] > 80) {
1795  d = 120;
1796  } else if (dark[sub_layer] > 40) {
1797  d = 90;
1798  } else if (dark[sub_layer] > 20) {
1799  d = 60;
1800  } else {
1801  d = 30;
1802  }
1803 
1804  packet_debug_data(packet, 1, "Darkness (sub-layer: %d)",
1805  sub_layer);
1806  packet_append_uint8(packet, d);
1807  }
1808 
1809  packet_debug_data(packet, 1, "Number of layers");
1810  packet_append_uint8(packet, num_layers);
1811 
1812  packet_append_packet(packet, packet_layer);
1813  packet_free(packet_layer);
1814 
1815  /* Kill animations? */
1816  for (sub_layer = 0; sub_layer < NUM_SUB_LAYERS; sub_layer++) {
1817  if (GET_MAP_RTAG(m, nx, ny, sub_layer) == global_round_tag) {
1818  if (anim_type[sub_layer] == 0) {
1819  anim_num++;
1820  }
1821 
1822  anim_type[sub_layer] = ANIM_KILL;
1823  anim_value[sub_layer] = GET_MAP_DAMAGE(m, nx, ny,
1824  sub_layer);
1825  }
1826  }
1827 
1828  if (anim_num != 0) {
1829  ext_flags |= MAP2_FLAG_EXT_ANIM;
1830  }
1831 
1832  if (ext_flags == mp->ext_flags && anim_num == mp->anim_num &&
1833  process_delay != 0) {
1834  ext_flags = 0;
1835  } else {
1836  mp->ext_flags = ext_flags;
1837  mp->anim_num = anim_num;
1838  }
1839 
1840  /* Add flags for this tile. */
1841  packet_debug_data(packet, 1, "Extended tile flags");
1842  packet_append_uint8(packet, ext_flags);
1843 
1844  /* Animation? Add its type and value. */
1845  if (ext_flags & MAP2_FLAG_EXT_ANIM) {
1846  packet_debug_data(packet, 1, "Number of animations");
1847  packet_append_uint8(packet, anim_num);
1848 
1849  for (sub_layer = 0; sub_layer < NUM_SUB_LAYERS; sub_layer++) {
1850  if (anim_type[sub_layer] == 0) {
1851  continue;
1852  }
1853 
1854  packet_debug_data(packet, 1, "Animation sub-layer");
1855  packet_append_uint8(packet, sub_layer);
1856  packet_debug_data(packet, 1, "Animation type");
1857  packet_append_uint8(packet, anim_type[sub_layer]);
1858  packet_debug_data(packet, 1, "Animation value");
1859  packet_append_int16(packet, anim_value[sub_layer]);
1860  }
1861  }
1862 
1863  /* If nothing has really changed, go back to the old position
1864  * in the packet. */
1865  if (!(mask & 0x3f) && !num_layers && !ext_flags) {
1866  packet_load(packet, &packet_save_buf);
1867  }
1868 
1869  /* Set 'mirror' back to NULL, so we'll try to re-find it on another
1870  * tile. */
1871  mirror = NULL;
1872  }
1873  }
1874 
1875  /* Verify that we in fact do need to send this. */
1876  if (packet->len >= 6) {
1877  socket_send_packet(CONTR(pl)->cs, packet);
1878  } else {
1879  packet_free(packet);
1880  }
1881 
1882  if (packet_sound->len >= 1) {
1883  socket_send_packet(CONTR(pl)->cs, packet_sound);
1884  } else {
1885  packet_free(packet_sound);
1886  }
1887 }
1888 
1889 void socket_command_quest_list(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
1890 {
1891  object *quest_container, *tmp, *tmp2, *last;
1892  StringBuffer *sb;
1893  packet_struct *packet;
1894  char *cp;
1895  size_t cp_len;
1896 
1897  quest_container = pl->quest_container;
1898 
1899  if (!quest_container || !quest_container->inv) {
1900  packet = packet_new(CLIENT_CMD_BOOK, 0, 0);
1901  packet_debug_data(packet, 0, "Quest list message");
1902  packet_append_string_terminated(packet, "[title]No quests to speak of.[/title]");
1903  socket_send_packet(pl->cs, packet);
1904  return;
1905  }
1906 
1907  sb = stringbuffer_new();
1908  stringbuffer_append_string(sb, "[book]Quest List[/book][title]Incomplete quests:[/title]\n");
1909 
1910  /* First show incomplete quests */
1911  for (tmp = quest_container->inv; tmp; tmp = tmp->below) {
1912  if (tmp->type != QUEST_CONTAINER || tmp->magic == QUEST_STATUS_COMPLETED) {
1913  continue;
1914  }
1915 
1916  stringbuffer_append_printf(sb, "\n[title]%s[/title]", tmp->race);
1917 
1918  /* Find the last entry. */
1919  for (last = tmp->inv; last && last->below; last = last->below) {
1920  }
1921 
1922  /* Show the quest parts. */
1923  for (tmp2 = last; tmp2; tmp2 = tmp2->above) {
1924  stringbuffer_append_printf(sb, "\n[b]%s[/b]", tmp2->race);
1925 
1926  if (tmp2->msg) {
1927  stringbuffer_append_printf(sb, ": %s", tmp2->msg);
1928 
1929  if (tmp2->magic == QUEST_STATUS_COMPLETED) {
1930  stringbuffer_append_string(sb, " []done]");
1931  } else if (tmp2->magic == QUEST_STATUS_FAILED) {
1932  stringbuffer_append_string(sb, " []failed]");
1933  }
1934  }
1935 
1936  switch (tmp2->sub_type) {
1937  case QUEST_TYPE_KILL:
1938  stringbuffer_append_printf(sb, "\n[x=10]Status: %d/%d", MIN(tmp2->last_sp, tmp2->last_grace), tmp2->last_grace);
1939  break;
1940  }
1941  }
1942 
1943  stringbuffer_append_string(sb, "\n");
1944  }
1945 
1946  stringbuffer_append_string(sb, "[p]\n[title]Completed quests:[/title]\n");
1947 
1948  /* Now show completed quests */
1949  for (tmp = quest_container->inv; tmp; tmp = tmp->below) {
1950  if (tmp->type != QUEST_CONTAINER || tmp->magic != QUEST_STATUS_COMPLETED) {
1951  continue;
1952  }
1953 
1954  stringbuffer_append_printf(sb, "\n[title]%s[/title]", tmp->race);
1955  }
1956 
1957  cp_len = stringbuffer_length(sb);
1958  cp = stringbuffer_finish(sb);
1959 
1960  packet = packet_new(CLIENT_CMD_BOOK, 0, 0);
1961  packet_debug_data(packet, 0, "Quest list message");
1962  packet_append_string_len(packet, cp, cp_len);
1963  socket_send_packet(pl->cs, packet);
1964  efree(cp);
1965 }
1966 
1967 void socket_command_clear(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
1968 {
1969  ns->packet_recv_cmd->len = 0;
1970 }
1971 
1972 void socket_command_move_path(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
1973 {
1974  uint8_t x, y;
1975  mapstruct *m;
1976  int xt, yt;
1977  path_node_t *node, *tmp;
1978 
1979  x = packet_to_uint8(data, len, &pos);
1980  y = packet_to_uint8(data, len, &pos);
1981 
1982  /* Validate the passed x/y. */
1983  if (x >= pl->cs->mapx || y >= pl->cs->mapy) {
1984  LOG(PACKET, "X/Y not in range: %d, %d", x, y);
1985  return;
1986  }
1987 
1988  /* If this is the middle of the screen where the player is already,
1989  * there isn't much to do. */
1990  if (x == pl->cs->mapx_2 && y == pl->cs->mapy_2) {
1991  return;
1992  }
1993 
1994  /* The x/y we got above is from the client's map, so 0,0 is
1995  * actually topmost (northwest) corner of the map in the client,
1996  * and not 0,0 of the actual map, so we need to transform it to
1997  * actual map coordinates. */
1998  xt = pl->ob->x + (x - pl->cs->mapx / 2);
1999  yt = pl->ob->y + (y - pl->cs->mapy / 2);
2000  m = get_map_from_coord(pl->ob->map, &xt, &yt);
2001 
2002  /* Invalid x/y. */
2003  if (!m) {
2004  return;
2005  }
2006 
2007  /* Find and compress the path to the destination. */
2008  node = path_compress(path_find(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, m, xt, yt, NULL));
2009 
2010  /* No path available. */
2011  if (!node) {
2012  return;
2013  }
2014 
2015  /* Clear any previously queued paths. */
2016  player_path_clear(pl);
2017 
2018  /* 'node' now actually points to where the player is standing, so
2019  * skip that. */
2020  if (node->next) {
2021  for (tmp = node->next; tmp; tmp = tmp->next) {
2022  player_path_add(pl, tmp->map, tmp->x, tmp->y);
2023  }
2024  }
2025 
2026  /* The last x,y where we wanted to move is not included in the
2027  * above paths finding, so we have to add it manually. */
2028  player_path_add(pl, m, xt, yt);
2029 }
2030 
2031 void socket_command_fire(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2032 {
2033  int dir;
2034  tag_t tag;
2035  object *tmp;
2036  double skill_time, delay;
2037 
2038  dir = packet_to_uint8(data, len, &pos);
2039  dir = MAX(0, MIN(dir, 8));
2040  tag = packet_to_uint32(data, len, &pos);
2041 
2042  if (tag) {
2043  if (pl->equipment[PLAYER_EQUIP_WEAPON_RANGED] && pl->equipment[PLAYER_EQUIP_WEAPON_RANGED]->count == tag) {
2044  tmp = pl->equipment[PLAYER_EQUIP_WEAPON_RANGED];
2045  } else {
2046  for (tmp = pl->ob->inv; tmp; tmp = tmp->below) {
2047  if (tmp->count == tag && (tmp->type == SPELL || tmp->type == SKILL)) {
2048  break;
2049  }
2050  }
2051  }
2052  } else {
2053  tmp = pl->equipment[PLAYER_EQUIP_WEAPON_RANGED];
2054 
2055  if (!tmp && pl->equipment[PLAYER_EQUIP_AMMO] && QUERY_FLAG(pl->equipment[PLAYER_EQUIP_AMMO], FLAG_IS_THROWN)) {
2056  tmp = pl->equipment[PLAYER_EQUIP_WEAPON];
2057  }
2058  }
2059 
2060  if (!tmp) {
2061  return;
2062  }
2063 
2064  if (!check_skill_to_fire(pl->ob, tmp)) {
2065  return;
2066  }
2067 
2068  if (pl->action_attack > global_round_tag) {
2069  return;
2070  }
2071 
2072  skill_time = skills[pl->ob->chosen_skill->stats.sp].time;
2073  delay = 0;
2074 
2075  object_ranged_fire(tmp, pl->ob, dir, &delay);
2076 
2077  if (skill_time > 1.0) {
2078  skill_time -= (SK_level(pl->ob) / 10.0 / 3.0) * 0.1;
2079 
2080  if (skill_time < 1.0) {
2081  skill_time = 1.0;
2082  }
2083  }
2084 
2085  pl->action_attack = global_round_tag + skill_time + delay;
2086 
2087  pl->action_timer = (float) (pl->action_attack - global_round_tag) / MAX_TICKS;
2088  pl->last_action_timer = 0;
2089 }
2090 
2091 void socket_command_keepalive(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2092 {
2093  ns->keepalive = 0;
2094 
2095  if (len == pos) {
2096  return;
2097  }
2098 
2099  uint32_t id = packet_to_uint32(data, len, &pos);
2100 
2101  packet_struct *packet = packet_new(CLIENT_CMD_KEEPALIVE, 20, 0);
2102  packet_enable_ndelay(packet);
2103  packet_debug_data(packet, 0, "Keepalive ID");
2104  packet_append_uint32(packet, id);
2105  socket_send_packet(ns, packet);
2106 }
2107 
2108 void socket_command_move(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2109 {
2110  uint8_t dir, run_on;
2111 
2112  dir = packet_to_uint8(data, len, &pos);
2113  run_on = packet_to_uint8(data, len, &pos);
2114 
2115  if (dir > 8) {
2116  LOG(PACKET, "%s: Invalid dir: %d", socket_get_str(ns->sc), dir);
2117  return;
2118  }
2119 
2120  if (run_on > 1) {
2121  LOG(PACKET, "%s: Invalid run_on: %d", socket_get_str(ns->sc), run_on);
2122  return;
2123  }
2124 
2125  if (run_on == 1 && dir == 0) {
2126  LOG(PACKET, "%s: run_on is 1 but dir is 0", socket_get_str(ns->sc));
2127  return;
2128  }
2129 
2130  pl->run_on = run_on;
2131 
2132  if (dir != 0) {
2133  pl->run_on_dir = dir - 1;
2134  pl->ob->speed_left -= 1.0;
2135  move_object(pl->ob, dir);
2136  }
2137 }
2138 
2145 {
2146  packet_struct *packet;
2147 
2148  if (!pl->ob->map) {
2149  LOG(PACKET, "Received target command while not playing.");
2150  return;
2151  }
2152 
2153  packet = packet_new(CLIENT_CMD_TARGET, 64, 64);
2154  packet_enable_ndelay(packet);
2155 
2156  pl->ob->enemy = NULL;
2157  pl->ob->enemy_count = 0;
2158 
2159  if (!pl->target_object || pl->target_object == pl->ob || !OBJECT_VALID(pl->target_object, pl->target_object_count) || IS_INVISIBLE(pl->target_object, pl->ob)) {
2160  packet_debug_data(packet, 0, "Target command type");
2161  packet_append_uint8(packet, CMD_TARGET_SELF);
2162  packet_debug_data(packet, 0, "Color");
2163  packet_append_string_terminated(packet, COLOR_YELLOW);
2164  packet_debug_data(packet, 0, "Target name");
2165  packet_append_string_terminated(packet, pl->ob->name);
2166 
2167  pl->target_object = pl->ob;
2168  pl->target_object_count = 0;
2169  } else {
2170  packet_debug_data(packet, 0, "Target command type");
2171 
2172  if (is_friend_of(pl->target_object, pl->ob)) {
2173  if (pl->target_object->type == PLAYER) {
2174  packet_append_uint8(packet, CMD_TARGET_FRIEND);
2175  } else {
2176  packet_append_uint8(packet, CMD_TARGET_NEUTRAL);
2177  }
2178  } else {
2179  packet_append_uint8(packet, CMD_TARGET_ENEMY);
2180 
2181  pl->ob->enemy = pl->target_object;
2182  pl->ob->enemy_count = pl->target_object_count;
2183  }
2184 
2185  packet_debug_data(packet, 0, "Color");
2186 
2187  if (pl->target_object->level < level_color[pl->ob->level].yellow) {
2188  if (pl->target_object->level < level_color[pl->ob->level].green) {
2189  packet_append_string_terminated(packet, COLOR_GRAY);
2190  } else {
2191  if (pl->target_object->level < level_color[pl->ob->level].blue) {
2192  packet_append_string_terminated(packet, COLOR_GREEN);
2193  } else {
2194  packet_append_string_terminated(packet, COLOR_BLUE);
2195  }
2196  }
2197  } else {
2198  if (pl->target_object->level >= level_color[pl->ob->level].purple) {
2199  packet_append_string_terminated(packet, COLOR_PURPLE);
2200  } else if (pl->target_object->level >= level_color[pl->ob->level].red) {
2201  packet_append_string_terminated(packet, COLOR_RED);
2202  } else if (pl->target_object->level >= level_color[pl->ob->level].orange) {
2203  packet_append_string_terminated(packet, COLOR_ORANGE);
2204  } else {
2205  packet_append_string_terminated(packet, COLOR_YELLOW);
2206  }
2207  }
2208 
2209  packet_debug_data(packet, 0, "Target name");
2210 
2211  if (pl->tgm) {
2212  char buf[MAX_BUF];
2213 
2214  snprintf(buf, sizeof(buf), "%s (lvl %d)", pl->target_object->name, pl->target_object->level);
2215  packet_append_string_terminated(packet, buf);
2216  } else {
2217  packet_append_string_terminated(packet, pl->target_object->name);
2218  }
2219  }
2220 
2221  packet_debug_data(packet, 0, "Combat mode");
2222  packet_append_uint8(packet, pl->combat);
2223  packet_debug_data(packet, 0, "Combat force mode");
2224  packet_append_uint8(packet, pl->combat_force);
2225 
2226  socket_send_packet(pl->cs, packet);
2227 }
2228 
2229 void socket_command_account(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2230 {
2231  uint8_t type;
2232 
2233  type = packet_to_uint8(data, len, &pos);
2234 
2235  if (type == CMD_ACCOUNT_LOGIN) {
2236  char name[MAX_BUF], password[MAX_BUF];
2237 
2238  packet_to_string(data, len, &pos, name, sizeof(name));
2239  packet_to_string(data, len, &pos, password, sizeof(password));
2240 
2241  if (*name == '\0' || *password == '\0' || string_contains_other(name, settings.allowed_chars[ALLOWED_CHARS_ACCOUNT]) || string_contains_other(password, settings.allowed_chars[ALLOWED_CHARS_PASSWORD])) {
2242  LOG(PACKET, "Received invalid data in account login command.");
2243  return;
2244  }
2245 
2246  account_login(ns, name, password);
2247  } else if (type == CMD_ACCOUNT_REGISTER) {
2248  char name[MAX_BUF], password[MAX_BUF], password2[MAX_BUF];
2249 
2250  packet_to_string(data, len, &pos, name, sizeof(name));
2251  packet_to_string(data, len, &pos, password, sizeof(password));
2252  packet_to_string(data, len, &pos, password2, sizeof(password2));
2253 
2254  account_register(ns, name, password, password2);
2255  } else if (type == CMD_ACCOUNT_LOGIN_CHAR) {
2256  char name[MAX_BUF];
2257 
2258  packet_to_string(data, len, &pos, name, sizeof(name));
2259 
2260  account_login_char(ns, name);
2261  } else if (type == CMD_ACCOUNT_NEW_CHAR) {
2262  char name[MAX_BUF], archname[MAX_BUF];
2263 
2264  packet_to_string(data, len, &pos, name, sizeof(name));
2265  packet_to_string(data, len, &pos, archname, sizeof(archname));
2266 
2267  account_new_char(ns, name, archname);
2268  } else if (type == CMD_ACCOUNT_PSWD) {
2269  char password[MAX_BUF], password_new[MAX_BUF], password_new2[MAX_BUF];
2270 
2271  packet_to_string(data, len, &pos, password, sizeof(password));
2272  packet_to_string(data, len, &pos, password_new, sizeof(password_new));
2273  packet_to_string(data, len, &pos, password_new2, sizeof(password_new2));
2274 
2275  account_password_change(ns, password, password_new, password_new2);
2276  } else {
2277  LOG(PACKET, "Invalid type: %d", type);
2278  }
2279 }
2280 
2287 {
2288  int i;
2289 
2290  snprintf(pl->quick_name, sizeof(pl->quick_name), "%s", pl->ob->name);
2291 
2292  for (i = 0; i < pl->num_cmd_permissions; i++) {
2293  if (pl->cmd_permissions[i] && string_startswith(pl->cmd_permissions[i], "[") && string_endswith(pl->cmd_permissions[i], "]")) {
2294  snprintfcat(pl->quick_name, sizeof(pl->quick_name), " %s",
2295  pl->cmd_permissions[i]);
2296  }
2297  }
2298 
2299  if (pl->afk) {
2300  snprintfcat(pl->quick_name, sizeof(pl->quick_name), " [AFK]");
2301  }
2302 }
2303 
2304 void socket_command_target(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2305 {
2306  uint8_t type;
2307 
2308  type = packet_to_uint8(data, len, &pos);
2309 
2310  if (type == CMD_TARGET_MAPXY) {
2311  uint8_t x, y;
2312  uint32_t count, target_object_count;
2313  int i, xt, yt;
2314  mapstruct *m;
2315  object *tmp;
2316 
2317  x = packet_to_uint8(data, len, &pos);
2318  y = packet_to_uint8(data, len, &pos);
2319  count = packet_to_uint32(data, len, &pos);
2320 
2321  /* Validate the passed x/y. */
2322  if (x >= pl->cs->mapx || y >= pl->cs->mapy) {
2323  LOG(PACKET, "Invalid X/Y: %d, %d", x, y);
2324  return;
2325  }
2326 
2327  target_object_count = pl->target_object_count;
2328  pl->target_object = NULL;
2329  pl->target_object_count = 0;
2330 
2331  for (i = 0; i <= SIZEOFFREE1 && !pl->target_object_count; i++) {
2332  /* Check whether we are still in range of the player's
2333  * viewport, and whether the player can see the square. */
2334  if (x + freearr_x[i] < 0 || x + freearr_x[i] >= pl->cs->mapx || y + freearr_y[i] < 0 || y + freearr_y[i] >= pl->cs->mapy || pl->blocked_los[x + freearr_x[i]][y + freearr_y[i]] > BLOCKED_LOS_BLOCKSVIEW) {
2335  continue;
2336  }
2337 
2338  /* The x/y we got above is from the client's map, so 0,0 is
2339  * actually topmost (northwest) corner of the map in the client,
2340  * and not 0,0 of the actual map, so we need to transform it to
2341  * actual map coordinates. */
2342  xt = pl->ob->x + (x - pl->cs->mapx_2) + freearr_x[i];
2343  yt = pl->ob->y + (y - pl->cs->mapy_2) + freearr_y[i];
2344  m = get_map_from_coord(pl->ob->map, &xt, &yt);
2345 
2346  /* Invalid x/y. */
2347  if (!m) {
2348  continue;
2349  }
2350 
2351  /* Nothing alive on this spot. */
2352  if (!(GET_MAP_FLAGS(m, xt, yt) & (P_IS_MONSTER | P_IS_PLAYER))) {
2353  continue;
2354  }
2355 
2356  FOR_MAP_LAYER_BEGIN(m, xt, yt, LAYER_LIVING, -1, tmp)
2357  {
2358  tmp = HEAD(tmp);
2359 
2360  if ((!count || tmp->count == count) && IS_LIVE(tmp) && tmp != pl->ob && !IS_INVISIBLE(tmp, pl->ob) && !OBJECT_IS_HIDDEN(pl->ob, tmp)) {
2361  pl->target_object = tmp;
2362  pl->target_object_count = tmp->count;
2364  }
2365  }
2367  }
2368 
2369  if (pl->target_object_count != target_object_count) {
2370  send_target_command(pl);
2371  }
2372  } else if (type == CMD_TARGET_CLEAR) {
2373  if (pl->target_object_count) {
2374  pl->target_object = NULL;
2375  pl->target_object_count = 0;
2376  send_target_command(pl);
2377  }
2378  } else {
2379  LOG(PACKET, "Invalid type: %d", type);
2380  }
2381 }
2382 
2383 void socket_command_talk(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2384 {
2385  uint8_t type;
2386  char msg[HUGE_BUF];
2387 
2388  pl->ob->speed_left -= 1.0;
2389 
2390  type = packet_to_uint8(data, len, &pos);
2391 
2392  if (type == CMD_TALK_NPC || type == CMD_TALK_NPC_NAME) {
2393  char npc_name[MAX_BUF];
2394  int i, x, y;
2395  mapstruct *m;
2396  object *tmp, *npc;
2397 
2398  if (type == CMD_TALK_NPC_NAME) {
2399  packet_to_string(data, len, &pos, npc_name, sizeof(npc_name));
2400 
2401  if (string_isempty(npc_name)) {
2402  LOG(PACKET, "Empty NPC name.");
2403  return;
2404  }
2405  }
2406 
2407  packet_to_string(data, len, &pos, msg, sizeof(msg));
2408  player_sanitize_input(msg);
2409 
2410  if (string_isempty(msg)) {
2411  LOG(PACKET, "Empty message.");
2412  return;
2413  }
2414 
2415  npc = NULL;
2416 
2417  if (type == CMD_TALK_NPC && OBJECT_VALID(pl->target_object, pl->target_object_count) && OBJECT_CAN_TALK(pl->target_object)) {
2418  for (i = 0; i <= SIZEOFFREE2; i++) {
2419  x = pl->ob->x + freearr_x[i];
2420  y = pl->ob->y + freearr_y[i];
2421  m = get_map_from_coord(pl->ob->map, &x, &y);
2422 
2423  if (!m) {
2424  continue;
2425  }
2426 
2427  if (m == pl->target_object->map && x == pl->target_object->x && y == pl->target_object->y) {
2428  npc = pl->target_object;
2429  break;
2430  }
2431  }
2432  }
2433 
2434  /* Use larger search space when trying to talk to a specific NPC. */
2435  for (i = 0; i <= (type == CMD_TALK_NPC ? SIZEOFFREE2 : SIZEOFFREE3) && !npc; i++) {
2436  x = pl->ob->x + freearr_x[i];
2437  y = pl->ob->y + freearr_y[i];
2438  m = get_map_from_coord(pl->ob->map, &x, &y);
2439 
2440  if (!m) {
2441  continue;
2442  }
2443 
2444  FOR_MAP_LAYER_BEGIN(m, x, y, LAYER_LIVING, -1, tmp)
2445  {
2446  if (OBJECT_CAN_TALK(tmp) && (type == CMD_TALK_NPC || strcmp(tmp->name, npc_name) == 0)) {
2447  npc = tmp;
2449  }
2450  }
2452  }
2453 
2454  if (npc) {
2455  LOG(CHAT, "[TALKTO] [%s] [%s] %s", pl->ob->name, npc->name, msg);
2456 
2457  if (!monster_guard_check(npc, pl->ob, msg, 0)) {
2458  talk_to_npc(pl->ob, npc, msg);
2459  }
2460  } else if (type == CMD_TALK_NPC && OBJECT_VALID(pl->target_object, pl->target_object_count) && OBJECT_CAN_TALK(pl->target_object)) {
2461  draw_info_format(COLOR_WHITE, pl->ob, "You are too far away from %s.", pl->target_object->name);
2462  } else {
2463  draw_info(COLOR_WHITE, pl->ob, "There are no NPCs that you can talk to nearby.");
2464  }
2465  } else if (type == CMD_TALK_INV || type == CMD_TALK_BELOW || type == CMD_TALK_CONTAINER) {
2466  tag_t tag;
2467  object *tmp;
2468 
2469  tag = packet_to_uint32(data, len, &pos);
2470  packet_to_string(data, len, &pos, msg, sizeof(msg));
2471  player_sanitize_input(msg);
2472 
2473  if (string_isempty(msg)) {
2474  LOG(PACKET, "Empty message.");
2475  return;
2476  }
2477 
2478  if (type == CMD_TALK_INV) {
2479  tmp = pl->ob->inv;
2480  } else if (type == CMD_TALK_BELOW) {
2481  tmp = GET_MAP_OB_LAST(pl->ob->map, pl->ob->x, pl->ob->y);
2482  } else if (type == CMD_TALK_CONTAINER && pl->container) {
2483  tmp = pl->container->inv;
2484  } else {
2485  return;
2486  }
2487 
2488  for (; tmp; tmp = tmp->below) {
2489  if (tmp->count == tag && HAS_EVENT(tmp, EVENT_SAY)) {
2490  trigger_event(EVENT_SAY, pl->ob, tmp, NULL, msg, 0, 0, 0, 0);
2491  break;
2492  }
2493  }
2494  } else if (type == CMD_TALK_CLOSE) {
2495  if (OBJECT_VALID(pl->talking_to, pl->talking_to_count)) {
2497  pl->talking_to = NULL;
2498  pl->talking_to_count = 0;
2499  }
2500  } else {
2501  LOG(PACKET, "Invalid type: %d", type);
2502  }
2503 }
2504 
2505 void socket_command_control(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
2506 {
2507  char word[MAX_BUF], app_name[MAX_BUF];
2508  uint8_t type, sub_type;
2509  packet_struct *packet;
2510 
2511  if (strcasecmp(settings.control_allowed_ips, "none") == 0) {
2512  LOG(PACKET, "Control command received but no IPs are allowed.");
2513  return;
2514  }
2515 
2516  bool ip_match = false;
2517 
2518  size_t pos2 = 0;
2519  while (string_get_word(settings.control_allowed_ips, &pos2, ',', VS(word),
2520  0)) {
2521  char *split[2];
2522  if (string_split(word, split, arraysize(split), '/') < 1) {
2523  continue;
2524  }
2525 
2526  struct sockaddr_storage addr;
2527  if (!socket_host2addr(split[0], &addr)) {
2528  continue;
2529  }
2530 
2531  unsigned short plen = socket_addr_plen(&addr);
2532  if (split[1] != NULL) {
2533  unsigned long value = strtoul(split[1], NULL, 10);
2534  if (value < plen) {
2535  plen = value;
2536  }
2537  }
2538 
2539  if (socket_cmp_addr(ns->sc, &addr, plen) == 0) {
2540  ip_match = true;
2541  break;
2542  }
2543  }
2544 
2545  if (!ip_match) {
2546  LOG(PACKET, "Received control command from unauthorized IP: %s",
2547  socket_get_str(ns->sc));
2548  return;
2549  }
2550 
2551  packet_to_string(data, len, &pos, app_name, sizeof(app_name));
2552 
2553  if (string_isempty(app_name)) {
2554  LOG(PACKET, "Received empty app_name.");
2555  return;
2556  }
2557 
2558  type = packet_to_uint8(data, len, &pos);
2559  sub_type = packet_to_uint8(data, len, &pos);
2560 
2561  switch (type) {
2562  case CMD_CONTROL_MAP:
2563  {
2564  char mappath[HUGE_BUF];
2565  shstr *mappath_sh;
2566  mapstruct *control_map;
2567 
2568  packet_to_string(data, len, &pos, mappath, sizeof(mappath));
2569 
2570  mappath_sh = add_string(mappath);
2571  control_map = has_been_loaded_sh(mappath_sh);
2572  free_string_shared(mappath_sh);
2573 
2574  /* No such map has been loaded, nothing to do. */
2575  if (control_map == NULL) {
2576  return;
2577  }
2578 
2579  switch (sub_type) {
2580  case CMD_CONTROL_MAP_RESET:
2581  {
2582  map_force_reset(control_map);
2583  return;
2584  }
2585  }
2586 
2587  break;
2588  }
2589 
2590  case CMD_CONTROL_PLAYER:
2591  {
2592  char playername[MAX_BUF];
2593  player *control_player;
2594  int ret;
2595 
2596  packet_to_string(data, len, &pos, playername, sizeof(playername));
2597 
2598  /* Attempt to find a suitable player as the controller. */
2599  if (!string_isempty(playername)) {
2600  control_player = find_player(playername);
2601  } else if (!string_isempty(settings.control_player)) {
2602  control_player = find_player(settings.control_player);
2603  } else {
2604  control_player = first_player;
2605  }
2606 
2607  /* No player has been found, return immediately. This is not an
2608  * error; no player is logged in, for example. */
2609  if (control_player == NULL) {
2610  return;
2611  }
2612 
2613  ret = 0;
2614 
2615  switch (sub_type) {
2616  case CMD_CONTROL_PLAYER_TELEPORT:
2617  {
2618  char mappath[HUGE_BUF];
2619  int16_t x, y;
2620  mapstruct *m;
2621 
2622  packet_to_string(data, len, &pos, mappath, sizeof(mappath));
2623  x = packet_to_int16(data, len, &pos);
2624  y = packet_to_int16(data, len, &pos);
2625 
2626  m = ready_map_name(mappath, NULL, 0);
2627 
2628  if (m == NULL) {
2629  LOG(ERROR, "Could not teleport player to '%s' (%d,%d): "
2630  "map could not be loaded.", mappath, x, y);
2631  return;
2632  }
2633 
2634  ret = object_enter_map(control_player->ob, NULL, m, x, y, 1);
2635  break;
2636  }
2637  }
2638 
2639  if (ret == 1) {
2640  packet = packet_new(CLIENT_CMD_CONTROL, 256, 256);
2641  packet_enable_ndelay(packet);
2642  packet_debug_data(packet, 0, "Forwarded data");
2643  packet_append_data_len(packet, data, len);
2644  socket_send_packet(control_player->cs, packet);
2645 
2646  return;
2647  }
2648 
2649  break;
2650  }
2651  }
2652 
2653  LOG(PACKET, "Unrecognised control command type: %d, sub-type: %d, "
2654  "by application: '%s'", type, sub_type, app_name);
2655 }
2656 
2657 void socket_command_combat(socket_struct *ns, player *pl, uint8_t *data,
2658  size_t len, size_t pos)
2659 {
2660  uint8_t combat = packet_to_uint8(data, len, &pos);
2661  uint8_t combat_force = packet_to_uint8(data, len, &pos);
2662 
2663  if (combat_force && !pl->combat_force) {
2664  combat = true;
2665  } else if (!combat && pl->combat) {
2666  combat_force = false;
2667  }
2668 
2669  pl->combat = combat;
2670  pl->combat_force = combat_force;
2671 
2672  send_target_command(pl);
2673 }
2674 
2680 static void
2682  player *pl,
2683  uint8_t *data,
2684  size_t len,
2685  size_t pos)
2686 {
2687  HARD_ASSERT(ns != NULL);
2688  HARD_ASSERT(pl == NULL);
2689  HARD_ASSERT(data != NULL);
2690 
2691  /* Ensure there's no bytes left. */
2692  if (pos != len) {
2693  LOG(PACKET, "Client sent malformed crypto hello command: %s",
2694  socket_get_str(ns->sc));
2695  ns->state = ST_DEAD;
2696  return;
2697  }
2698 
2699  const char *server_cert = socket_crypto_get_cert();
2700  if (server_cert == NULL) {
2701  LOG(SYSTEM, "Crypto hello received but no cert loaded: %s",
2702  socket_get_str(ns->sc));
2703  ns->state = ST_DEAD;
2704  return;
2705  }
2706 
2707  socket_crypto_t *crypto = socket_crypto_create(ns->sc);
2708 
2709  StringBuffer *sb = stringbuffer_new();
2710  packet_to_stringbuffer(data, len, &pos, sb);
2711  char *cert = stringbuffer_finish(sb);
2712  sb = stringbuffer_new();
2713  packet_to_stringbuffer(data, len, &pos, sb);
2714  char *chain = stringbuffer_finish(sb);
2715 
2716  if (*cert != '\0' && !socket_crypto_load_cert(crypto, cert, chain)) {
2717  efree(cert);
2718  efree(chain);
2719  ns->state = ST_DEAD;
2720  return;
2721  }
2722 
2723  efree(cert);
2724  efree(chain);
2725 
2726  packet_struct *packet = packet_new(CLIENT_CMD_CRYPTO, 512, 256);
2727  packet_debug_data(packet, 0, "Crypto sub-command");
2728  packet_append_uint8(packet, CMD_CRYPTO_HELLO);
2729  packet_debug_data(packet, 0, "Certificate");
2730  packet_append_string_terminated(packet, server_cert);
2731  packet_debug_data(packet, 0, "Certificate chain");
2732  const char *cert_chain = socket_crypto_get_cert_chain();
2733  packet_append_string_terminated(packet,
2734  cert_chain != NULL ? cert_chain : "");
2735  socket_send_packet(ns, packet);
2736 }
2737 
2743 static void
2745  player *pl,
2746  uint8_t *data,
2747  size_t len,
2748  size_t pos)
2749 {
2750  HARD_ASSERT(ns != NULL);
2751  HARD_ASSERT(pl == NULL);
2752  HARD_ASSERT(data != NULL);
2753 
2754  socket_crypto_t *crypto = socket_get_crypto(ns->sc);
2755  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
2756 
2757  if (pos == len) {
2758  LOG(PACKET, "Client sent malformed crypto key command: %s",
2759  socket_get_str(ns->sc));
2760  ns->state = ST_DEAD;
2761  return;
2762  }
2763 
2764  uint8_t key_len = packet_to_uint8(data, len, &pos);
2765  key_len = MIN(key_len, len - pos);
2766  /* No need to reset the IV buffer; it will be changed below anyway. */
2767  socket_crypto_set_key(crypto, data + pos, key_len, false);
2768  pos += key_len;
2769 
2770  if (pos == len) {
2771  LOG(PACKET, "Client sent malformed crypto key command: %s",
2772  socket_get_str(ns->sc));
2773  ns->state = ST_DEAD;
2774  return;
2775  }
2776 
2777  uint8_t iv_len = packet_to_uint8(data, len, &pos);
2778  iv_len = MIN(iv_len, len - pos);
2779  socket_crypto_set_iv(crypto, data + pos, iv_len);
2780  pos += iv_len;
2781 
2782  if (pos != len) {
2783  LOG(PACKET, "Client sent malformed crypto key command: %s",
2784  socket_get_str(ns->sc));
2785  ns->state = ST_DEAD;
2786  return;
2787  }
2788 
2789  const unsigned char *iv = socket_crypto_get_iv(crypto, &iv_len);
2790  if (iv == NULL) {
2791  LOG(ERROR, "IV is NULL but it was just set");
2792  ns->state = ST_DEAD;
2793  return;
2794  }
2795 
2796  packet_struct *packet = packet_new(CLIENT_CMD_CRYPTO, 64, 64);
2797  packet_debug_data(packet, 0, "Crypto sub-command");
2798  packet_append_uint8(packet, CMD_CRYPTO_KEY);
2799  packet_debug_data(packet, 0, "IV buffer");
2800  packet_append_uint8(packet, iv_len);
2801  packet_append_data_len(packet, iv, iv_len);
2802  socket_send_packet(ns, packet);
2803 }
2804 
2810 static void
2812  player *pl,
2813  uint8_t *data,
2814  size_t len,
2815  size_t pos)
2816 {
2817  HARD_ASSERT(ns != NULL);
2818  HARD_ASSERT(pl == NULL);
2819  HARD_ASSERT(data != NULL);
2820 
2821  socket_crypto_t *crypto = socket_get_crypto(ns->sc);
2822  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
2823 
2824  char name[MAX_BUF];
2825  while (packet_to_string(data, len, &pos, VS(name)) != NULL) {
2826  int nid;
2827  if (socket_crypto_curve_supported(name, &nid)) {
2828  socket_crypto_set_nid(crypto, nid);
2829 
2830  uint8_t iv_size;
2831  const unsigned char *iv = socket_crypto_gen_iv(crypto, &iv_size);
2832  if (iv == NULL) {
2833  LOG(SYSTEM, "Failed to generate IV buffer: %s",
2834  socket_get_str(ns->sc));
2835  ns->state = ST_DEAD;
2836  return;
2837  }
2838 
2839  packet_struct *packet = packet_new(CLIENT_CMD_CRYPTO, 64, 64);
2840  packet_debug_data(packet, 0, "Crypto sub-command");
2841  packet_append_uint8(packet, CMD_CRYPTO_CURVES);
2842  packet_debug_data(packet, 0, "Elliptic curve name");
2843  packet_append_string_terminated(packet, name);
2844  socket_send_packet(ns, packet);
2845 
2846  size_t pubkey_len;
2847  unsigned char *pubkey = socket_crypto_gen_pubkey(crypto,
2848  &pubkey_len);
2849  if (pubkey == NULL) {
2850  LOG(SYSTEM, "Failed to generate a public key: %s",
2851  socket_get_str(ns->sc));
2852  ns->state = ST_DEAD;
2853  return;
2854  }
2855 
2856  if (pubkey_len > INT16_MAX) {
2857  LOG(SYSTEM, "Public key too long: %s",
2858  socket_get_str(ns->sc));
2859  ns->state = ST_DEAD;
2860  efree(pubkey);
2861  return;
2862  }
2863 
2864  packet = packet_new(CLIENT_CMD_CRYPTO, 512, 0);
2865  packet_debug_data(packet, 0, "Crypto sub-command");
2866  packet_append_uint8(packet, CMD_CRYPTO_PUBKEY);
2867  packet_debug_data(packet, 0, "ECDH public key length");
2868  packet_append_uint16(packet, (uint16_t) pubkey_len);
2869  packet_debug_data(packet, 0, "ECDH public key");
2870  packet_append_data_len(packet, pubkey, pubkey_len);
2871  packet_debug_data(packet, 0, "IV buffer size");
2872  packet_append_uint8(packet, iv_size);
2873  packet_debug_data(packet, 0, "IV buffer");
2874  packet_append_data_len(packet, iv, iv_size);
2875  socket_send_packet(ns, packet);
2876  efree(pubkey);
2877  return;
2878  }
2879  }
2880 
2881  LOG(SYSTEM,
2882  "Client requested crypto but failed to provide a compatible "
2883  "crypto elliptic curve: %s",
2884  socket_get_str(ns->sc));
2885  ns->state = ST_DEAD;
2886 }
2887 
2893 static void
2895  player *pl,
2896  uint8_t *data,
2897  size_t len,
2898  size_t pos)
2899 {
2900  HARD_ASSERT(ns != NULL);
2901  HARD_ASSERT(pl == NULL);
2902  HARD_ASSERT(data != NULL);
2903 
2904  socket_crypto_t *crypto = socket_get_crypto(ns->sc);
2905  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
2906 
2907  if (len == pos) {
2908  LOG(PACKET, "Client sent malformed crypto pubkey command: %s",
2909  socket_get_str(ns->sc));
2910  ns->state = ST_DEAD;
2911  return;
2912  }
2913 
2914  uint16_t pubkey_len = packet_to_uint16(data, len, &pos);
2915  unsigned char *pubkey = data + pos;
2916  pubkey_len = MIN(pubkey_len, len - pos);
2917  pos += pubkey_len;
2918  uint8_t iv_len = packet_to_uint8(data, len, &pos);
2919  unsigned char *iv = data + pos;
2920  iv_len = MIN(iv_len, len - pos);
2921  pos += iv_len;
2922 
2923  if (!socket_crypto_derive(crypto, pubkey, pubkey_len, iv, iv_len)) {
2924  LOG(SYSTEM, "Couldn't derive shared secret key: %s",
2925  socket_get_str(ns->sc));
2926  ns->state = ST_DEAD;
2927  return;
2928  }
2929 
2930  if (len != pos) {
2931  LOG(PACKET, "Client sent malformed crypto pubkey command: %s",
2932  socket_get_str(ns->sc));
2933  ns->state = ST_DEAD;
2934  return;
2935  }
2936 }
2937 
2943 static void
2945  player *pl,
2946  uint8_t *data,
2947  size_t len,
2948  size_t pos)
2949 {
2950  HARD_ASSERT(ns != NULL);
2951  HARD_ASSERT(pl == NULL);
2952  HARD_ASSERT(data != NULL);
2953 
2954  socket_crypto_t *crypto = socket_get_crypto(ns->sc);
2955  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
2956 
2957  if (len == pos) {
2958  LOG(PACKET, "Client sent malformed crypto secret command: %s",
2959  socket_get_str(ns->sc));
2960  ns->state = ST_DEAD;
2961  return;
2962  }
2963 
2964  uint8_t secret_len = packet_to_uint8(data, len, &pos);
2965  secret_len = MIN(secret_len, len - pos);
2966 
2967  if (!socket_crypto_set_secret(crypto, data + pos, secret_len)) {
2968  LOG(PACKET, "Client sent malformed crypto secret command: %s",
2969  socket_get_str(ns->sc));
2970  ns->state = ST_DEAD;
2971  return;
2972  }
2973 
2974  pos += secret_len;
2975 
2976  if (len != pos) {
2977  LOG(PACKET, "Client sent malformed crypto secret command: %s",
2978  socket_get_str(ns->sc));
2979  ns->state = ST_DEAD;
2980  return;
2981  }
2982 
2983  const unsigned char *secret = socket_crypto_create_secret(crypto,
2984  &secret_len);
2985  if (secret == NULL) {
2986  LOG(ERROR, "Failed to generate a secret");
2987  ns->state = ST_DEAD;
2988  return;
2989  }
2990 
2991  packet_struct *packet = packet_new(CLIENT_CMD_CRYPTO, 32, 0);
2992  packet_debug_data(packet, 0, "Crypto sub-command");
2993  packet_append_uint8(packet, CMD_CRYPTO_SECRET);
2994  packet_debug_data(packet, 0, "Secret salt length");
2995  packet_append_uint8(packet, secret_len);
2996  packet_append_data_len(packet, secret, secret_len);
2997  socket_send_packet(ns, packet);
2998 }
2999 
3005 static void
3007  player *pl,
3008  uint8_t *data,
3009  size_t len,
3010  size_t pos)
3011 {
3012  HARD_ASSERT(ns != NULL);
3013  HARD_ASSERT(pl == NULL);
3014  HARD_ASSERT(data != NULL);
3015 
3016  socket_crypto_t *crypto = socket_get_crypto(ns->sc);
3017  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
3018 
3019  if (len != pos) {
3020  LOG(PACKET, "Client sent malformed crypto secret command: %s",
3021  socket_get_str(ns->sc));
3022  ns->state = ST_DEAD;
3023  return;
3024  }
3025 
3026  packet_struct *packet = packet_new(CLIENT_CMD_CRYPTO, 8, 0);
3027  packet_append_uint8(packet, CMD_CRYPTO_DONE);
3028  socket_send_packet(ns, packet);
3029 
3030  if (!socket_crypto_set_done(crypto)) {
3031  /* Logging already done */
3032  ns->state = ST_DEAD;
3033  return;
3034  }
3035 
3036  LOG(SYSTEM, "Connection: established a secure channel with %s",
3037  socket_get_str(ns->sc));
3038 }
3039 
3045 void
3047  player *pl,
3048  uint8_t *data,
3049  size_t len,
3050  size_t pos)
3051 {
3052  HARD_ASSERT(ns != NULL);
3053  HARD_ASSERT(data != NULL);
3054 
3055  uint8_t type = packet_to_uint8(data, len, &pos);
3056  if (!socket_crypto_check_cmd(type, socket_get_crypto(ns->sc))) {
3057  LOG(PACKET, "Received crypto command in invalid state: %u", type);
3058  ns->state = ST_DEAD;
3059  return;
3060  }
3061 
3062  /* Don't let clients initiate a handshake when they're already logged in.
3063  * In practice, this should never happen. */
3064  if (pl != NULL) {
3065  LOG(PACKET, "Received while logged in: %s", pl->ob->name);
3066  ns->state = ST_DEAD;
3067  return;
3068  }
3069 
3070  switch (type) {
3071  case CMD_CRYPTO_HELLO:
3072  socket_crypto_hello(ns, pl, data, len, pos);
3073  break;
3074 
3075  case CMD_CRYPTO_KEY:
3076  socket_crypto_key(ns, pl, data, len, pos);
3077  break;
3078 
3079  case CMD_CRYPTO_CURVES:
3080  socket_crypto_curves(ns, pl, data, len, pos);
3081  break;
3082 
3083  case CMD_CRYPTO_PUBKEY:
3084  socket_crypto_pubkey(ns, pl, data, len, pos);
3085  break;
3086 
3087  case CMD_CRYPTO_SECRET:
3088  socket_crypto_secret(ns, pl, data, len, pos);
3089  break;
3090 
3091  case CMD_CRYPTO_DONE:
3092  socket_crypto_done(ns, pl, data, len, pos);
3093  break;
3094 
3095  default:
3096  LOG(PACKET, "Received unknown security sub-command: %" PRIu8, type);
3097  ns->state = ST_DEAD;
3098  break;
3099  }
3100 }
3101 
3107 void
3109  player *pl,
3110  uint8_t *data,
3111  size_t len,
3112  size_t pos)
3113 {
3114  HARD_ASSERT(ns != NULL);
3115  HARD_ASSERT(data != NULL);
3116 
3117  char resource_name[HUGE_BUF];
3118  packet_to_string(data, len, &pos, VS(resource_name));
3119 
3120  if (string_isempty(resource_name)) {
3121  LOG(PACKET, "Empty resource name from client %s",
3122  socket_get_str(ns->sc));
3123  return;
3124  }
3125 
3126  resource_t *resource = resources_find(resource_name);
3127  if (resource == NULL) {
3128  LOG(DEVEL, "Invalid resource '%s' from client %s",
3129  resource_name,
3130  socket_get_str(ns->sc));
3131  return;
3132  }
3133 
3134  resources_send(resource, ns);
3135 }
#define BLOCKED_LOS_BLOCKED
Definition: define.h:95
socket_t * sc
Definition: newserver.h:109
void generate_quick_name(player *pl)
Definition: request.c:2286
resource_t * resources_find(const char *name)
Definition: resources.c:162
static void socket_crypto_key(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:2744
#define CORPSE_INFRAVISION_PERCENT
Definition: object.h:646
static void socket_crypto_pubkey(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:2894
tag_t target_object_count
Definition: newserver.h:79
#define TILED_NUM_DIR
Definition: global.h:210
int16_t ac
Definition: living.h:93
#define MAP_IN_MEMORY
Definition: map.h:170
shstr * name
Definition: map.h:553
uint8_t item_level
Definition: object.h:375
int16_t zoom_x
Definition: object.h:451
uint8_t tgm
Definition: player.h:528
static void socket_crypto_done(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:3006
const char * race
Definition: object.h:174
double weapon_speed
Definition: object.h:475
#define FLAG_CURSED
Definition: define.h:1154
int purple
Definition: exp.h:55
#define BLOCKED_LOS_BLOCKSVIEW
Definition: define.h:93
uint16_t last_gen_hp
Definition: player.h:487
uint8_t is_friend
Friendly state cache.
Definition: newserver.h:87
tag_t enemy_count
Definition: object.h:216
#define QUEST_CONTAINER
Definition: define.h:489
path_node_t * path_find(object *op, mapstruct *map1, int x, int y, mapstruct *map2, int x2, int y2, path_visualizer_t **visualizer)
Definition: pathfinder.c:859
int object_get_gender(const object *op)
Definition: object.c:2877
#define SOUTH
Definition: map.h:845
int trigger_event(int event_type, object *const activator, object *const me, object *const other, const char *msg, int parm1, int parm2, int parm3, int flags)
Definition: plugins.c:510
mapstruct * get_map_from_coord2(mapstruct *m, int *x, int *y)
Definition: map.c:2000
uint8_t type
One of operation types.
Definition: sound_ambient.c:45
#define TILED_UP
Definition: global.h:203
#define MAP_WIDTH(m)
Definition: map.h:120
#define SOCKET_VERSION
Definition: config.h:181
short time
Definition: skills.h:126
#define FLAG_IS_THROWN
Definition: define.h:1170
int16_t y
Y position on the map for this node.
Definition: pathfinder.h:63
double last_weapon_speed
Definition: player.h:271
static const char * get_playername_color(object *pl, object *op)
Definition: request.c:603
#define FLAG_ANIMATE
Definition: define.h:912
shstr * path
Definition: map.h:568
double speed_left
Definition: object.h:472
#define SIZEOFFREE1
Definition: define.h:654
mapstruct * get_map_from_coord(mapstruct *m, int *x, int *y)
Definition: map.c:1869
int SK_level(object *op)
Definition: skill_util.c:470
uint32_t in_memory
Definition: map.h:627
#define map_if_clearcell()
Definition: request.c:642
int16_t last_heal
Definition: object.h:310
int blue
Definition: exp.h:43
#define BOW
Definition: define.h:174
int16_t arrow_get_wc(object *op, object *bow, object *arrow)
Definition: arrow.c:200
struct Map lastmap
Definition: newserver.h:167
unsigned int run_on
Definition: player.h:289
player * find_player(const char *plname)
Definition: player.c:96
object * arrow_find(object *op, shstr *type)
Definition: arrow.c:294
const char * slaying
Definition: object.h:180
int yellow
Definition: exp.h:46
void esrv_move_object(object *pl, tag_t to, tag_t tag, long nrof)
Definition: item.c:1039
object * ob
Definition: player.h:185
char http_url[MAX_BUF]
Definition: global.h:459
int16_t last_sp
Definition: object.h:313
#define FLAG_SEE_INVISIBLE
Definition: define.h:946
#define LAYER_FLOOR
Definition: map.h:49
#define FLAG_BLIND
Definition: define.h:884
uint32_t target_object_count
Definition: player.h:434
#define HAS_EVENT(ob, event)
Definition: plugin.h:179
int64_t exp
Definition: living.h:69
#define LAYER_ITEM
Definition: map.h:53
int height
Definition: map.h:653
uint8_t layer
Definition: object.h:405
uint8_t flags[NUM_REAL_LAYERS]
Definition: newserver.h:62
struct obj * above
Definition: object.h:120
#define MAP_BUILDING_DARKNESS_WALL
Definition: map.h:862
static int get_tiled_map_id(player *pl, struct mapdef *map)
Definition: request.c:362
uint16_t gen_client_sp
Definition: player.h:484
#define OUT_OF_MAP(M, X, Y)
Definition: map.h:240
static void socket_crypto_hello(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:2681
#define ST1_CONTAINER_CORPSE
Definition: define.h:568
#define MAP_TILE_IS_SAME_LEVEL(_m, _z)
Definition: map.h:696
#define IS_LIVE(op)
Definition: define.h:841
#define PLAYER
Definition: define.h:122
#define WEST
Definition: map.h:849
uint32_t path_attuned
Definition: object.h:255
double bow_get_ws(object *bow, object *arrow)
Definition: bow.c:144
int16_t sp
Definition: living.h:78
bool object_enter_map(object *op, object *exit, mapstruct *m, int x, int y, bool fixed_pos)
Definition: object.c:2956
uint32_t socket_version
Definition: newserver.h:130
#define MMIRROR(ob)
Definition: object.h:678
uint8_t alpha
Definition: object.h:463
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
uint32_t path_repelled
Definition: object.h:258
uint32_t afk
Definition: player.h:443
const char * region_get_longname(const region_struct *region)
Definition: region.c:309
struct obj * enemy
Definition: object.h:196
int8_t Int
Definition: living.h:112
path_node_t * path_compress(path_node_t *path)
Definition: pathfinder.c:759
int16_t arrow_get_damage(object *op, object *bow, object *arrow)
Definition: arrow.c:237
char quick_name[MAX_BUF]
Definition: player.h:156
uint32_t last_path_repelled
Definition: player.h:459
#define WALL
Definition: define.h:340
int16_t maxsp
Definition: living.h:81
int8_t Con
Definition: living.h:109
int32_t hp
Definition: living.h:72
#define FLAG_DRAW_DIRECTION
Definition: define.h:1326
double last_speed
Definition: player.h:268
uint32_t last_weight_limit
Definition: player.h:437
struct mapdef * last_update
Definition: player.h:182
uint16_t number
Definition: face.h:46
#define FLAG_SEE_IN_DARK
Definition: define.h:1198
float last_ranged_ws
Definition: player.h:449
int object_ranged_fire(object *op, object *shooter, int dir, double *delay)
unsigned char last_level
Definition: player.h:274
#define NORTH
Definition: map.h:837
#define P_BLOCKSVIEW
Definition: map.h:250
#define MSP_EXTRA_IS_BALCONY
Definition: map.h:328
struct obj * chosen_skill
Definition: object.h:210
const char * title
Definition: object.h:171
int16_t y
Definition: object.h:276
int16_t last_ranged_dam
Definition: player.h:502
int32_t maxhp
Definition: living.h:75
uint32_t path_denied
Definition: object.h:261
uint32_t sound
Definition: newserver.h:143
#define P_IS_PLAYER
Definition: map.h:256
uint8_t glow_speed
Definition: object.h:466
#define BLOCKED_LOS_IGNORE
Definition: define.h:91
#define QUEST_TYPE_KILL
Definition: define.h:1534
uint32_t update_tag
Definition: object.h:267
uint8_t sub_layer
Definition: object.h:408
uint32_t keepalive
Definition: newserver.h:177
int16_t last_ranged_wc
Definition: player.h:505
int time
Definition: spells.h:138
object * container
Definition: player.h:206
int is_friend_of(object *op, object *obj)
Definition: monster.c:1685
#define MAP_BUILDING_DARKNESS
Definition: map.h:866
#define SIZEOFFREE2
Definition: define.h:656
char * player_sanitize_input(char *str)
Definition: player.c:1311
void draw_client_map(object *pl)
Definition: request.c:426
object * map_info
Definition: map.h:345
uint8_t item_condition
Definition: object.h:369
#define EAST
Definition: map.h:841
uint16_t darkness[NUM_SUB_LAYERS]
Definition: newserver.h:53
int16_t z
Definition: object.h:286
uint8_t is_bot
Definition: newserver.h:146
void socket_command_ask_resource(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:3108
struct mapdef * map
Definition: object.h:139
uint8_t anim_num
Last number of animations sent.
Definition: newserver.h:85
Definition: newserver.h:91
shstr * bg_music
Definition: map.h:556
void resources_send(resource_t *resource, socket_struct *ns)
Definition: resources.c:182
#define FLAG_IS_INVISIBLE
Definition: define.h:888
tag_t sound_ambient_count
Definition: map.h:363
static void socket_crypto_curves(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:2811
int16_t dam
Definition: living.h:87
union @21 data
Data about the rule.
const char * name
Definition: object.h:168
uint32_t weight_limit[MAX_STAT+1]
Definition: living.c:129
#define LAYER_LIVING
Definition: map.h:59
static void copy_lastmap(socket_struct *ns, int dx, int dy)
Definition: request.c:388
shstr * tile_path[TILED_NUM]
Definition: map.h:571
#define SIZEOFFREE3
Definition: define.h:658
uint8_t quick_pos[NUM_REAL_LAYERS]
Definition: newserver.h:59
#define move_object(__op, __dir)
Definition: global.h:253
struct obj * below
Definition: object.h:114
#define CONTAINER
Definition: define.h:493
int16_t last_grace
Definition: object.h:316
struct mapdef * tile_map[TILED_NUM]
Definition: map.h:550
int16_t zoom_y
Definition: object.h:460
uint8_t last_gender
Definition: player.h:513
int orange
Definition: exp.h:49
object * target_object
Definition: player.h:188
#define FLAG_DRAW_DOUBLE
Definition: define.h:1330
int talk_to_npc(object *op, object *npc, char *txt)
Definition: monster.c:1615
char control_player[MAX_BUF]
Definition: global.h:444
#define SOUTHEAST
Definition: map.h:843
int red
Definition: exp.h:52
int flags
Definition: map.h:381
#define MAP_HEIGHT(m)
Definition: map.h:122
int8_t item_power
Definition: object.h:442
void socket_command_crypto(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:3046
int16_t align
Definition: object.h:332
#define IS_INVISIBLE(__ob_, __player_)
Definition: define.h:1356
#define EVENT_SAY
Definition: plugin.h:85
#define FLAG_IS_USED_UP
Definition: define.h:976
char allowed_chars[ALLOWED_CHARS_NUM][MAX_BUF]
Definition: global.h:429
#define NUM_LAYERS
Definition: map.h:67
#define FOR_MAP_LAYER_END
Definition: define.h:1657
double speed
Definition: object.h:469
shstr * weather
Definition: map.h:559
#define HEAD(op)
Definition: object.h:657
bool monster_guard_check(object *op, object *target, const char *msg, uint32_t distance)
int8_t last_protection[NROFATTACKS]
Definition: player.h:510
uint8_t combat
Definition: player.h:543
tag_t talking_to_count
ID of ::talking_to.
Definition: player.h:572
#define MSP_EXTRA_IS_BUILDING
Definition: map.h:326
char * map_first
Definition: map.h:487
#define OBJECT_CAN_TALK(ob)
Definition: object.h:683
uint32_t last_path_denied
Definition: player.h:464
int num_cmd_permissions
Definition: player.h:254
void player_path_clear(player *pl)
Definition: player.c:1086
static void socket_crypto_secret(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:2944
int16_t x
Definition: object.h:273
#define NUM_SUB_LAYERS
Definition: map.h:71
int pvp_area(object *attacker, object *victim)
Definition: player.c:977
void draw_client_map2(object *pl)
Definition: request.c:653
#define FOR_MAP_LAYER_BEGIN(_m, _x, _y, _layer, _sub_layer, _obj)
Definition: define.h:1630
int16_t last_eat
Definition: object.h:319
#define MAP_CLIENT_X
Definition: config.h:62
#define LAYER_ITEM2
Definition: map.h:55
#define TILED_DOWN
Definition: global.h:205
int16_t wc
Definition: living.h:90
#define FLAG_DRAW_DOUBLE_ALWAYS
Definition: define.h:1217
void send_target_command(player *pl)
Definition: request.c:2144
spell_struct spells[NROFREALSPELLS]
Definition: spellist.h:34
int world_darkness
Definition: init.c:61
uint8_t combat_force
Definition: player.h:549
#define FOR_MAP_LAYER_BREAK
Definition: define.h:1650
struct settings_struct settings
Definition: init.c:55
#define MSP_EXTRA_IS_OVERLOOK
Definition: map.h:330
#define FLAG_HIDDEN
Definition: define.h:1255
int8_t protection[NROFATTACKS]
Definition: object.h:439
living last_stats
Definition: player.h:552
#define FLOOR
Definition: define.h:324
int green
Definition: exp.h:40
int SP_level_dam_adjust(object *caster, int spell_type, bool exact)
Definition: spell_util.c:992
float last_action_timer
Definition: player.h:265
#define LAYER_EFFECT
Definition: map.h:61
#define FLAG_XRAYS
Definition: define.h:1110
struct MapCell_struct cells[MAP_CLIENT_X][MAP_CLIENT_Y]
Definition: newserver.h:93
region_struct * region
Definition: map.h:580
uint16_t last_flags
Definition: player.h:472
#define QUEST_STATUS_COMPLETED
Definition: define.h:1522
tag_t count
Definition: object.h:142
tag_t map_info_count
Definition: map.h:360
int16_t x
X position on the map for this node.
Definition: pathfinder.h:62
living stats
Definition: object.h:481
int8_t Dex
Definition: living.h:106
uint8_t ext_flags
Last ext flags.
Definition: newserver.h:81
mapstruct * map_force_reset(mapstruct *m)
Definition: map.c:2691
object * equipment[PLAYER_EQUIP_MAX]
Definition: player.h:191
socket_struct * cs
Definition: player.h:148
int freearr_x[SIZEOFFREE]
Definition: object.c:84
#define SKILL
Definition: define.h:246
uint8_t type
Definition: object.h:360
void esrv_new_player(player *pl, uint32_t weight)
Definition: request.c:337
uint8_t extra_flags
Definition: map.h:390
struct mapdef * map
Pointer to the map.
Definition: pathfinder.h:61
const char * msg
Definition: object.h:183
#define QUEST_STATUS_FAILED
Definition: define.h:1524
void update_los(object *op)
Definition: los.c:314
char * name
Definition: map.h:463
#define BLOCKED_LOS_OUT_OF_MAP
Definition: define.h:97
char control_allowed_ips[HUGE_BUF]
Definition: global.h:439
uint32_t last_path_attuned
Definition: player.h:454
void monster_data_dialogs_remove(object *op, object *activator)
Definition: monster_data.c:254
mapstruct * has_been_loaded_sh(shstr *name)
Definition: map.c:389
uint8_t probe
Definition: newserver.h:74
#define OBJECT_VALID(_ob_, _count_)
Definition: object.h:548
uint16_t last_gen_sp
Definition: player.h:490
char target_hp
Definition: player.h:218
int16_t faces[NUM_REAL_LAYERS]
Definition: newserver.h:56
int16_t coords[3]
X, Y and Z coordinates.
Definition: map.h:678
#define NORTHEAST
Definition: map.h:839
int8_t Str
Definition: living.h:103
#define DOOR
Definition: define.h:194
const region_struct * region_find_with_map(const region_struct *region)
Definition: region.c:285
void esrv_update_stats(player *pl)
Definition: request.c:187
#define SOUTHWEST
Definition: map.h:847
int8_t Pow
Definition: living.h:115
char ** cmd_permissions
Definition: player.h:168
struct obj * inv
Definition: object.h:123
#define OBJECT_IS_HIDDEN(pl, ob)
Definition: map.h:857
#define P_IS_MONSTER
Definition: map.h:258
int check_skill_to_fire(object *op, object *weapon)
Definition: skill_util.c:252
void player_path_add(player *pl, mapstruct *map, int16_t x, int16_t y)
Definition: player.c:1061
#define MAX_DARKNESS
Definition: map.h:37
mapstruct * ready_map_name(const char *name, mapstruct *originator, int flags)
Definition: map.c:1584
player * first_player
Definition: main.c:57
uint16_t gen_client_hp
Definition: player.h:481
uint32_t last_equipment[PLAYER_EQUIP_MAX]
Definition: player.h:469
int blocked_los[MAP_CLIENT_X][MAP_CLIENT_Y]
Definition: player.h:230
object * sound_ambient
Definition: map.h:348
float action_timer
Definition: player.h:262
#define NORTHWEST
Definition: map.h:851
Definition: map.h:536
struct path_node * next
Next node in a linked list.
Definition: pathfinder.h:57
int width
Definition: map.h:656
object * talking_to
Object the player is talking to.
Definition: player.h:571
New_Face * face
Definition: object.h:234
object * quest_container
Definition: player.h:215
skill_struct skills[NROFSKILLS]
Definition: skillist.h:62
int8_t level
Definition: object.h:347
int freearr_y[SIZEOFFREE]
Definition: object.c:99
mapstruct * get_map_from_tiled(mapstruct *m, int tiled)
Definition: map.c:1838
tag_t sound_ambient_count
Definition: newserver.h:45
int8_t magic
Definition: object.h:341
unsigned int run_on_dir
Definition: player.h:292
time_t last
Last successful update.
Definition: metaserver.c:47
#define LAYER_WALL
Definition: map.h:57
shstr * glow
Definition: object.h:193
mapstruct * magic_mirror_get_map(object *op)
Definition: magic_mirror.c:121
int16_t rotate
Definition: object.h:335
int16_t food
Definition: living.h:84
int8_t level_min
Minimum level offset that is part of this map.
Definition: map.h:680
#define SPELL
Definition: define.h:210
uint8_t sub_type
Definition: object.h:363