Atrinik Client  4.0
region_map.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 
32 #include <global.h>
33 #include <region_map.h>
34 #include <toolkit/string.h>
35 #include <toolkit/path.h>
36 
37 #ifndef __CPROTO__
38 
39 static UT_icd icd = {sizeof(region_map_fow_tile_t), NULL, NULL, NULL};
40 
42 static void region_map_def_load(region_map_def_t *def, const char *str);
43 static void region_map_def_free(region_map_def_t *def);
45 static void region_map_fow_create(region_map_t *region_map);
46 static void region_map_fow_free(region_map_t *region_map);
47 static void region_map_fow_reset(region_map_t *region_map);
48 
55 {
57 
58  region_map = ecalloc(1, sizeof(*region_map));
59  region_map->zoom = 100;
60  region_map->def = region_map_def_new();
61  region_map->fow = region_map_fow_new();
62 
63  return region_map;
64 }
65 
74 {
75  region_map_t *clone;
76 
77  clone = ecalloc(1, sizeof(*clone));
78  clone->zoom = 100;
79  clone->surface = SDL_DisplayFormat(region_map->surface);
80  clone->def = region_map->def;
81  clone->def->refcount++;
82  clone->fow = region_map->fow;
83  clone->fow->refcount++;
84 
85  return clone;
86 }
87 
94 {
95  HARD_ASSERT(region_map != NULL);
96  HARD_ASSERT(region_map->def != NULL);
97  HARD_ASSERT(region_map->fow != NULL);
98 
99  region_map_reset(region_map);
100  efree(region_map->def);
101  efree(region_map->fow);
102  efree(region_map);
103 }
104 
111 {
112  HARD_ASSERT(region_map != NULL);
113  HARD_ASSERT(region_map->def != NULL);
114  HARD_ASSERT(region_map->fow != NULL);
115 
116  memset(&region_map->pos, 0, sizeof(region_map->pos));
117 
118  if (region_map->request_png != NULL) {
119  curl_request_free(region_map->request_png);
120  region_map->request_png = NULL;
121  }
122 
123  if (region_map->request_def != NULL) {
124  curl_request_free(region_map->request_def);
125  region_map->request_def = NULL;
126  }
127 
128  /* The fog of war freeing makes use of region_map->surface, so it must
129  * be freed before the surface... */
130  if (--region_map->fow->refcount == 0) {
131  region_map_fow_free(region_map);
132  efree(region_map->fow);
133  }
134 
135  region_map->fow = region_map_fow_new();
136 
137  if (region_map->surface != NULL) {
138  SDL_FreeSurface(region_map->surface);
139  region_map->surface = NULL;
140  }
141 
142  if (region_map->zoomed != NULL) {
143  SDL_FreeSurface(region_map->zoomed);
144  region_map->zoomed = NULL;
145  }
146 
147  if (--region_map->def->refcount == 0) {
148  region_map_def_free(region_map->def);
149  efree(region_map->def);
150  }
151 
152  region_map->def = region_map_def_new();
153 }
154 
155 /*
156  * Updates the specified region map, resetting it and scheduling
157  * a re-download of the image and definition files.
158  * @param region_map
159  * Region map.
160  * @param region_name
161  * Region name.
162  */
163 void region_map_update(region_map_t *region_map, const char *region_name)
164 {
165  char url[HUGE_BUF], buf[HUGE_BUF], *path;
166 
167  region_map_reset(region_map);
168 
169  /* Download the image. */
170  snprintf(VS(url), "%s/client-maps/%s.png", cpl.http_url, region_name);
171  snprintf(VS(buf), "client-maps/%s.png", region_name);
172  path = file_path_server(buf);
173  region_map->request_png = curl_request_create(url,
174  CURL_PKEY_TRUST_APPLICATION);
175  curl_request_set_path(region_map->request_png, path);
176  curl_request_start_get(region_map->request_png);
177  efree(path);
178 
179  /* Download the definitions. */
180  snprintf(VS(url), "%s/client-maps/%s.def", cpl.http_url, region_name);
181  snprintf(VS(buf), "client-maps/%s.def", region_name);
182  path = file_path_server(buf);
183  region_map->request_def = curl_request_create(url,
184  CURL_PKEY_TRUST_APPLICATION);
185  curl_request_set_path(region_map->request_def, path);
186  curl_request_start_get(region_map->request_def);
187  efree(path);
188 
189  snprintf(VS(buf), "client-maps/%s.tiles", region_name);
190  region_map->fow->path = file_path_player(buf);
191 }
192 
201 {
202  SDL_Surface *img;
203  size_t i;
204 
205  HARD_ASSERT(region_map != NULL);
206 
207  if (region_map->surface != NULL) {
208  return true;
209  }
210 
211  if (region_map->request_png == NULL || region_map->request_def == NULL) {
212  return false;
213  }
214 
215  SOFT_ASSERT_RC(region_map->zoomed == NULL, false,
216  "Region map already has a zoomed surface.");
217 
218  if (curl_request_get_state(region_map->request_png) != CURL_STATE_OK) {
219  return false;
220  }
221 
222  if (curl_request_get_state(region_map->request_def) != CURL_STATE_OK) {
223  return false;
224  }
225 
226  size_t body_png_size;
227  char *body_png = curl_request_get_body(region_map->request_png,
228  &body_png_size);
229  if (body_png == NULL) {
230  return false;
231  }
232 
233  char *body_def = curl_request_get_body(region_map->request_def, NULL);
234  if (body_def == NULL) {
235  return false;
236  }
237 
238  img = IMG_Load_RW(SDL_RWFromMem(body_png, body_png_size), 1);
239  region_map->surface = SDL_DisplayFormat(img);
240  SDL_FreeSurface(img);
241 
242  region_map_pan(region_map);
243  region_map_def_load(region_map->def, body_def);
244 
245  /* Draw the labels. */
246  for (i = 0; i < region_map->def->num_labels; i++) {
247  text_show(region_map->surface, FONT_SERIF20,
248  region_map->def->labels[i].text,
249  region_map->def->labels[i].x, region_map->def->labels[i].y,
251  }
252 
253  for (i = 0; i < region_map->def->num_tooltips; i++) {
254  if (!region_map->def->tooltips[i].outline) {
255  continue;
256  }
257 
258  border_create(region_map->surface,
259  region_map->def->tooltips[i].x, region_map->def->tooltips[i].y,
260  region_map->def->tooltips[i].w, region_map->def->tooltips[i].h,
261  SDL_MapRGB(region_map->surface->format,
262  region_map->def->tooltips[i].outline_color.r,
263  region_map->def->tooltips[i].outline_color.g,
264  region_map->def->tooltips[i].outline_color.b),
265  region_map->def->tooltips[i].outline_size);
266  }
267 
268  if (region_map->fow->surface == NULL ||
269  region_map->fow->surface->w != region_map->surface->w ||
270  region_map->fow->surface->h != region_map->surface->h) {
271  region_map_fow_reset(region_map);
272  region_map_fow_create(region_map);
273  }
274 
275  curl_request_free(region_map->request_png);
276  region_map->request_png = NULL;
277 
278  curl_request_free(region_map->request_def);
279  region_map->request_def = NULL;
280 
281  minimap_redraw_flag = 1;
282 
283  return true;
284 }
285 
296  const char *map_path)
297 {
298  size_t i;
299 
300  HARD_ASSERT(region_map != NULL);
301  HARD_ASSERT(map_path != NULL);
302 
303  for (i = 0; i < region_map->def->num_maps; i++) {
304  if (strcmp(region_map->def->maps[i].path, map_path) == 0) {
305  return &region_map->def->maps[i];
306  }
307  }
308 
309  return NULL;
310 }
311 
319 SDL_Surface *region_map_surface(region_map_t *region_map)
320 {
321  HARD_ASSERT(region_map != NULL);
322  HARD_ASSERT(region_map->surface != NULL);
323 
324  if (region_map->zoomed != NULL) {
325  return region_map->zoomed;
326  }
327 
328  return region_map->surface;
329 }
330 
331 void region_map_pan(region_map_t *region_map)
332 {
334 
335  HARD_ASSERT(region_map != NULL);
336  HARD_ASSERT(region_map->surface != NULL);
337 
338  map = region_map_find_map(region_map, MapData.map_path);
339 
340  if (map != NULL) {
341  region_map->pos.x = (map->xpos + MapData.posx *
342  region_map->def->pixel_size) * (region_map->zoom / 100.0) -
343  region_map->pos.w / 2.0;
344  region_map->pos.y = (map->ypos + MapData.posy *
345  region_map->def->pixel_size) * (region_map->zoom / 100.0) -
346  region_map->pos.h / 2.0;
347  } else {
348  region_map->pos.x = region_map->surface->w / 2 - region_map->pos.w / 2;
349  region_map->pos.y = region_map->surface->h / 2 - region_map->pos.h / 2;
350  }
351 
352  surface_pan(region_map_surface(region_map), &region_map->pos);
353 }
354 
362 void region_map_resize(region_map_t *region_map, int adjust)
363 {
364  float delta;
365 
366  HARD_ASSERT(region_map != NULL);
367  HARD_ASSERT(region_map->fow != NULL);
368  SOFT_ASSERT(region_map->surface != NULL, "Region map's surface is NULL.");
369 
370  region_map->zoom += adjust;
371 
372  if (region_map->zoomed != NULL) {
373  SDL_FreeSurface(region_map->zoomed);
374  region_map->zoomed = NULL;
375  }
376 
377  if (region_map->fow_zoomed != NULL) {
378  SDL_FreeSurface(region_map->fow_zoomed);
379  region_map->fow_zoomed = NULL;
380  }
381 
382  if (region_map->zoom != 100) {
383  /* Zoom the surface. */
384  region_map->zoomed = zoomSurface(region_map->surface,
385  region_map->zoom / 100.0, region_map->zoom / 100.0, 0);
386  region_map->fow_zoomed = zoomSurface(region_map->fow->surface,
387  region_map->zoom / 100.0, region_map->zoom / 100.0, 0);
388  SDL_SetColorKey(region_map->fow_zoomed, SDL_SRCCOLORKEY,
389  SDL_MapRGB(region_map->fow_zoomed->format, 255, 255, 255));
390  }
391 
392  if (adjust > 0) {
393  delta = (region_map->zoom / 100.0 - 0.1f);
394  } else {
395  delta = (region_map->zoom / 100.0 + 0.1f);
396  }
397 
398  region_map->pos.x += region_map->pos.x / delta * (adjust / 100.0) +
399  region_map->pos.w / delta * (adjust / 100.0) / 2;
400  region_map->pos.y += region_map->pos.y / delta * (adjust / 100.0) +
401  region_map->pos.h / delta * (adjust / 100.0) / 2;
402 
403  surface_pan(region_map_surface(region_map), &region_map->pos);
404 }
405 
417 void region_map_render_marker(region_map_t *region_map, SDL_Surface *surface,
418  int x, int y)
419 {
420  SDL_Surface *marker;
421  SDL_Rect box, srcbox;
423 
424  map = region_map_find_map(region_map, MapData.map_path);
425 
426  if (map == NULL) {
427  return;
428  }
429 
430  /* TODO: Could cache this */
431  marker = rotozoomSurface(TEXTURE_CLIENT("map_marker"),
432  -((map_get_player_direction() - 1) * 45),
433  region_map->zoom / 100.0, 1);
434  /* Calculate the player's marker position. */
435  box.x = x + (map->xpos + MapData.posx * region_map->def->pixel_size) *
436  (region_map->zoom / 100.0) - marker->w / 2.0 +
437  region_map->def->pixel_size / 2.0 - region_map->pos.x;
438  box.y = y + (map->ypos + MapData.posy * region_map->def->pixel_size) *
439  (region_map->zoom / 100.0) - marker->h / 2.0 +
440  region_map->def->pixel_size / 2.0 - region_map->pos.y;
441 
442  srcbox.x = MAX(0, x - box.x);
443  srcbox.y = MAX(0, y - box.y);
444  srcbox.w = MAX(0, region_map->pos.w - (box.x - x));
445  srcbox.h = MAX(0, region_map->pos.h - (box.y - y));
446 
447  box.x += srcbox.x;
448  box.y += srcbox.y;
449 
450  SDL_BlitSurface(marker, &srcbox, surface, &box);
451  SDL_FreeSurface(marker);
452 }
453 
454 void region_map_render_fow(region_map_t *region_map, SDL_Surface *surface,
455  int x, int y)
456 {
457  SDL_Rect box;
458 
459  if (region_map->fow->surface == NULL) {
460  return;
461  }
462 
463  box.x = x;
464  box.y = y;
465  SDL_BlitSurface(region_map_fow_surface(region_map), &region_map->pos,
466  surface, &box);
467 }
468 
475 {
476  region_map_def_t *def;
477 
478  def = ecalloc(1, sizeof(*def));
479  def->refcount = 1;
480 
481  return def;
482 }
483 
491 static void region_map_def_load(region_map_def_t *def, const char *str)
492 {
493  char line[HUGE_BUF], *cps[10], region[MAX_BUF];
494  size_t pos, pos2;
495  region_map_def_map_t *def_map;
496 
497  def->pixel_size = 1;
498  def->map_size_x = 24;
499  def->map_size_y = 24;
500 
501  pos = 0;
502 
503  while (string_get_word(str, &pos, '\n', VS(line), 0)) {
504  if (strcmp(line, "t_outline") == 0) {
505  if (def->num_tooltips == 0) {
506  LOG(ERROR, "No tooltips defined.");
507  continue;
508  }
509 
510  def->tooltips[def->num_tooltips - 1].outline = 1;
511  def->tooltips[def->num_tooltips - 1].outline_size = 1;
512  def->tooltips[def->num_tooltips - 1].outline_color.r = 255;
513  def->tooltips[def->num_tooltips - 1].outline_color.g = 0;
514  def->tooltips[def->num_tooltips - 1].outline_color.b = 0;
515  continue;
516  }
517 
518  if (string_split(line, cps, 2, ' ') != 2) {
519  LOG(ERROR, "Invalid line in definitions file: %s", line);
520  continue;
521  }
522 
523  if (strcmp(cps[0], "pixel_size") == 0) {
524  def->pixel_size = atoi(cps[1]);
525  } else if (strcmp(cps[0], "map_size_x") == 0) {
526  def->map_size_x = atoi(cps[1]);
527  } else if (strcmp(cps[0], "map_size_y") == 0) {
528  def->map_size_y = atoi(cps[1]);
529  } else if (strcmp(cps[0], "map") == 0) {
530  if (string_split(cps[1], cps, 4, ' ') < 3) {
531  LOG(ERROR, "Invalid map in definitions file: %s", cps[1]);
532  continue;
533  }
534 
535  def->maps = erealloc(def->maps, sizeof(*def->maps) *
536  (def->num_maps + 1));
537  def_map = &def->maps[def->num_maps];
538  def->num_maps++;
539 
540  def_map->xpos = strtoul(cps[0], NULL, 16);
541  def_map->ypos = strtoul(cps[1], NULL, 16);
542  def_map->path = estrdup(cps[2]);
543  def_map->regions = NULL;
544  def_map->regions_num = 0;
545 
546  if (cps[3] != NULL) {
547  pos2 = 0;
548 
549  while (string_get_word(cps[3], &pos2, ',', VS(region), 0)) {
550  def_map->regions = erealloc(def_map->regions,
551  sizeof(*def_map->regions) *
552  (def_map->regions_num + 1));
553  def_map->regions[def_map->regions_num] = estrdup(region);
554  def_map->regions_num++;
555  }
556  }
557  } else if (strcmp(cps[0], "label") == 0) {
558  if (string_split(cps[1], cps, 4, ' ') != 4) {
559  LOG(ERROR, "Invalid label in definitions file: %s",
560  cps[1]);
561  continue;
562  }
563 
564  def->labels = erealloc(def->labels, sizeof(*def->labels) *
565  (def->num_labels + 1));
566  def->labels[def->num_labels].x = strtoul(cps[0], NULL, 16);
567  def->labels[def->num_labels].y = strtoul(cps[1], NULL, 16);
568  def->labels[def->num_labels].name = estrdup(cps[2]);
569  def->labels[def->num_labels].text = estrdup(cps[3]);
570  string_newline_to_literal(def->labels[def->num_labels].text);
571  def->num_labels++;
572  } else if (strcmp(cps[0], "label_hide") == 0) {
573 
574  } else if (strcmp(cps[0], "tooltip") == 0) {
575  if (string_split(cps[1], cps, 6, ' ') != 6) {
576  LOG(ERROR, "Invalid tooltip in definitions file: %s",
577  cps[1]);
578  continue;
579  }
580 
581  def->tooltips = erealloc(def->tooltips, sizeof(*def->tooltips) *
582  (def->num_tooltips + 1));
583  def->tooltips[def->num_tooltips].outline = 0;
584  def->tooltips[def->num_tooltips].x = strtoul(cps[0], NULL, 16);
585  def->tooltips[def->num_tooltips].y = strtoul(cps[1], NULL, 16);
586  def->tooltips[def->num_tooltips].w = strtoul(cps[2], NULL, 16);
587  def->tooltips[def->num_tooltips].h = strtoul(cps[3], NULL, 16);
588  def->tooltips[def->num_tooltips].name = estrdup(cps[4]);
589  def->tooltips[def->num_tooltips].text = estrdup(cps[5]);
590  string_newline_to_literal(def->tooltips[def->num_tooltips].text);
591  def->num_tooltips++;
592  } else if (strcmp(cps[0], "t_outline") == 0) {
593  if (string_split(cps[1], cps, 2, ' ') != 2) {
594  LOG(ERROR, "Invalid t_outline in definitions file: %s",
595  cps[1]);
596  continue;
597  }
598 
599  if (def->num_tooltips == 0) {
600  LOG(ERROR, "No tooltips defined.");
601  continue;
602  }
603 
604  if (!text_color_parse(cps[0],
605  &def->tooltips[def->num_tooltips - 1].outline_color)) {
606  LOG(ERROR, "Color in invalid format: %s", cps[0]);
607  continue;
608  }
609 
610  def->tooltips[def->num_tooltips - 1].outline = 1;
611  def->tooltips[def->num_tooltips - 1].outline_size = atoi(cps[1]);
612  }
613  }
614 }
615 
624 {
625  size_t i;
626 
627  HARD_ASSERT(def != NULL);
628 
629  /* Free all maps. */
630  for (i = 0; i < def->num_maps; i++) {
631  efree(def->maps[i].path);
632 
633  if (def->maps[i].regions != NULL) {
634  for (size_t j = 0; j < def->maps[i].regions_num; j++) {
635  efree(def->maps[i].regions[j]);
636  }
637 
638  efree(def->maps[i].regions);
639  }
640  }
641 
642  if (def->maps != NULL) {
643  efree(def->maps);
644  def->maps = NULL;
645  def->num_maps = 0;
646  }
647 
648  /* Free labels. */
649  for (i = 0; i < def->num_labels; i++) {
650  efree(def->labels[i].name);
651  efree(def->labels[i].text);
652  }
653 
654  if (def->labels != NULL) {
655  efree(def->labels);
656  def->labels = NULL;
657  def->num_labels = 0;
658  }
659 
660  /* Free tooltips. */
661  for (i = 0; i < def->num_tooltips; i++) {
662  efree(def->tooltips[i].name);
663  efree(def->tooltips[i].text);
664  }
665 
666  if (def->tooltips != NULL) {
667  efree(def->tooltips);
668  def->tooltips = NULL;
669  def->num_tooltips = 0;
670  }
671 }
672 
679 {
680  region_map_fow_t *fow;
681 
682  fow = ecalloc(1, sizeof(*fow));
683  fow->refcount = 1;
684  utarray_new(fow->tiles, &icd);
685 
686  return fow;
687 }
688 
689 static void region_map_fow_create(region_map_t *region_map)
690 {
691  FILE *fp;
692 
693  HARD_ASSERT(region_map->fow != NULL);
694  HARD_ASSERT(region_map->fow->path != NULL);
695  HARD_ASSERT(region_map->fow->bitmap == NULL);
696 
697  fp = path_fopen(region_map->fow->path, "r");
698 
699  if (fp != NULL) {
700  struct stat statbuf;
701 
702  if (fstat(fileno(fp), &statbuf) == -1) {
703  LOG(ERROR, "Could not stat %s: %d (%s)", region_map->fow->path,
704  errno, strerror(errno));
705  } else if ((size_t) statbuf.st_size ==
706  RM_MAP_FOW_BITMAP_SIZE(region_map)) {
707  region_map->fow->bitmap = emalloc(statbuf.st_size);
708 
709  if (fread(region_map->fow->bitmap, 1, statbuf.st_size, fp) !=
710  (size_t) statbuf.st_size) {
711  LOG(ERROR, "Could not read %"PRIu64" bytes from %s: %d "
712  "(%s)", (uint64_t) statbuf.st_size, region_map->fow->path,
713  errno, strerror(errno));
714  efree(region_map->fow->bitmap);
715  region_map->fow->bitmap = NULL;
716  }
717  }
718 
719  fclose(fp);
720  }
721 
722  if (region_map->fow->bitmap == NULL) {
723  region_map->fow->bitmap = ecalloc(1,
724  RM_MAP_FOW_BITMAP_SIZE(region_map));
725  }
726 
727  region_map_fow_update(region_map);
728 }
729 
730 static void region_map_fow_free(region_map_t *region_map)
731 {
732  unsigned i;
733  region_map_fow_tile_t *tile;
734 
735  HARD_ASSERT(region_map != NULL);
736  HARD_ASSERT(region_map->fow != NULL);
737 
738  region_map_fow_reset(region_map);
739 
740  if (region_map->fow->tiles != NULL) {
741  for (i = 0; i < utarray_len(region_map->fow->tiles); i++) {
742  tile = (region_map_fow_tile_t *) utarray_eltptr(
743  region_map->fow->tiles, i);
744  efree(tile->path);
745  }
746 
747  utarray_free(region_map->fow->tiles);
748  region_map->fow->tiles = NULL;
749  }
750 
751  if (region_map->fow->path != NULL) {
752  efree(region_map->fow->path);
753  region_map->fow->path = NULL;
754  }
755 }
756 
757 static void region_map_fow_reset(region_map_t *region_map)
758 {
759  HARD_ASSERT(region_map != NULL);
760  HARD_ASSERT(region_map->fow != NULL);
761 
762  if (region_map->fow->surface != NULL) {
763  SDL_FreeSurface(region_map->fow->surface);
764  region_map->fow->surface = NULL;
765  }
766 
767  if (region_map->fow_zoomed != NULL) {
768  SDL_FreeSurface(region_map->fow_zoomed);
769  region_map->fow_zoomed = NULL;
770  }
771 
772  if (region_map->fow->bitmap != NULL) {
773  FILE *fp;
774 
775  HARD_ASSERT(region_map->surface != NULL);
776  HARD_ASSERT(region_map->fow->path != NULL);
777 
778  fp = path_fopen(region_map->fow->path, "w");
779 
780  if (fp != NULL) {
781  fwrite(region_map->fow->bitmap, 1,
782  RM_MAP_FOW_BITMAP_SIZE(region_map), fp);
783  fclose(fp);
784  }
785 
786  efree(region_map->fow->bitmap);
787  region_map->fow->bitmap = NULL;
788  }
789 }
790 
791 static bool region_map_fow_update_regions(region_map_t *region_map,
792  const uint32_t *color)
793 {
794  bool ret = false;
795  region_map_def_map_t *def_map, *def_map_regions;
796  UT_array *regions;
797 
798  utarray_new(regions, &ut_str_icd);
799 
800  for (object *op = cpl.ob->inv; op != NULL; op = op->next) {
801  if (op->itype != TYPE_REGION_MAP) {
802  continue;
803  }
804 
805  char *cp = op->s_name;
806  utarray_push_back(regions, &cp);
807  }
808 
809  utarray_sort(regions, ut_str_sort);
810 
811  def_map_regions = NULL;
812 
813  for (size_t i = 0; i < region_map->def->num_maps; i++) {
814  def_map = &region_map->def->maps[i];
815 
816  if (def_map->regions != NULL) {
817  def_map_regions = def_map;
818  }
819 
820  if (def_map_regions == NULL) {
821  continue;
822  }
823 
824  for (size_t j = 0; j < def_map_regions->regions_num; j++) {
825  if (utarray_find(regions, &def_map_regions->regions[j],
826  ut_str_sort) == NULL) {
827  continue;
828  }
829 
830  if (color != NULL) {
831  SDL_Rect box;
832 
833  box.x = def_map->xpos;
834  box.y = def_map->ypos;
835  box.w = region_map->def->map_size_x *
836  region_map->def->pixel_size;
837  box.h = region_map->def->map_size_y *
838  region_map->def->pixel_size;
839  SDL_FillRect(region_map->fow->surface, &box, *color);
840  }
841 
842  ret = true;
843  }
844  }
845 
846  utarray_free(regions);
847 
848  return ret;
849 }
850 
851 void region_map_fow_update(region_map_t *region_map)
852 {
853  region_map_def_map_t *def_map;
854  int rowsize, x, y;
855  uint32_t color;
856  SDL_Surface *surface;
857 
858  HARD_ASSERT(region_map != NULL);
859  HARD_ASSERT(region_map->fow != NULL);
860  HARD_ASSERT(region_map->def != NULL);
861 
862  if (region_map->surface == NULL) {
863  /* Not yet loaded, nothing to do. */
864  return;
865  }
866 
867  if (region_map->fow->tiles != NULL) {
868  region_map_fow_tile_t *tile;
869 
870  /* Now that the definitions are loaded, we can go back through the tiles
871  * data and actually set the visited tiles. */
872  for (size_t i = 0; i < utarray_len(region_map->fow->tiles); i++) {
873  tile = (region_map_fow_tile_t *) utarray_eltptr(
874  region_map->fow->tiles, i);
875  def_map = region_map_find_map(region_map, tile->path);
876  efree(tile->path);
877 
878  if (def_map != NULL) {
879  region_map_fow_set_visited(region_map, def_map, NULL,
880  tile->x, tile->y);
881  }
882  }
883 
884  utarray_free(region_map->fow->tiles);
885  region_map->fow->tiles = NULL;
886  }
887 
888  if (region_map->fow->surface == NULL) {
889  region_map->fow->surface = SDL_CreateRGBSurface(get_video_flags(),
890  region_map->surface->w, region_map->surface->h, video_get_bpp(),
891  0, 0, 0, 0);
892  }
893 
894  SDL_FillRect(region_map->fow->surface, NULL, 0);
895  rowsize = (region_map->surface->w / region_map->def->pixel_size + 31) / 32;
896  color = SDL_MapRGB(region_map->fow->surface->format, 255, 255, 255);
897 
898  for (y = 0; y < region_map->surface->h / region_map->def->pixel_size; y++) {
899  for (x = 0; x < region_map->surface->w / region_map->def->pixel_size;
900  x++) {
901  SDL_Rect box;
902 
903  if (x % 32 == 0 && (region_map->fow->bitmap[(x / 32) + rowsize *
904  y] == 0xffffffff)) {
905  /* If this entire 32 tiles area is visible, then we just
906  * draw one wide rectangle. */
907  box.x = x * region_map->def->pixel_size;
908  box.w = region_map->def->pixel_size * 32;
909  x += 32 - 1;
910  } else if (region_map->fow->bitmap[(x / 32) + rowsize * y] &
911  (1U << (x % 32))) {
912  /* The tile is visible */
913  box.x = x * region_map->def->pixel_size;
914  box.w = region_map->def->pixel_size;
915  } else {
916  continue;
917  }
918 
919  box.y = y * region_map->def->pixel_size;
920  box.h = region_map->def->pixel_size;
921  SDL_FillRect(region_map->fow->surface, &box, color);
922  }
923  }
924 
925  region_map_fow_update_regions(region_map, &color);
926 
927  SDL_SetColorKey(region_map->fow->surface, SDL_SRCCOLORKEY, color);
928  surface = SDL_DisplayFormat(region_map->fow->surface);
929  SDL_FreeSurface(region_map->fow->surface);
930  region_map->fow->surface = surface;
931 }
932 
933 bool region_map_fow_set_visited(region_map_t *region_map,
934  region_map_def_map_t *map, const char *map_path, int x, int y)
935 {
936  int rowsize;
937  ssize_t idx;
938 
939  HARD_ASSERT(region_map != NULL);
940  HARD_ASSERT(region_map->fow != NULL);
941  HARD_ASSERT(map != NULL || map_path != NULL);
942 
943  if (map == NULL) {
945 
946  if (region_map->fow->tiles == NULL) {
947  return false;
948  }
949 
950  tile.path = estrdup(map_path);
951  tile.x = x;
952  tile.y = y;
953  utarray_push_back(region_map->fow->tiles, &tile);
954  return false;
955  }
956 
957  HARD_ASSERT(region_map->fow->bitmap != NULL);
958 
959  x += map->xpos / region_map->def->pixel_size;
960  y += map->ypos / region_map->def->pixel_size;
961 
962  if (x < 0 || x >= region_map->surface->w / region_map->def->pixel_size ||
963  y < 0 || y >= region_map->surface->h /
964  region_map->def->pixel_size) {
965  return false;
966  }
967 
968  if (region_map_fow_is_visited(region_map, x, y)) {
969  return false;
970  }
971 
972  rowsize = (region_map->surface->w / region_map->def->pixel_size + 31) / 32;
973  idx = (x / 32) + rowsize * y;
974 
975  SOFT_ASSERT_RC(idx >= 0 && (size_t) idx < RM_MAP_FOW_BITMAP_SIZE(
976  region_map) / sizeof(*region_map->fow->bitmap), false,
977  "Attempt to write at an invalid position: %"PRIu64" max: %"PRIu64,
978  (uint64_t) idx, (uint64_t) RM_MAP_FOW_BITMAP_SIZE(region_map) /
979  sizeof(*region_map->fow->bitmap));
980 
981  region_map->fow->bitmap[idx] |= (1U << (x % 32));
982  return true;
983 }
984 
985 bool region_map_fow_is_visited(region_map_t *region_map, int x, int y)
986 {
987  int rowsize;
988  ssize_t idx;
989 
990  HARD_ASSERT(region_map != NULL);
991  HARD_ASSERT(region_map->fow != NULL);
992 
993  rowsize = (region_map->surface->w / region_map->def->pixel_size + 31) / 32;
994  idx = (x / 32) + rowsize * y;
995 
996  SOFT_ASSERT_RC(idx >= 0 && (size_t) idx < RM_MAP_FOW_BITMAP_SIZE(
997  region_map) / sizeof(*region_map->fow->bitmap), false,
998  "Attempt to read at an invalid position: %"PRIu64" max: %"PRIu64,
999  (uint64_t) idx, (uint64_t) RM_MAP_FOW_BITMAP_SIZE(region_map) /
1000  sizeof(*region_map->fow->bitmap));
1001 
1002  return region_map->fow->bitmap[idx] & (1U << (x % 32));
1003 }
1004 
1005 bool region_map_fow_is_visible(region_map_t *region_map, int x, int y)
1006 {
1007  if (region_map_fow_is_visited(region_map, x, y)) {
1008  return true;
1009  }
1010 
1011  if (region_map_fow_update_regions(region_map, NULL)) {
1012  return true;
1013  }
1014 
1015  return false;
1016 }
1017 
1025 SDL_Surface *region_map_fow_surface(region_map_t *region_map)
1026 {
1027  HARD_ASSERT(region_map->fow != NULL);
1028  HARD_ASSERT(region_map->fow != NULL);
1029  HARD_ASSERT(region_map->fow->surface != NULL);
1030 
1031  if (region_map->fow_zoomed != NULL) {
1032  return region_map->fow_zoomed;
1033  }
1034 
1035  return region_map->fow->surface;
1036 }
1037 
1038 #endif
char map_path[HUGE_BUF]
Definition: map.h:134
char ** regions
Regions this map belongs to.
Definition: region_map.h:53
size_t regions_num
Number of entries in 'regions'.
Definition: region_map.h:54
region_map_t * region_map_create(void)
Definition: region_map.c:54
int text_color_parse(const char *color_notation, SDL_Color *color)
Definition: text.c:603
size_t num_tooltips
Definition: region_map.h:126
void region_map_resize(region_map_t *region_map, int adjust)
Definition: region_map.c:362
struct region_map_fow_tile region_map_fow_tile_t
uint32_t get_video_flags(void)
Definition: video.c:365
void text_show(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:1983
SDL_Surface * zoomed
Definition: region_map.h:189
#define COLOR_HGOLD
Definition: text.h:319
static region_map_fow_t * region_map_fow_new(void)
Definition: region_map.c:678
#define TEXT_MARKUP
Definition: text.h:224
region_map_def_map_t * maps
Definition: region_map.h:117
char * file_path_player(const char *path)
Definition: wrapper.c:452
_mapdata MapData
Definition: map.c:64
static void region_map_def_free(region_map_def_t *def)
Definition: region_map.c:623
int video_get_bpp(void)
Definition: video.c:334
bool region_map_ready(region_map_t *region_map)
Definition: region_map.c:200
region_map_def_t * def
Definition: region_map.h:206
SDL_Rect pos
Definition: region_map.h:224
Client_Player cpl
Definition: client.c:50
size_t num_labels
Definition: region_map.h:132
int posx
Definition: map.h:145
SDL_Surface * region_map_surface(region_map_t *region_map)
Definition: region_map.c:319
curl_request_t * request_def
Definition: region_map.h:234
SDL_Surface * region_map_fow_surface(region_map_t *region_map)
Definition: region_map.c:1025
region_map_def_map_t * region_map_find_map(region_map_t *region_map, const char *map_path)
Definition: region_map.c:295
void region_map_free(region_map_t *region_map)
Definition: region_map.c:93
char http_url[MAX_BUF]
Definition: player.h:252
int y
Y coordinate.
Definition: region_map.h:154
int x
X coordinate.
Definition: region_map.h:153
char * path
Map path.
Definition: region_map.h:152
void region_map_reset(region_map_t *region_map)
Definition: region_map.c:110
#define TEXT_OUTLINE
Definition: text.h:255
struct obj * next
Definition: item.h:45
size_t num_maps
Definition: region_map.h:120
char * file_path_server(const char *path)
Definition: wrapper.c:476
SDL_Surface * fow_zoomed
Definition: region_map.h:199
void border_create(SDL_Surface *surface, int x, int y, int w, int h, int color, int size)
Definition: sprite.c:1226
region_map_t * region_map_clone(region_map_t *region_map)
Definition: region_map.c:73
static region_map_def_t * region_map_def_new(void)
Definition: region_map.c:474
SDL_Surface * surface
Definition: region_map.h:182
int map_get_player_direction(void)
Definition: map.c:370
int posy
Definition: map.h:148
static region_map_t * region_map
Definition: region_map.c:145
struct obj * inv
Definition: item.h:57
region_map_def_label_t * labels
Definition: region_map.h:129
void region_map_render_marker(region_map_t *region_map, SDL_Surface *surface, int x, int y)
Definition: region_map.c:417
region_map_def_tooltip_t * tooltips
Definition: region_map.h:123
curl_request_t * request_png
Definition: region_map.h:229
void surface_pan(SDL_Surface *surface, SDL_Rect *box)
Definition: sprite.c:1151
object * ob
Definition: player.h:111
static void region_map_def_load(region_map_def_t *def, const char *str)
Definition: region_map.c:491