Crossfire Client, Trunk
map.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, see the
9  * 'LICENSE' and 'COPYING' files.
10  *
11  * The authors can be reached via e-mail to crossfire-devel@real-time.com
12  */
13 
20 #include "client.h"
21 
22 #include <math.h>
23 #include <gtk/gtk.h>
24 
25 #include "image.h"
26 #include "main.h"
27 #include "mapdata.h"
28 #include "gtk2proto.h"
29 
30 /* Configuration (from config.c) */
31 extern int predict_alpha;
32 extern bool time_map_redraw;
33 
35 static gboolean map_updated = FALSE;
36 
37 GtkWidget *map_notebook;
38 static GtkWidget *map_drawing_area;
39 
40 // Forward declarations for events
41 static gboolean map_button_event(GtkWidget *widget,
42  GdkEventButton *event, gpointer user_data);
43 static gboolean map_expose_event(GtkWidget *widget,
44  GdkEventExpose *event, gpointer user_data);
45 
46 // Font for drawing player labels
47 static cairo_font_face_t *font;
48 
53  if (!GTK_IS_WIDGET(map_drawing_area)) {
54  // Called by config_check(), but main window layout not yet loaded.
55  return;
56  }
57 
58  GtkAllocation size;
59  gtk_widget_get_allocation(map_drawing_area, &size);
60  int scaled_size = map_image_size * use_config[CONFIG_MAPSCALE] / 100;
61  int w = size.width / scaled_size + 1;
62  int h = size.height / scaled_size + 1;
63  w = (w > MAP_MAX_SIZE) ? MAP_MAX_SIZE : w;
64  h = (h > MAP_MAX_SIZE) ? MAP_MAX_SIZE : h;
65 
66  // If request would be even, make it odd so player is centered.
67  if (w % 2 == 0) {
68  w += 1;
69  }
70 
71  if (h % 2 == 0) {
72  h += 1;
73  }
74 
78  if (csocket.fd) {
79  client_mapsize(w, h);
80  }
81  }
82 }
83 
88  // TODO: This is technically missing a cairo_font_face_destroy()
89  font = cairo_toy_font_face_create("", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
90 
91  // Do dummy text drawing to cache the font
92  const char *test_text = "TEST TEXT";
93  cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10);
94  cairo_t *cr = cairo_create(cst);
95  cairo_set_font_face(cr, font);
96  cairo_text_extents_t extents;
97  cairo_text_extents(cr, test_text, &extents);
98  cairo_show_text(cr, test_text);
99  cairo_destroy(cr);
100  cairo_surface_destroy(cst);
101 }
102 
108 void map_init(GtkWidget *window_root) {
109  static gulong map_button_handler = 0;
110  map_drawing_area = GTK_WIDGET(gtk_builder_get_object(
111  window_xml, "drawingarea_map"));
112  map_notebook = GTK_WIDGET(gtk_builder_get_object(
113  window_xml, "map_notebook"));
114 
115  g_signal_connect(map_drawing_area, "configure_event",
116  G_CALLBACK(map_check_resize), NULL);
117  g_signal_connect(map_drawing_area, "expose_event",
118  G_CALLBACK(map_expose_event), NULL);
119 
120  // Enable event masks and set callbacks to handle mouse events.
121  // If its already connected (e.g. on a second login), then skip
122  // an additional association.
123  if (!g_signal_handler_is_connected(map_drawing_area, map_button_handler)) {
124  gtk_widget_add_events(map_drawing_area,
125  GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
126  map_button_handler = g_signal_connect(map_drawing_area, "event",
127  G_CALLBACK(map_button_event), NULL);
128  }
129 
130  // Set our image sizes.
131  // IIRC, atoi stops at the first nonnumeric char, so the x in the size will be the end.
132  if (face_info.facesets[face_info.faceset].size != NULL) {
134  map_image_size = image_size; // These should be the same.
135  } else {
136  LOG(LOG_ERROR, "map_init", "Invalid faceset size from server");
137  }
138  // If we are not on the default size, we need to resize pixmaps[0].
140  int nx = map_image_size, ny = map_image_size;
141  guint8 *png_tmp = rescale_rgba_data(pixmaps[0]->map_image, &nx, &ny, use_config[CONFIG_MAPSCALE]);
142  // Try to affect pixmap[0] in-place, since it is referenced extensively.
143  pixmaps[0]->icon_width = nx;
144  pixmaps[0]->icon_height = ny;
145  // Do not affect full_icon_width/height, since those are expected to be the unscaled size.
146  do_new_image(png_tmp, pixmaps[0]);
147  }
148 
149  // Set map size based on window size and show widget.
151  gtk_widget_show(map_drawing_area);
152 }
153 
159 static void draw_pixmap(cairo_t *cr, PixmapInfo *pixmap, int ax, int ay) {
160  const int dest_x = ax * map_image_size;
161  const int dest_y = ay * map_image_size;
162  cairo_set_source_surface(cr, pixmap->map_image, dest_x, dest_y);
163  cairo_paint(cr);
164 }
165 
166 static void draw_smooth_pixmap(cairo_t* cr, PixmapInfo* pixmap,
167  const int sx, const int sy, const int dx, const int dy) {
168  const int src_x = map_image_size * sx;
169  const int src_y = map_image_size * sy;
170  const int dest_x = map_image_size * dx;
171  const int dest_y = map_image_size * dy;
172  cairo_set_source_surface(cr, pixmap->map_image, dest_x - src_x, dest_y - src_y);
173  cairo_rectangle(cr, dest_x, dest_y, map_image_size, map_image_size);
174  cairo_fill(cr);
175 }
176 
177 int display_mapscroll(int dx, int dy) {
178  return 0;
179 }
180 
191 static void drawsmooth(cairo_t *cr, int mx, int my, int layer, int picx, int picy) {
192  static int dx[8]= {0,1,1,1,0,-1,-1,-1};
193  static int dy[8]= {-1,-1,0,1,1,1,0,-1};
194  static int bweights[8]= {2,0,4,0,8,0,1,0};
195  static int cweights[8]= {0,2,0,4,0,8,0,1};
196  static int bc_exclude[8]= {
197  1+2,/*north exclude northwest (bit0) and northeast(bit1)*/
198  0,
199  2+4,/*east exclude northeast and southeast*/
200  0,
201  4+8,/*and so on*/
202  0,
203  8+1,
204  0
205  };
206  int partdone[8]= {0,0,0,0,0,0,0,0};
207  int slevels[8];
208  int sfaces[8];
209  int i,weight,weightC;
210  int emx,emy;
211  int smoothface;
212  int hasFace = 0;
213  for (i=0; i<=layer; i++) {
214  hasFace |= mapdata_cell(mx, my)->heads[i].face;
215  }
216  if (!hasFace || !mapdata_can_smooth(mx, my, layer)) {
217  return;
218  }
219  for (i=0; i<8; i++) {
220  emx=mx+dx[i];
221  emy=my+dy[i];
222  if (!mapdata_contains(emx, emy)) {
223  slevels[i]=0;
224  sfaces[i]=0; /*black picture*/
225  } else if (mapdata_cell(emx, emy)->smooth[layer] <= mapdata_cell(mx, my)->smooth[layer]) {
226  slevels[i]=0;
227  sfaces[i]=0; /*black picture*/
228  } else {
229  slevels[i]=mapdata_cell(emx, emy)->smooth[layer];
230  sfaces[i]=pixmaps[mapdata_cell(emx, emy)->heads[layer].face]->smooth_face;
231  }
232  }
233  /*
234  * Now we have a list of smoothlevel higher than current square. There are
235  * at most 8 different levels. so... check 8 times for the lowest one (we
236  * draw from bottom to top!).
237  */
238  while (1) {
239  int lowest = -1;
240  for (i=0; i<8; i++) {
241  if ( (slevels[i]>0) && (!partdone[i]) &&
242  ((lowest<0) || (slevels[i]<slevels[lowest]))
243  ) {
244  lowest=i;
245  }
246  }
247  if (lowest<0) {
248  break; /*no more smooth to do on this square*/
249  }
250  /*printf ("hey, must smooth something...%d\n",sfaces[lowest]);*/
251  /* Here we know 'what' to smooth
252  *
253  * Calculate the weight for border and weight for corners. Then
254  * 'markdone' the corresponding squares
255  *
256  * First, the border, which may exclude some corners
257  */
258  weight=0;
259  weightC=15; /*works in backward. remove where there is nothing*/
260  /*for (i=0;i<8;i++)
261  cornermask[i]=1;*/
262  for (i=0; i<8; i++) { /*check all nearby squares*/
263  if ( (slevels[i]==slevels[lowest]) &&
264  (sfaces[i]==sfaces[lowest])) {
265  partdone[i]=1;
266  weight=weight+bweights[i];
267  weightC&=~bc_exclude[i];
268  } else {
269  /*must rmove the weight of a corner if not in smoothing*/
270  weightC&=~cweights[i];
271  }
272  }
273  /*We can't do this before since we need the partdone to be adjusted*/
274  if (sfaces[lowest]<=0) {
275  continue; /*Can't smooth black*/
276  }
277  smoothface=sfaces[lowest];
278  if (smoothface<=0) {
279  continue; /*picture for smoothing not yet available*/
280  }
281  /*
282  * now, it's quite easy. We must draw using a 32x32 part of the picture
283  * smoothface. This part is located using the 2 weights calculated:
284  * (32*weight,0) and (32*weightC,32)
285  */
286  if ( (!pixmaps[smoothface]->map_image) ||
287  (pixmaps[smoothface] == pixmaps[0])) {
288  continue; /*don't have the picture associated*/
289  }
290 
291  if (weight > 0) {
292  draw_smooth_pixmap(cr, pixmaps[smoothface], weight, 0, picx, picy);
293  }
294 
295  if (weightC > 0) {
296  draw_smooth_pixmap(cr, pixmaps[smoothface], weightC, 1, picx, picy);
297  }
298  }
299 }
300 
304 static void map_draw_layer(cairo_t *cr, int layer, int mx_start, int nx, int my_start, int ny) {
305  for (int x = 0; x <= nx; x++) {
306  for (int y = 0; y <= ny; y++) {
307  // Translate on-screen coordinates to virtual map coordinates.
308  const int mx = mx_start + x;
309  const int my = my_start + y;
310 
311  // Skip current cell if not visible and not using fog of war.
312  if (!use_config[CONFIG_FOGWAR] && mapdata_cell(mx, my)->state == FOG) {
313  continue;
314  }
315 
316  // Draw pixmaps
317  int dx, dy, face = mapdata_face_info(mx, my, layer, &dx, &dy);
318  if (face > 0 && pixmaps[face]->map_image != NULL) {
319  draw_pixmap(cr, pixmaps[face], x + dx, y + dy);
320  }
321 
322  // Draw smoothing
323  if (use_config[CONFIG_SMOOTH]) {
324  drawsmooth(cr, mx, my, layer, x, y);
325  }
326  }
327  }
328 }
329 
330 static void map_draw_labels(cairo_t *cr, int mx_start, int nx, int my_start, int ny) {
331  cairo_set_font_face(cr, font);
332  for (int x = 0; x <= nx; x++) {
333  for (int y = 0; y <= ny; y++) {
334  // Translate on-screen coordinates to virtual map coordinates.
335  const int mx = mx_start + x;
336  const int my = my_start + y;
337 
338  struct MapLabel *next = mapdata_cell(mx, my)->label;
339  double off_y = 0;
340  while (next != NULL) {
341  // calculate extents to center text above square
342  cairo_text_extents_t extents;
343  cairo_text_extents(cr, next->label, &extents);
344  double off_x = map_image_size/2 - extents.width/2;
345  double sx = (mx-mx_start)*map_image_size + off_x;
346  double sy = (my-my_start)*map_image_size + off_y;
347 
348  // background shading
349  int bx = 3;
350  double lineheight = extents.height+2*bx;
351  cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 0.5);
352  cairo_rectangle(cr, sx - bx, sy-extents.height-bx, extents.width+2*bx, lineheight);
353  cairo_fill(cr);
354 
355  // render text
356  cairo_move_to(cr, sx, sy);
357  switch (next->subtype) {
358  case MAP2_LABEL_DM:
359  cairo_set_source_rgb(cr, 1, 0, 0);
360  break;
362  cairo_set_source_rgb(cr, 177.0/255, 225.0/255, 255.0/255);
363  break;
364  default:
365  cairo_set_source_rgb(cr, 1, 1, 1);
366  }
367  cairo_show_text(cr, next->label);
368 
369  next = next->next;
370  off_y += lineheight;
371  }
372  }
373  }
374 }
375 
376 static double mapcell_darkness(int mx, int my) {
377  double opacity = mapdata_cell(mx, my)->darkness / 192.0 * 0.6;
378  if (use_config[CONFIG_FOGWAR] && mapdata_cell(mx, my)->state == FOG) {
379  opacity += 0.2;
380  }
381  return opacity;
382 }
383 
384 static void draw_darkness(cairo_t *cr, int nx, int ny, int mx_start, int my_start) {
389  cairo_surface_t *cst_lm = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nx+2, ny+2);
390  cairo_t *cr_lm = cairo_create(cst_lm);
391  for (int x = -1; x <= nx+1; x++) {
392  for (int y = -1; y <= ny+1; y++) {
393  const int dx = MIN(MAX(0, x), nx);
394  const int dy = MIN(MAX(0, y), ny);
395 
396  // Map coordinate to get darkness information from
397  const int mx = mx_start + dx;
398  const int my = my_start + dy;
399 
400  // Destination coordinates on light map
401  const int ax = x + 1;
402  const int ay = y + 1;
403 
404  cairo_rectangle(cr_lm, ax, ay, 1, 1);
405  cairo_set_source_rgba(cr_lm, 0, 0, 0, mapcell_darkness(mx, my));
406  cairo_fill(cr_lm);
407  }
408  }
409  cairo_destroy(cr_lm);
410 
411  // Scale up light map and draw to map.
412  cairo_scale(cr, map_image_size, map_image_size);
413  cairo_translate(cr, -1, -1);
414  cairo_set_source_surface(cr, cst_lm, 0, 0);
415  switch (use_config[CONFIG_LIGHTING]) {
416  case CFG_LT_TILE:
417  cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
418  break;
419  case CFG_LT_PIXEL:
420  cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD);
421  break;
422  case CFG_LT_PIXEL_BEST:
423  cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BEST);
424  break;
425  }
426  cairo_paint(cr);
427  cairo_surface_destroy(cst_lm);
428 }
429 
430 // Draw move-to tile.
431 static void draw_move_to(cairo_t *cr, int mx_start, int my_start) {
432  int mx = move_to_x;
433  int my = move_to_y;
434  int x = mx - mx_start;
435  int y = my - my_start;
436  if (!is_at_moveto()) {
437  int sx = x * map_image_size;
438  int sy = y * map_image_size;
439  cairo_rectangle(cr, sx, sy, map_image_size, map_image_size);
440  if (move_to_attack) {
441  cairo_set_source_rgb(cr, 1, 0, 0); // red to attack
442  } else {
443  cairo_set_source_rgb(cr, 1, 1, 0); // yellow to walk
444  }
445  cairo_set_line_width(cr, 2);
446  cairo_stroke(cr);
447  cairo_rectangle(cr, sx + 2, sy + 2, map_image_size - 4, map_image_size - 4);
448  cairo_set_source_rgb(cr, 0, 0, 0); // black
449  cairo_set_line_width(cr, 1);
450  cairo_stroke(cr);
451  }
452 }
453 
457 static void gtk_map_redraw() {
458  if (!map_updated) {
459  return;
460  }
461 
462  GtkAllocation size;
463  gtk_widget_get_allocation(map_drawing_area, &size);
464 
465  // Effective dimensions in pixels, i.e. after adjusting for map scale
466  float scale = use_config[CONFIG_MAPSCALE]/100.0;
467  const double ew = size.width / scale;
468  const double eh = size.height / scale;
469 
470  // Number of tiles to show in x and y dimensions
471  const int nx = (int)ceilf(ew / map_image_size);
472  const int ny = (int)ceilf(eh / map_image_size);
473 
474  // Current viewport dimensions as sent by server, in squares
475  const int vw = use_config[CONFIG_MAPWIDTH];
476  const int vh = use_config[CONFIG_MAPHEIGHT];
477 
478  // The server always centers the player in the viewport. However, if our
479  // drawing area shows more tiles than the viewport, then the player is
480  // no longer centered. Correct that here.
481  const int mx_start = (nx > vw) ? pl_pos.x - (nx - vw)/2 : pl_pos.x;
482  const int my_start = (ny > vh) ? pl_pos.y - (ny - vh)/2 : pl_pos.y;
483 
484  // Create double buffer and associated graphics context.
485  cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ew, eh);
486  cairo_t *cr = cairo_create(cst);
487 
488  // Blank graphics context with a solid black background.
489  cairo_set_source_rgb(cr, 0, 0, 0);
490  cairo_rectangle(cr, 0, 0, ew, eh);
491  cairo_fill(cr);
492 
493  // Set global offset (after blanking background)
494  cairo_translate(cr, global_offset_x, global_offset_y);
495 
496  // Draw layer-by-layer. Drawing cell-by-cell, looping over the layers,
497  // doesn't work because big faces need to be correctly layered on top.
498  for (int layer = 0; layer < MIN(render_debug_layers, MAXLAYERS); layer++) {
499  map_draw_layer(cr, layer, mx_start, nx, my_start, ny);
500  }
501 
502  draw_move_to(cr, mx_start, my_start);
503  map_draw_labels(cr, mx_start, nx, my_start, ny);
504 
505  if (use_config[CONFIG_LIGHTING] != 0) {
506  draw_darkness(cr, nx, ny, mx_start, my_start);
507  }
508  cairo_destroy(cr);
509 
510  // Copy the double buffer on the map drawing area.
511  cairo_t *map_cr = gdk_cairo_create(gtk_widget_get_window(map_drawing_area));
512  if (use_config[CONFIG_MAPSCALE] != 100) {
513  cairo_scale(map_cr, scale, scale);
514  }
515  cairo_set_source_surface(map_cr, cst, 0, 0);
516  if (use_config[CONFIG_MAPSCALE] % 100 == 0) {
517  cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
518  }
519  cairo_paint(map_cr);
520  cairo_destroy(map_cr);
521 
522  cairo_surface_destroy(cst);
523 }
524 
531 void resize_map_window(int x, int y) {
532 }
533 
534 static void update_global_offset() {
535  int dx, dy;
538  global_offset_x += dx;
539  global_offset_y += dy;
540 }
541 
545 void draw_map() {
546  gint64 t_start, t_end;
547  t_start = g_get_monotonic_time();
548 
550  gtk_map_redraw();
551 
552  t_end = g_get_monotonic_time();
553  gint64 elapsed = t_end - t_start;
554  if (time_map_redraw) {
555  printf("profile/redraw,%"G_GINT64_FORMAT"\n", elapsed);
556  }
557 
558  const unsigned int target_redraw = 100000;
559  const int no_resize_above = 100; // don't resize above this value of mapscale
560  if (elapsed > target_redraw && use_config[CONFIG_MAPSCALE] < no_resize_above) {
561  use_config[CONFIG_MAPSCALE] = MIN(use_config[CONFIG_MAPSCALE] + 5, no_resize_above);
562  LOG(LOG_DEBUG, "draw_map", "Increasing mapscale to %d to reduce draw time below %u us",
563  use_config[CONFIG_MAPSCALE], target_redraw);
565  }
566 }
567 
568 static gboolean map_expose_event(GtkWidget *widget, GdkEventExpose *event,
569  gpointer user_data) {
570  draw_map();
571  return FALSE;
572 }
573 
580 int relative_direction(int dx, int dy) {
581  if (dx == 0 && dy == 0) {
582  return 0;
583  } else if (dx == 0 && dy < 0) {
584  return 1;
585  } else if (dx > 0 && dy < 0) {
586  return 2;
587  } else if (dx > 0 && dy == 0) {
588  return 3;
589  } else if (dx > 0 && dy > 0) {
590  return 4;
591  } else if (dx == 0 && dy > 0) {
592  return 5;
593  } else if (dx < 0 && dy > 0) {
594  return 6;
595  } else if (dx < 0 && dy == 0) {
596  return 7;
597  } else if (dx < 0 && dy < 0) {
598  return 8;
599  } else {
600  g_assert_not_reached();
601  }
602 }
603 
609 static void coord_to_tile(int x, int y, int *dx, int *dy) {
610  // Calculate tile below (x, y) coordinates. The top left corner is (0, 0).
611  // This is easy, just floor divide the coordinates by tile size.
612  const float tile_size = map_image_size * use_config[CONFIG_MAPSCALE]/100.0;
613  int mx = x / tile_size;
614  int my = y / tile_size;
615 
616  // Now calculate where the player is drawn. The code below is copied from
617  // gtk_map_redraw() (see the comments there):
618  GtkAllocation size;
619  gtk_widget_get_allocation(map_drawing_area, &size);
620 
621  float scale = use_config[CONFIG_MAPSCALE]/100.0;
622  const double ew = size.width / scale;
623  const double eh = size.height / scale;
624 
625  const int nx = (int)ceilf(ew / map_image_size);
626  const int ny = (int)ceilf(eh / map_image_size);
627 
628  const int vw = use_config[CONFIG_MAPWIDTH];
629  const int vh = use_config[CONFIG_MAPHEIGHT];
630 
631  // Normally, the player is centered in the middle of the server viewport
632  // (with floor division).
633  int ox = vw / 2;
634  int oy = vh / 2;
635 
636  // If mapscale is less than 100, what is shown in the client no longer
637  // matches the viewport. Add the right offset.
638  if (nx > vw) {
639  ox += (nx - vw)/2;
640  }
641 
642  if (ny > vh) {
643  oy += (ny - vh)/2;
644  }
645 
646  // Shift the clicked tile by the player's position.
647  *dx = mx - ox;
648  *dy = my - oy;
649 }
650 
654 static gboolean map_button_event(GtkWidget *widget,
655  GdkEventButton *event, gpointer user_data) {
656  int dx, dy;
657  coord_to_tile((int)event->x, (int)event->y, &dx, &dy);
658  int dir = relative_direction(dx, dy);
659 
660  switch (event->button) {
661  case 1:
662  if (event->type == GDK_BUTTON_PRESS) {
663  look_at(dx,dy);
664  }
665  break;
666  case 2:
667  if (event->type == GDK_BUTTON_RELEASE) {
668  clear_fire();
669  } else {
670  fire_dir(dir);
671  }
672  break;
673  case 3:
674  if (event->type == GDK_BUTTON_PRESS) {
675  set_move_to(dx, dy);
676  run_move_to();
677  }
678  break;
679  }
680 
681  return FALSE;
682 }
683 
691 void display_map_doneupdate(int redraw, int notice) {
692  map_updated |= redraw || !notice;
693 }
mapdata_cell
struct MapCell * mapdata_cell(const int x, const int y)
Get the stored map cell at the given map coordinate.
Definition: mapdata.c:139
redraw
static gboolean redraw(gpointer data)
Redraw the map.
Definition: main.c:137
map_image_size
int map_image_size
Definition: map.c:34
PlayerPosition::x
int x
Definition: client.h:528
draw_smooth_pixmap
static void draw_smooth_pixmap(cairo_t *cr, PixmapInfo *pixmap, const int sx, const int sy, const int dx, const int dy)
Definition: map.c:166
is_at_moveto
bool is_at_moveto()
Definition: mapdata.c:1516
CFG_LT_PIXEL
#define CFG_LT_PIXEL
Definition: client.h:231
ClientSocket::fd
GSocketConnection * fd
Definition: client.h:124
want_offset_x
int want_offset_x
Definition: mapdata.c:92
drawsmooth
static void drawsmooth(cairo_t *cr, int mx, int my, int layer, int picx, int picy)
Draw anything in adjacent squares that could smooth on given square.
Definition: map.c:191
gtk_map_redraw
static void gtk_map_redraw()
Redraw the entire map using GTK.
Definition: map.c:457
move_to_x
int move_to_x
Move to coordinates on the current map.
Definition: mapdata.c:39
do_new_image
void do_new_image(guint8 *data, PixmapInfo *pi)
Wrapper for accessing outside this file.
Definition: image.c:105
pixmaps
PixmapInfo * pixmaps[MAXPIXMAPNUM]
Definition: image.c:34
face_info
Face_Information face_info
Definition: image.c:169
CONFIG_FOGWAR
#define CONFIG_FOGWAR
Definition: client.h:188
FaceSets_struct::size
char * size
Definition: client.h:399
CONFIG_MAPSCALE
#define CONFIG_MAPSCALE
Definition: client.h:190
MIN
#define MIN(X__, Y__)
Definition: client.h:618
font
static cairo_font_face_t * font
Definition: map.c:47
coord_to_tile
static void coord_to_tile(int x, int y, int *dx, int *dy)
Given x, y coordinates on the map drawing area, determine the tile that the coordinates are on with r...
Definition: map.c:609
draw_darkness
static void draw_darkness(cairo_t *cr, int nx, int ny, int mx_start, int my_start)
Definition: map.c:384
draw_move_to
static void draw_move_to(cairo_t *cr, int mx_start, int my_start)
Definition: map.c:431
map_check_resize
void map_check_resize()
Calculate and set desired map size based on map window size.
Definition: map.c:52
mapdata_can_smooth
bool mapdata_can_smooth(int x, int y, int layer)
Definition: mapdata.c:154
move_to_attack
bool move_to_attack
Definition: mapdata.c:40
CONFIG_LIGHTING
#define CONFIG_LIGHTING
Definition: client.h:199
clear_fire
void clear_fire()
Definition: player.c:111
MAP2_LABEL_PLAYER_PARTY
@ MAP2_LABEL_PLAYER_PARTY
Definition: newclient.h:58
PlayerPosition::y
int y
Definition: client.h:529
map_notebook
GtkWidget * map_notebook
Definition: map.c:37
render_debug_layers
int render_debug_layers
Current number of layers to render for renderer debugging purposes.
Definition: p_cmd.c:46
CFG_LT_TILE
#define CFG_LT_TILE
Definition: client.h:230
MapLabel::subtype
int subtype
Definition: mapdata.h:75
mapdata.h
global_offset_y
int global_offset_y
Definition: mapdata.c:91
PixmapInfo::icon_height
guint16 icon_height
Definition: image.h:47
Face_Information_struct::facesets
FaceSets facesets[MAX_FACE_SETS]
Definition: client.h:423
MapCellLayer::face
gint16 face
Definition: mapdata.h:19
DEFAULT_IMAGE_SIZE
#define DEFAULT_IMAGE_SIZE
Definition: image.h:40
map_button_event
static gboolean map_button_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Handle a mouse event in the drawing area.
Definition: map.c:654
time_map_redraw
bool time_map_redraw
Definition: config.c:53
MapCell::heads
struct MapCellLayer heads[MAXLAYERS]
Definition: mapdata.h:64
map_draw_layer
static void map_draw_layer(cairo_t *cr, int layer, int mx_start, int nx, int my_start, int ny)
Draw a single map layer to the given cairo context.
Definition: map.c:304
predict_alpha
int predict_alpha
Speed of local map prediction scrolling, 0-100 (0 to disable).
Definition: config.c:56
move_to_y
int move_to_y
Definition: mapdata.c:39
gtk2proto.h
display_mapscroll
int display_mapscroll(int dx, int dy)
Definition: map.c:177
want_offset_y
int want_offset_y
Definition: mapdata.c:93
map_draw_labels
static void map_draw_labels(cairo_t *cr, int mx_start, int nx, int my_start, int ny)
Definition: map.c:330
MapCell::smooth
guint8 smooth[MAXLAYERS]
Definition: mapdata.h:67
LOG
void LOG(LogLevel level, const char *origin, const char *format,...)
Log messages of a certain importance to stderr.
Definition: misc.c:111
global_offset_x
int global_offset_x
Definition: mapdata.c:90
draw_pixmap
static void draw_pixmap(cairo_t *cr, PixmapInfo *pixmap, int ax, int ay)
Draw a pixmap to the given map tile on screen.
Definition: map.c:159
map_pre_sandbox_init
void map_pre_sandbox_init()
Called before entering the sandbox to cache things like fonts.
Definition: map.c:87
PixmapInfo::smooth_face
guint16 smooth_face
A face used for smoothing with this face.
Definition: image.h:54
MAP_MAX_SIZE
#define MAP_MAX_SIZE
Map size the client will request the map to be.
Definition: client.h:469
CFG_LT_PIXEL_BEST
#define CFG_LT_PIXEL_BEST
Definition: client.h:232
MapLabel
Definition: mapdata.h:74
want_config
gint16 want_config[CONFIG_NUMS]
Definition: init.c:44
csocket
ClientSocket csocket
Definition: client.c:70
MapCell::darkness
guint8 darkness
Definition: mapdata.h:68
image.h
MapLabel::label
char * label
Definition: mapdata.h:76
mapdata_face_info
gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy)
Return the face number of the pixmap in the given map cell and set the offset pointers to indicate wh...
Definition: mapdata.c:1087
image_size
int image_size
Definition: image.c:30
map_expose_event
static gboolean map_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
Definition: map.c:568
mapdata_contains
bool mapdata_contains(int x, int y)
Determine whether the map data contains the given cell.
Definition: mapdata.c:146
FOG
@ FOG
Definition: mapdata.h:46
MAP2_LABEL_DM
@ MAP2_LABEL_DM
Definition: newclient.h:59
set_move_to
void set_move_to(int dx, int dy)
Definition: mapdata.c:1494
draw_map
void draw_map()
Draw the map window using the appropriate backend.
Definition: map.c:545
LOG_ERROR
@ LOG_ERROR
Warning that something definitely didn't work.
Definition: client.h:439
relative_direction
int relative_direction(int dx, int dy)
Given a relative tile coordinate, determine its compass direction.
Definition: map.c:580
main.h
CONFIG_MAPWIDTH
#define CONFIG_MAPWIDTH
Definition: client.h:201
CONFIG_SMOOTH
#define CONFIG_SMOOTH
Definition: client.h:208
PixmapInfo::map_image
void * map_image
Definition: image.h:53
map_init
void map_init(GtkWidget *window_root)
This initializes the stuff we need for the map.
Definition: map.c:108
fire_dir
void fire_dir(int dir)
Definition: player.c:125
Face_Information_struct::faceset
guint8 faceset
Definition: client.h:409
map_drawing_area
static GtkWidget * map_drawing_area
Definition: map.c:38
pl_pos
PlayerPosition pl_pos
Position of the player on the internal map.
Definition: mapdata.c:30
use_config
gint16 use_config[CONFIG_NUMS]
Definition: client.h:245
look_at
void look_at(int x, int y)
Definition: player.c:78
MAXLAYERS
#define MAXLAYERS
The protocol supports 10 layers, so set MAXLAYERS accordingly.
Definition: mapdata.h:6
PixmapInfo
Definition: image.h:43
run_move_to
void run_move_to()
Definition: mapdata.c:1526
mapcell_darkness
static double mapcell_darkness(int mx, int my)
Definition: map.c:376
update_global_offset
static void update_global_offset()
Definition: map.c:534
window_root
GtkWidget * window_root
In main.c.
Definition: main.c:109
resize_map_window
void resize_map_window(int x, int y)
Resize_map_window is a NOOP for the time being - not sure if it will in fact need to do something,...
Definition: map.c:531
CONFIG_MAPHEIGHT
#define CONFIG_MAPHEIGHT
Definition: client.h:202
MapLabel::next
struct MapLabel * next
Definition: mapdata.h:77
display_map_doneupdate
void display_map_doneupdate(int redraw, int notice)
This is called after the map has been all digested.
Definition: map.c:691
rescale_rgba_data
guint8 * rescale_rgba_data(guint8 *data, int *width, int *height, int scale)
Takes png data and scales it accordingly.
Definition: png.c:235
PixmapInfo::icon_width
guint16 icon_width
Definition: image.h:47
map_updated
static gboolean map_updated
Definition: map.c:35
LOG_DEBUG
@ LOG_DEBUG
Useful debugging information.
Definition: client.h:436
client_mapsize
void client_mapsize(int width, int height)
Ask the server for the given map size.
Definition: client.c:171
client.h
MapCell::label
struct MapLabel * label
Definition: mapdata.h:66
window_xml
GtkBuilder * window_xml
Definition: main.c:108