ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.48
Committed: Tue Apr 18 00:14:16 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.47: +54 -32 lines
Log Message:
naive conversion to the visual c++ programming language

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2     # include <malloc.h>
3     #endif
4    
5 root 1.1 #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.5 #include <string.h>
10 root 1.25 #include <stdio.h>
11 root 1.5
12 root 1.2 #include <SDL.h>
13 root 1.23 #include <SDL_image.h>
14 root 1.3 #include <SDL_opengl.h>
15 root 1.5
16 root 1.30 #include <glib/gmacros.h>
17    
18 root 1.5 #include <pango/pango.h>
19 root 1.10 #include <pango/pangofc-fontmap.h>
20 root 1.5 #include <pango/pangoft2.h>
21    
22 root 1.48 #ifndef _WIN32
23     # include <sys/types.h>
24     # include <sys/socket.h>
25     # include <netinet/in.h>
26     # include <netinet/tcp.h>
27     # include <inttypes.h>
28     #else
29     typedef unsigned char uint8_t;
30     typedef unsigned short uint16_t;
31     typedef unsigned int uint32_t;
32     typedef signed char int8_t;
33     typedef signed short int16_t;
34     typedef signed int int32_t;
35     #endif
36 root 1.28
37 root 1.29 #define FOW_DARKNESS 32
38    
39     #define MAP_EXTEND_X 32
40     #define MAP_EXTEND_Y 512
41    
42 root 1.5 static PangoContext *context;
43     static PangoFontMap *fontmap;
44 root 1.2
45 root 1.14 typedef struct cf_layout {
46     PangoLayout *pl;
47     int base_height;
48 root 1.15 } *CFClient__Layout;
49 root 1.14
50     static void
51 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
52     {
53 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
54 root 1.35 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
55 root 1.19 }
56    
57     static void
58 root 1.17 layout_update (CFClient__Layout self)
59     {
60 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
61     * reasonably well with bitstream vera
62     */
63 root 1.17 PangoFontDescription *font = pango_context_get_font_description (context);
64 root 1.46
65     int height = self->base_height * (PANGO_SCALE * 8 / 10);
66    
67     if (pango_font_description_get_size (font) != height)
68     {
69     pango_font_description_set_absolute_size (font, height);
70     pango_layout_context_changed (self->pl);
71     }
72 root 1.17 }
73    
74     static void
75 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
76 root 1.14 {
77 root 1.19 layout_update (self);
78 root 1.16
79 root 1.14 pango_layout_get_pixel_size (self->pl, w, h);
80    
81     *w = (*w + 3) & ~3;
82     if (!*w) *w = 1;
83     if (!*h) *h = 1;
84     }
85    
86 root 1.42 typedef uint16_t mapface;
87    
88 root 1.28 typedef struct {
89 root 1.30 GLint name;
90     int w, h;
91     float s, t;
92 root 1.39 uint8_t r, g, b, a;
93 root 1.42 } maptex;
94 root 1.30
95     typedef struct {
96 root 1.29 int16_t darkness;
97 root 1.42 mapface face[3];
98 root 1.28 } mapcell;
99    
100     typedef struct {
101 root 1.30 int32_t c0, c1;
102 root 1.28 mapcell *col;
103     } maprow;
104    
105     typedef struct map {
106     int x, y, w, h;
107 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
108 root 1.28 int faces;
109 root 1.30 mapface *face;
110 root 1.28
111 root 1.42 int texs;
112     maptex *tex;
113    
114 root 1.48 int32_t rows;
115 root 1.28 maprow *row;
116     } *CFClient__Map;
117    
118 root 1.30 static char *
119     prepend (char *ptr, int sze, int inc)
120     {
121     char *p;
122    
123     New (0, p, sze + inc, char);
124     Zero (p, inc, char);
125     Move (ptr, p + inc, sze, char);
126     Safefree (ptr);
127    
128     return p;
129     }
130    
131     static char *
132     append (char *ptr, int sze, int inc)
133     {
134     Renew (ptr, sze + inc, char);
135     Zero (ptr + sze, inc, char);
136    
137     return ptr;
138     }
139    
140     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
141     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
142    
143 root 1.42 static maprow *
144     map_get_row (CFClient__Map self, int y)
145     {
146     if (0 > y)
147     {
148     int extend = - y + MAP_EXTEND_Y;
149     Prepend (maprow, self->row, self->rows, extend);
150    
151     self->rows += extend;
152     self->y += extend;
153     y += extend;
154     }
155     else if (y >= self->rows)
156     {
157     int extend = y - self->rows + MAP_EXTEND_Y;
158     Append (maprow, self->row, self->rows, extend);
159     self->rows += extend;
160     }
161    
162     return self->row + y;
163     }
164    
165     static mapcell *
166     row_get_cell (maprow *row, int x)
167     {
168     if (!row->col)
169     {
170     Newz (0, row->col, MAP_EXTEND_X, mapcell);
171     row->c0 = x - MAP_EXTEND_X / 4;
172     row->c1 = row->c0 + MAP_EXTEND_X;
173     }
174    
175     if (row->c0 > x)
176     {
177     int extend = row->c0 - x + MAP_EXTEND_X;
178     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
179     row->c0 -= extend;
180     }
181     else if (x >= row->c1)
182     {
183     int extend = x - row->c1 + MAP_EXTEND_X;
184     Append (mapcell, row->col, row->c1 - row->c0, extend);
185     row->c1 += extend;
186     }
187    
188     return row->col + (x - row->c0);
189     }
190    
191     static mapcell *
192     map_get_cell (CFClient__Map self, int x, int y)
193     {
194     return row_get_cell (map_get_row (self, y), x);
195     }
196    
197 root 1.30 static void
198     map_clear (CFClient__Map self)
199     {
200     int r;
201    
202     for (r = 0; r < self->rows; r++)
203     Safefree (self->row[r].col);
204    
205     Safefree (self->row);
206    
207     self->x = 0;
208     self->y = 0;
209 root 1.42 self->ox = 0;
210     self->oy = 0;
211 root 1.30 self->row = 0;
212     self->rows = 0;
213     }
214    
215 root 1.29 static void
216     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
217     {
218     int x, y;
219 root 1.48 maprow *row;
220 root 1.29
221     for (y = y0; y < y0 + h; y++)
222 root 1.30 if (y >= 0)
223     {
224     if (y >= self->rows)
225     break;
226    
227 root 1.48 row = self->row + y;
228 root 1.30
229     for (x = x0; x < x0 + w; x++)
230     if (x >= row->c0)
231     {
232     if (x >= row->c1)
233     break;
234 root 1.29
235 root 1.31 row->col[x - row->c0].darkness = -1;
236 root 1.30 }
237     }
238 root 1.29 }
239    
240 root 1.15 MODULE = CFClient PACKAGE = CFClient
241 root 1.1
242 root 1.11 PROTOTYPES: ENABLE
243    
244 root 1.5 BOOT:
245     {
246     fontmap = pango_ft2_font_map_new ();
247 root 1.19 pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0);
248 root 1.8 context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap);
249 root 1.5 }
250    
251 root 1.10 void
252     lowdelay (int fd, int val = 1)
253     CODE:
254 root 1.48 #ifndef _WIN32
255 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
256 root 1.48 #endif
257 root 1.10
258 root 1.3 char *
259 root 1.4 gl_version ()
260     CODE:
261 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
262 root 1.4 OUTPUT:
263     RETVAL
264    
265     char *
266 root 1.3 gl_extensions ()
267     CODE:
268 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
269 root 1.3 OUTPUT:
270     RETVAL
271    
272 root 1.5 void
273 root 1.13 add_font (char *file)
274     CODE:
275     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
276    
277     void
278 root 1.9 set_font (char *file)
279 root 1.8 CODE:
280     {
281 root 1.9 int count;
282     FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)file, 0, 0, &count);
283 root 1.10 PangoFontDescription *font = pango_fc_font_description_from_pattern (pattern, 0);
284 root 1.9 FcPatternDestroy (pattern);
285 root 1.8 pango_context_set_font_description (context, font);
286     }
287    
288 root 1.23 void
289     load_image_inline (SV *image_)
290     ALIAS:
291     load_image_file = 1
292     PPCODE:
293     {
294     STRLEN image_len;
295     char *image = (char *)SvPVbyte (image_, image_len);
296     SDL_Surface *surface, *surface2;
297     SDL_PixelFormat fmt;
298     SDL_RWops *rw = ix
299     ? SDL_RWFromFile (image, "r")
300     : SDL_RWFromConstMem (image, image_len);
301    
302     if (!rw)
303 root 1.41 croak ("load_image: %s", SDL_GetError ());
304 root 1.23
305     surface = IMG_Load_RW (rw, 1);
306     if (!surface)
307 root 1.41 croak ("load_image: %s", SDL_GetError ());
308 root 1.23
309     fmt.palette = NULL;
310     fmt.BitsPerPixel = 32;
311     fmt.BytesPerPixel = 4;
312     fmt.Rmask = 0x000000ff;
313     fmt.Gmask = 0x0000ff00;
314     fmt.Bmask = 0x00ff0000;
315     fmt.Amask = 0xff000000;
316     fmt.Rloss = 0;
317     fmt.Gloss = 0;
318     fmt.Bloss = 0;
319     fmt.Aloss = 0;
320     fmt.Rshift = 0;
321     fmt.Gshift = 8;
322     fmt.Bshift = 16;
323     fmt.Ashift = 24;
324     fmt.colorkey = 0;
325     fmt.alpha = 0;
326    
327     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
328    
329 root 1.39 assert (surface2->pitch == surface2->w * 4);
330    
331 root 1.23 EXTEND (SP, 5);
332     PUSHs (sv_2mortal (newSViv (surface2->w)));
333     PUSHs (sv_2mortal (newSViv (surface2->h)));
334     SDL_LockSurface (surface2);
335     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
336     SDL_UnlockSurface (surface2);
337 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
338 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
339     PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_INT_8_8_8_8_REV)));
340    
341     SDL_FreeSurface (surface);
342     SDL_FreeSurface (surface2);
343     }
344    
345 root 1.25 void
346 root 1.39 average (int x, int y, uint32_t *data)
347     PPCODE:
348     {
349     uint32_t r = 0, g = 0, b = 0, a = 0;
350    
351     x = y = x * y;
352    
353     while (x--)
354     {
355     uint32_t p = *data++;
356    
357     r += (p ) & 255;
358     g += (p >> 8) & 255;
359     b += (p >> 16) & 255;
360     a += (p >> 24) & 255;
361     }
362    
363     EXTEND (SP, 4);
364 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
365     PUSHs (sv_2mortal (newSViv (g / y)));
366     PUSHs (sv_2mortal (newSViv (b / y)));
367     PUSHs (sv_2mortal (newSViv (a / y)));
368 root 1.39 }
369    
370     void
371 root 1.25 fatal (char *message)
372     CODE:
373     #ifdef WIN32
374     MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
375     #else
376 root 1.40 fprintf (stderr, "FATAL: %s\n", message);
377 root 1.25 #endif
378     exit (1);
379    
380 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
381 root 1.14
382 root 1.15 CFClient::Layout
383 root 1.14 new (SV *class, int base_height = 10)
384     CODE:
385     New (0, RETVAL, 1, struct cf_layout);
386     RETVAL->base_height = base_height;
387     RETVAL->pl = pango_layout_new (context);
388     pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
389     OUTPUT:
390     RETVAL
391    
392     void
393 root 1.15 DESTROY (CFClient::Layout self)
394 root 1.14 CODE:
395     g_object_unref (self->pl);
396     Safefree (self);
397 root 1.13
398 root 1.8 void
399 root 1.35 set_text (CFClient::Layout self, SV *text_)
400     CODE:
401     {
402     STRLEN textlen;
403     char *text = SvPVutf8 (text_, textlen);
404    
405     pango_layout_set_text (self->pl, text, textlen);
406     }
407    
408     void
409 root 1.15 set_markup (CFClient::Layout self, SV *text_)
410 root 1.14 CODE:
411 root 1.5 {
412     STRLEN textlen;
413     char *text = SvPVutf8 (text_, textlen);
414 root 1.14
415     pango_layout_set_markup (self->pl, text, textlen);
416     }
417    
418 root 1.46 SV *
419     get_text (CFClient::Layout self)
420     CODE:
421 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
422 root 1.46 SvUTF8_on (RETVAL);
423     OUTPUT:
424     RETVAL
425    
426 root 1.14 void
427 root 1.16 set_height (CFClient::Layout self, int base_height)
428     CODE:
429     self->base_height = base_height;
430    
431     void
432 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
433 root 1.14 CODE:
434     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
435    
436     void
437 root 1.15 size (CFClient::Layout self)
438 root 1.14 PPCODE:
439     {
440     int w, h;
441    
442 root 1.17 layout_update (self);
443 root 1.14 layout_get_pixel_size (self, &w, &h);
444    
445     EXTEND (SP, 2);
446     PUSHs (sv_2mortal (newSViv (w)));
447     PUSHs (sv_2mortal (newSViv (h)));
448     }
449    
450 root 1.17 int
451     xy_to_index (CFClient::Layout self, int x, int y)
452     CODE:
453     {
454     int index, trailing;
455    
456     layout_update (self);
457     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
458    
459     RETVAL = index;
460     }
461     OUTPUT:
462     RETVAL
463    
464     void
465     cursor_pos (CFClient::Layout self, int index)
466     PPCODE:
467     {
468     PangoRectangle strong_pos;
469     layout_update (self);
470     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
471 root 1.30
472 root 1.17 EXTEND (SP, 3);
473     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
474     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
475     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
476     }
477    
478 root 1.14 void
479 root 1.15 render (CFClient::Layout self)
480 root 1.14 PPCODE:
481     {
482 root 1.5 SV *retval;
483     int w, h;
484     FT_Bitmap bitmap;
485    
486 root 1.17 layout_update (self);
487 root 1.14 layout_get_pixel_size (self, &w, &h);
488 root 1.5
489     retval = newSV (w * h);
490     SvPOK_only (retval);
491     SvCUR_set (retval, w * h);
492    
493     bitmap.rows = h;
494     bitmap.width = w;
495     bitmap.pitch = w;
496     bitmap.buffer = (unsigned char*)SvPVX (retval);
497     bitmap.num_grays = 256;
498     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
499    
500     memset (bitmap.buffer, 0, w * h);
501    
502 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
503 root 1.1
504 root 1.5 EXTEND (SP, 3);
505     PUSHs (sv_2mortal (newSViv (w)));
506     PUSHs (sv_2mortal (newSViv (h)));
507     PUSHs (sv_2mortal (retval));
508     }
509 root 1.11
510 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
511 root 1.11
512     void
513 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
514 root 1.12 PROTOTYPE: $$$;$$
515 root 1.11 CODE:
516     {
517 root 1.12 HV *hv = (HV *)SvRV (self);
518 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
519     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
520 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
521 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
522 root 1.12
523     if (items < 5)
524     {
525 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
526     h = SvNV (*hv_fetch (hv, "h", 1, 1));
527 root 1.12 }
528    
529     glBindTexture (GL_TEXTURE_2D, name);
530 elmex 1.36 if (wrap_mode) {
531     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
532     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
533     }
534 root 1.12 glBegin (GL_QUADS);
535 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
536     glTexCoord2f (0, t); glVertex2f (x , y + h);
537     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
538     glTexCoord2f (s, 0); glVertex2f (x + w, y );
539 root 1.12 glEnd ();
540 root 1.11 }
541 root 1.28
542     MODULE = CFClient PACKAGE = CFClient::Map
543    
544     CFClient::Map
545     new (SV *class, int map_width, int map_height)
546     CODE:
547     New (0, RETVAL, 1, struct map);
548 root 1.42 RETVAL->x = 0;
549     RETVAL->y = 0;
550     RETVAL->w = map_width;
551     RETVAL->h = map_height;
552     RETVAL->ox = 0;
553     RETVAL->oy = 0;
554 root 1.30 RETVAL->faces = 8192;
555     Newz (0, RETVAL->face, RETVAL->faces, mapface);
556 root 1.42 RETVAL->texs = 8192;
557     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
558 root 1.28 RETVAL->rows = 0;
559     RETVAL->row = 0;
560     OUTPUT:
561     RETVAL
562    
563     void
564     DESTROY (CFClient::Map self)
565     CODE:
566     {
567 root 1.30 map_clear (self);
568 root 1.28 Safefree (self->face);
569 root 1.29 Safefree (self);
570     }
571    
572     void
573 root 1.30 clear (CFClient::Map self)
574     CODE:
575     map_clear (self);
576    
577     void
578 root 1.42 set_face (CFClient::Map self, int face, int texid)
579 root 1.29 CODE:
580     {
581 root 1.42 while (self->faces <= face)
582 root 1.28 {
583 root 1.30 Append (mapface, self->face, self->faces, self->faces);
584 root 1.29 self->faces *= 2;
585     }
586 root 1.28
587 root 1.42 self->face [face] = texid;
588     }
589    
590     void
591     set_texture (CFClient::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
592     CODE:
593     {
594     while (self->texs <= texid)
595     {
596     Append (maptex, self->tex, self->texs, self->texs);
597     self->texs *= 2;
598     }
599    
600 root 1.48 {
601     maptex *tex = self->tex + texid;
602 root 1.39
603 root 1.48 tex->name = name;
604     tex->w = w;
605     tex->h = h;
606     tex->s = s;
607     tex->t = t;
608     tex->r = r;
609     tex->g = g;
610     tex->b = b;
611     tex->a = a;
612     }
613 root 1.29 }
614    
615 root 1.42 int
616     ox (CFClient::Map self)
617     ALIAS:
618     oy = 1
619     CODE:
620     switch (ix)
621     {
622     case 0: RETVAL = self->ox; break;
623     case 1: RETVAL = self->oy; break;
624     }
625     OUTPUT:
626     RETVAL
627    
628 root 1.29 void
629 root 1.43 scroll (CFClient::Map self, int dx, int dy)
630     CODE:
631     {
632 root 1.44 if (dx > 0)
633     map_blank (self, self->x, self->y, dx - 1, self->h);
634     else if (dx < 0)
635     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
636    
637     if (dy > 0)
638     map_blank (self, self->x, self->y, self->w, dy - 1);
639     else if (dy < 0)
640     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
641 root 1.43
642 root 1.44 self->ox += dx; self->x += dx;
643     self->oy += dy; self->y += dy;
644 root 1.43
645     while (self->y < 0)
646     {
647     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
648    
649     self->rows += MAP_EXTEND_Y;
650     self->y += MAP_EXTEND_Y;
651     }
652 root 1.44 }
653 root 1.43
654 root 1.44 void
655     map1a_update (CFClient::Map self, SV *data_)
656     CODE:
657     {
658 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
659     uint8_t *data_end = (uint8_t *)SvEND (data_);
660 root 1.48 mapcell *cell;
661     int x, y, flags;
662 root 1.43
663 root 1.29 while (data < data_end)
664     {
665 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
666 root 1.30
667 root 1.48 x = ((flags >> 10) & 63) + self->x;
668     y = ((flags >> 4) & 63) + self->y;
669 root 1.29
670 root 1.48 cell = map_get_cell (self, x, y);
671 root 1.29
672     if (flags & 15)
673     {
674 root 1.45 if (cell->darkness < 0)
675 root 1.29 {
676     cell->darkness = 0;
677     cell->face [0] = 0;
678     cell->face [1] = 0;
679     cell->face [2] = 0;
680     }
681 root 1.45
682 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
683    
684 root 1.42 //TODO: don't trust server data to be in-range(!)
685    
686 root 1.29 if (flags & 4)
687     {
688 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
689 root 1.29 }
690    
691     if (flags & 2)
692     {
693 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
694 root 1.29 }
695    
696     if (flags & 1)
697     {
698 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
699 root 1.29 }
700     }
701     else
702 root 1.31 cell->darkness = -1;
703 root 1.29 }
704 root 1.28 }
705    
706 root 1.40 SV *
707     mapmap (CFClient::Map self, int w, int h)
708     CODE:
709     {
710     int x0, x1, x;
711     int y0, y1, y;
712     int z;
713     SV *map_sv = newSV (w * h * sizeof (uint32_t));
714     uint32_t *map = (uint32_t *)SvPVX (map_sv);
715    
716     SvPOK_only (map_sv);
717     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
718    
719     x0 = self->x - w / 2; x1 = x0 + w;
720     y0 = self->y - h / 2; y1 = y0 + h;
721    
722     for (y = y0; y < y1; y++)
723     {
724     maprow *row = 0 <= y && y < self->rows
725     ? self->row + y
726     : 0;
727    
728     for (x = x0; x < x1; x++)
729     {
730     int r = 32, g = 32, b = 32, a = 192;
731    
732     if (row && row->c0 <= x && x < row->c1)
733     {
734     mapcell *cell = row->col + (x - row->c0);
735    
736     for (z = 0; z <= 0; z++)
737     {
738 root 1.42 mapface face = cell->face [z];
739 root 1.40
740     if (face)
741     {
742 root 1.42 maptex tex = self->tex [face];
743 root 1.40 int a0 = 255 - tex.a;
744     int a1 = tex.a;
745    
746     r = (r * a0 + tex.r * a1) / 255;
747     g = (g * a0 + tex.g * a1) / 255;
748     b = (b * a0 + tex.b * a1) / 255;
749     a = (a * a0 + tex.a * a1) / 255;
750     }
751     }
752     }
753    
754     *map++ = (r )
755     | (g << 8)
756     | (b << 16)
757     | (a << 24);
758     }
759     }
760    
761     RETVAL = map_sv;
762     }
763     OUTPUT:
764     RETVAL
765    
766 root 1.30 void
767 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
768 root 1.32 PPCODE:
769 root 1.30 {
770 root 1.48 int vx, vy;
771     int x, y, z;
772     int last_name;
773     mapface face;
774 root 1.32 int sw4 = (sw + 3) & ~3;
775     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
776 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
777 root 1.48
778 root 1.42 memset (darkness, 255, sw4 * sh);
779 root 1.32 SvPOK_only (darkness_sv);
780     SvCUR_set (darkness_sv, sw4 * sh);
781    
782 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
783     vy = self->y + (self->h - sh) / 2 - shift_y;
784 root 1.38
785 root 1.42 /*
786     int vx = self->vx = self->w >= sw
787     ? self->x + (self->w - sw) / 2
788     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
789    
790     int vy = self->vy = self->h >= sh
791     ? self->y + (self->h - sh) / 2
792     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
793     */
794 root 1.30
795     glColor4ub (255, 255, 255, 255);
796    
797     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
798     glEnable (GL_BLEND);
799     glEnable (GL_TEXTURE_2D);
800     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
801    
802 root 1.48 glBegin (GL_QUADS);
803 root 1.30
804 root 1.48 last_name = 0;
805 root 1.30
806     for (z = 0; z < 3; z++)
807     for (y = 0; y < sh; y++)
808     if (0 <= y + vy && y + vy < self->rows)
809     {
810     maprow *row = self->row + (y + vy);
811    
812     for (x = 0; x < sw; x++)
813     if (row->c0 <= x + vx && x + vx < row->c1)
814     {
815     mapcell *cell = row->col + (x + vx - row->c0);
816 root 1.32
817     darkness[y * sw4 + x] = cell->darkness < 0
818 root 1.33 ? 255 - FOW_DARKNESS
819 root 1.32 : 255 - cell->darkness;
820    
821 root 1.48 face = cell->face [z];
822 root 1.30
823     if (face)
824     {
825 root 1.42 maptex tex = self->tex [face];
826 root 1.30
827     int px = (x + 1) * 32 - tex.w;
828     int py = (y + 1) * 32 - tex.h;
829    
830     if (last_name != tex.name)
831     {
832     glEnd ();
833     last_name = tex.name;
834     glBindTexture (GL_TEXTURE_2D, last_name);
835     glBegin (GL_QUADS);
836     }
837    
838     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
839     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
840     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
841     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
842     }
843     }
844     }
845    
846     glEnd ();
847 root 1.32
848 root 1.34 glDisable (GL_TEXTURE_2D);
849     glDisable (GL_BLEND);
850    
851 root 1.32 EXTEND (SP, 3);
852     PUSHs (sv_2mortal (newSViv (sw4)));
853     PUSHs (sv_2mortal (newSViv (sh)));
854     PUSHs (darkness_sv);
855 root 1.30 }
856    
857 root 1.42 SV *
858     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
859     CODE:
860     {
861     int x, y, x1, y1;
862     SV *data_sv = newSV (w * h * 7 + 5);
863     uint8_t *data = (uint8_t *)SvPVX (data_sv);
864    
865     *data++ = 0; /* version 0 format */
866     *data++ = w >> 8; *data++ = w;
867     *data++ = h >> 8; *data++ = h;
868    
869     // we need to do this 'cause we don't keep an absolute coord system for rows
870     // TODO: treat rows as we treat
871     map_get_row (self, y0 + self->y - self->oy);//D
872     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
873    
874     x0 += self->x - self->ox;
875     y0 += self->y - self->oy;
876    
877     x1 = x0 + w;
878     y1 = y0 + h;
879    
880     for (y = y0; y < y1; y++)
881     {
882     maprow *row = 0 <= y && y < self->rows
883     ? self->row + y
884     : 0;
885    
886     for (x = x0; x < x1; x++)
887     {
888     if (row && row->c0 <= x && x < row->c1)
889     {
890     mapcell *cell = row->col + (x - row->c0);
891     uint8_t flags = 0;
892    
893     if (cell->face [0]) flags |= 1;
894     if (cell->face [1]) flags |= 2;
895     if (cell->face [2]) flags |= 4;
896    
897     *data++ = flags;
898    
899     if (flags & 1)
900     {
901     *data++ = cell->face [0] >> 8;
902     *data++ = cell->face [0];
903     }
904    
905     if (flags & 2)
906     {
907     *data++ = cell->face [1] >> 8;
908     *data++ = cell->face [1];
909     }
910    
911     if (flags & 4)
912     {
913     *data++ = cell->face [2] >> 8;
914     *data++ = cell->face [2];
915     }
916     }
917     else
918     *data++ = 0;
919     }
920     }
921    
922     SvPOK_only (data_sv);
923     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
924     RETVAL = data_sv;
925     }
926     OUTPUT:
927     RETVAL
928    
929     void
930     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
931     PPCODE:
932     {
933     int x, y, z;
934 root 1.48 int w, h;
935 root 1.42 int x1, y1;
936    
937     if (*data++ != 0)
938     return; /* version mismatch */
939    
940 root 1.48 w = *data++ << 8; w |= *data++;
941     h = *data++ << 8; h |= *data++;
942 root 1.42
943     // we need to do this 'cause we don't keep an absolute coord system for rows
944     // TODO: treat rows as we treat
945     map_get_row (self, y0 + self->y - self->oy);//D
946     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
947    
948     x0 += self->x - self->ox;
949     y0 += self->y - self->oy;
950    
951     x1 = x0 + w;
952     y1 = y0 + h;
953    
954     for (y = y0; y < y1; y++)
955     {
956     maprow *row = map_get_row (self, y);
957    
958     for (x = x0; x < x1; x++)
959     {
960     uint8_t flags = *data++;
961    
962     if (flags)
963     {
964     mapface face[3] = { 0, 0, 0 };
965    
966     mapcell *cell = row_get_cell (row, x);
967    
968     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
969     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
970     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
971    
972     if (cell->darkness <= 0)
973     {
974     cell->darkness = -1;
975    
976     for (z = 0; z <= 2; z++)
977     {
978     cell->face[z] = face[z];
979    
980     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
981     XPUSHs (sv_2mortal (newSViv (face[z])));
982     }
983     }
984     }
985     }
986     }
987     }
988