ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/image.C
(Generate patch)

Comparing deliantra/server/common/image.C (file contents):
Revision 1.6 by root, Sun Sep 10 16:00:23 2006 UTC vs.
Revision 1.19 by root, Sun Mar 11 02:12:44 2007 UTC

1
2/* 1/*
3 * static char *rcsid_image_c = 2 * CrossFire, A Multiplayer game
4 * "$Id: image.C,v 1.6 2006/09/10 16:00:23 root Exp $"; 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (C) 1992 Frank Tore Johansen
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 maintainer of this code can be reached at <crossfire@schmorp.de>
5 */ 23 */
6
7/*
8 CrossFire, A Multiplayer game for X-windows
9
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27 The maintainer of this code can be reached at crossfire-devel@real-time.com
28*/
29 24
30 25
31#include <global.h> 26#include <global.h>
32#include <stdio.h> 27#include <stdio.h>
33 28
34New_Face *new_faces; 29#include "face.h"
30#include "crc.h"
35 31
36/* bmappair and xbm are used when looking for the image id numbers 32faceidx blank_face, empty_face;
37 * of a face by name. xbm is sorted alphabetically so that bsearch
38 * can be used to quickly find the entry for a name. the number is
39 * then an index into the new_faces array.
40 * This data is redundant with new_face information - the difference
41 * is that this data gets sorted, and that doesn't necessarily happen
42 * with the new_face data - when accessing new_face[some number],
43 * that some number corresponds to the face at that number - for
44 * xbm, it may not. At current time, these do in fact match because
45 * the bmaps file is created in a sorted order.
46 */
47 33
48struct bmappair 34facehash_t facehash;
49{ 35std::vector<faceinfo> faces;
50 char *name; 36std::vector<facedata> face32, face64;
51 unsigned int number;
52};
53
54void free (bmappair *); // guard to catch free when delete should be used
55
56static struct bmappair *xbm = NULL;
57
58/* Following can just as easily be pointers, but
59 * it is easier to keep them like this.
60 */
61New_Face *blank_face, *dark_faces[3], *empty_face, *smooth_face;
62
63
64/* nroffiles is the actual number of bitmaps defined.
65 * nrofpixmaps is the number of bitmaps loaded. With
66 * the automatic generation of the bmaps file, this is now equal
67 * to nroffiles.
68 *
69 * The xbm array (which contains name and number information, and
70 * is then sorted) contains nroffiles entries. the xbm_names
71 * array (which is used for converting the numeric face to
72 * a name) contains nrofpixmaps entries.
73 */
74static int nroffiles = 0;
75int nrofpixmaps = 0;
76 37
77/** 38/**
78 * id is the face to smooth, smooth is the 16x2 face used to smooth id. 39 * id is the face to smooth, smooth is the 16x2 face used to smooth id.
79 */ 40 */
80struct smoothing:zero_initialised 41struct smoothing : zero_initialised
81{ 42{
82 uint16 id; 43 uint16 id;
83 uint16 smooth; 44 uint16 smooth;
84}; 45};
85
86void free (smoothing *); // guard to catch free when delete should be used
87 46
88/** 47/**
89 * Contains all defined smoothing entries. smooth is an array of nrofsmooth 48 * Contains all defined smoothing entries. smooth is an array of nrofsmooth
90 * entries. It is sorted by smooth[].id. 49 * entries. It is sorted by smooth[].id.
91 */ 50 */
113 "yellow", /* 11 */ 72 "yellow", /* 11 */
114 "khaki" /* 12 */ 73 "khaki" /* 12 */
115}; 74};
116 75
117static int 76static int
118compar (const struct bmappair *a, const struct bmappair *b)
119{
120 return strcmp (a->name, b->name);
121}
122static int
123compar_smooth (const struct smoothing *a, const struct smoothing *b) 77compar_smooth (const struct smoothing *a, const struct smoothing *b)
124{ 78{
125 if (a->id < b->id) 79 if (a->id < b->id)
126 return -1; 80 return -1;
127 if (b->id < a->id) 81 if (b->id < a->id)
128 return 1; 82 return 1;
129 return 0; 83 return 0;
130} 84}
131 85
132
133/* 86/*
134 * Returns the matching color in the coloralias if found, 87 * Returns the matching color in the coloralias if found,
135 * 0 otherwise. Note that 0 will actually be black, so there is no 88 * 0 otherwise. Note that 0 will actually be black, so there is no
136 * way the calling function can tell if an error occurred or not 89 * way the calling function can tell if an error occurred or not
137 */ 90 */
138
139static uint8 91static uint8
140find_color (const char *name) 92find_color (const char *name)
141{ 93{
142 uint8 i; 94 uint8 i;
143 95
144 for (i = 0; i < sizeof (colorname) / sizeof (*colorname); i++) 96 for (i = 0; i < sizeof (colorname) / sizeof (*colorname); i++)
145 if (!strcmp (name, colorname[i])) 97 if (!strcmp (name, colorname[i]))
146 return i; 98 return i;
99
147 LOG (llevError, "Unknown color: %s\n", name); 100 LOG (llevError, "Unknown color: %s\n", name);
148 return 0; 101 return 0;
149} 102}
150 103
151/* This reads the lib/faces file, getting color and visibility information. 104int
152 * it is called by ReadBmapNames. 105face_find (const char *name, int defidx)
153 */ 106{
107 facehash_t::iterator i = facehash.find (name);
154 108
155static void 109 return i == facehash.end ()
156ReadFaceData (void) 110 ? defidx : i->second;
157{
158 char buf[MAX_BUF], *cp;
159 New_Face *on_face = NULL;
160 FILE *fp;
161
162 sprintf (buf, "%s/faces", settings.datadir);
163 LOG (llevDebug, "Reading faces from %s...", buf);
164 if ((fp = fopen (buf, "r")) == NULL)
165 {
166 LOG (llevError, "Cannot open faces file %s: %s\n", buf, strerror (errno));
167 exit (-1);
168 }
169 while (fgets (buf, MAX_BUF, fp) != NULL)
170 {
171 if (*buf == '#')
172 continue;
173 if (!strncmp (buf, "end", 3))
174 {
175 on_face = NULL;
176 }
177 else if (!strncmp (buf, "face", 4))
178 {
179 int tmp;
180
181 cp = buf + 5;
182 cp[strlen (cp) - 1] = '\0'; /* remove newline */
183
184 if ((tmp = FindFace (cp, -1)) == -1)
185 {
186 LOG (llevError, "Could not find face %s\n", cp);
187 continue;
188 }
189 on_face = &new_faces[tmp];
190 on_face->visibility = 0;
191 }
192 else if (on_face == NULL)
193 {
194 LOG (llevError, "Got line with no face set: %s\n", buf);
195 }
196 else if (!strncmp (buf, "color_fg", 8))
197 {
198 cp = buf + 9;
199 cp[strlen (cp) - 1] = '\0';
200 if (on_face->magicmap == 255)
201 on_face->magicmap = find_color (cp);
202 }
203 else if (!strncmp (buf, "color_bg", 8))
204 {
205 /* ignore it */
206 }
207 else if (!strncmp (buf, "visibility", 10))
208 {
209 on_face->visibility = atoi (buf + 11);
210 }
211 else if (!strncmp (buf, "magicmap", 8))
212 {
213 cp = buf + 9;
214 cp[strlen (cp) - 1] = '\0';
215 on_face->magicmap = find_color (cp);
216 }
217 else if (!strncmp (buf, "is_floor", 8))
218 {
219 int value = atoi (buf + 9);
220
221 if (value)
222 on_face->magicmap |= FACE_FLOOR;
223 }
224 else
225 LOG (llevDebug, "Got unknown line in faces file: %s\n", buf);
226 }
227 LOG (llevDebug, "done\n");
228 fclose (fp);
229} 111}
230 112
231/* This reads the bmaps file to get all the bitmap names and 113facedata *
232 * stuff. It only needs to be done once, because it is player 114face_data (int idx, int faceset)
233 * independent (ie, what display the person is on will not make a
234 * difference.)
235 */
236
237void
238ReadBmapNames (void)
239{ 115{
240 char buf[MAX_BUF], *p, *q; 116 return &(faceset ? face64 : face32)[idx];
241 FILE *fp;
242 int value, nrofbmaps = 0, i;
243 size_t l;
244
245 bmaps_checksum = 0;
246 sprintf (buf, "%s/bmaps", settings.datadir);
247 LOG (llevDebug, "Reading bmaps from %s...", buf);
248 if ((fp = fopen (buf, "r")) == NULL)
249 {
250 LOG (llevError, "Cannot open bmaps file %s: %s\n", buf, strerror (errno));
251 exit (-1);
252 }
253
254 /* First count how many bitmaps we have, so we can allocate correctly */
255 while (fgets (buf, MAX_BUF, fp) != NULL)
256 if (buf[0] != '#' && buf[0] != '\n')
257 nrofbmaps++;
258 rewind (fp);
259
260 xbm = new bmappair[nrofbmaps];
261 memset (xbm, 0, sizeof (struct bmappair) * nrofbmaps);
262
263 while (nroffiles < nrofbmaps && fgets (buf, MAX_BUF, fp) != NULL)
264 {
265 if (*buf == '#')
266 continue;
267
268 p = (*buf == '\\') ? (buf + 1) : buf;
269 if (!(p = strtok (p, " \t")) || !(q = strtok (NULL, " \t\n")))
270 {
271 LOG (llevDebug, "Warning, syntax error: %s\n", buf);
272 continue;
273 }
274 value = atoi (p);
275 xbm[nroffiles].name = strdup_local (q);
276
277 /* We need to calculate the checksum of the bmaps file
278 * name->number mapping to send to the client. This does not
279 * need to match what sum or other utility may come up with -
280 * as long as we get the same results on the same real file
281 * data, it does the job as it lets the client know if
282 * the file has the same data or not.
283 */
284 ROTATE_RIGHT (bmaps_checksum);
285 bmaps_checksum += value & 0xff;
286 bmaps_checksum &= 0xffffffff;
287
288 ROTATE_RIGHT (bmaps_checksum);
289 bmaps_checksum += (value >> 8) & 0xff;
290 bmaps_checksum &= 0xffffffff;
291 for (l = 0; l < strlen (q); l++)
292 {
293 ROTATE_RIGHT (bmaps_checksum);
294 bmaps_checksum += q[l];
295 bmaps_checksum &= 0xffffffff;
296 }
297
298 xbm[nroffiles].number = value;
299 nroffiles++;
300 if (value >= nrofpixmaps)
301 nrofpixmaps = value + 1;
302 }
303 fclose (fp);
304
305 LOG (llevDebug, "done (got %d/%d/%d)\n", nrofpixmaps, nrofbmaps, nroffiles);
306
307 new_faces = new New_Face[nrofpixmaps];
308
309 for (i = 0; i < nrofpixmaps; i++)
310 {
311 new_faces[i].name = "";
312 new_faces[i].number = i;
313 new_faces[i].visibility = 0;
314 new_faces[i].magicmap = 255;
315 }
316 for (i = 0; i < nroffiles; i++)
317 {
318 new_faces[xbm[i].number].name = xbm[i].name;
319 }
320
321 // non-pod datatype, likely not allowed
322 qsort (xbm, nroffiles, sizeof (struct bmappair), (int (*)(const void *, const void *)) compar);
323
324 ReadFaceData ();
325
326 for (i = 0; i < nrofpixmaps; i++)
327 {
328 if (new_faces[i].magicmap == 255)
329 {
330#if 0 /* Useful for initial debugging, not needed now */
331 LOG (llevDebug, "Face %s still had default magicmap, resetting to black\n", new_faces[i].name);
332#endif
333 new_faces[i].magicmap = 0;
334 }
335 }
336 /* Actually forcefully setting the colors here probably should not
337 * be done - it could easily create confusion.
338 */
339 blank_face = &new_faces[FindFace (BLANK_FACE_NAME, 0)];
340 blank_face->magicmap = find_color ("khaki") | FACE_FLOOR;
341
342 empty_face = &new_faces[FindFace (EMPTY_FACE_NAME, 0)];
343
344 dark_faces[0] = &new_faces[FindFace (DARK_FACE1_NAME, 0)];
345 dark_faces[1] = &new_faces[FindFace (DARK_FACE2_NAME, 0)];
346 dark_faces[2] = &new_faces[FindFace (DARK_FACE3_NAME, 0)];
347
348 smooth_face = &new_faces[FindFace (SMOOTH_FACE_NAME, 0)];
349}
350
351/* This returns an the face number of face 'name'. Number is constant
352 * during an invocation, but not necessarily between versions (this
353 * is because the faces are arranged in alphabetical order, so
354 * if a face is removed or added, all faces after that will now
355 * have a different number.
356 *
357 * the parameter error determines behaviour. If a face is
358 * not found, then error is returned. This can be useful if
359 * you want some default face used, or can be set to negative
360 * so that it will be known that the face could not be found
361 * (needed in client, so that it will know to request that image
362 * from the server)
363 */
364int
365FindFace (const char *name, int error)
366{
367 struct bmappair *bp, tmp;
368 char *p;
369
370 if (!name)
371 return error;
372
373 if ((p = strchr (name, '\n')))
374 *p = '\0';
375
376 tmp.name = (char *) name;
377 bp = (struct bmappair *) bsearch (&tmp, xbm, nroffiles, sizeof (struct bmappair), (int (*)(const void *, const void *)) compar);
378
379 return bp ? bp->number : error;
380} 117}
381 118
382/* Reads the smooth file to know how to smooth datas. 119/* Reads the smooth file to know how to smooth datas.
383 * the smooth file if made of 2 elements lines. 120 * the smooth file if made of 2 elements lines.
384 * lines starting with # are comment 121 * lines starting with # are comment
391{ 128{
392 char buf[MAX_BUF], *p, *q; 129 char buf[MAX_BUF], *p, *q;
393 FILE *fp; 130 FILE *fp;
394 int smoothcount = 0; 131 int smoothcount = 0;
395 132
396 bmaps_checksum = 0;
397 sprintf (buf, "%s/smooth", settings.datadir); 133 sprintf (buf, "%s/smooth", settings.datadir);
398 LOG (llevDebug, "Reading smooth from %s...", buf); 134 LOG (llevDebug, "Reading smooth from %s...\n", buf);
399 if ((fp = fopen (buf, "r")) == NULL) 135 if ((fp = fopen (buf, "r")) == NULL)
400 { 136 {
401 LOG (llevError, "Cannot open smooth file %s: %s\n", strerror (errno)); 137 LOG (llevError, "Cannot open smooth file %s: %s\n", strerror (errno));
402 exit (-1); 138 exit (-1);
403 } 139 }
417 p = strchr (buf, ' '); 153 p = strchr (buf, ' ');
418 if (!p) 154 if (!p)
419 continue; 155 continue;
420 *p = '\0'; 156 *p = '\0';
421 q = buf; 157 q = buf;
422 smooth[nrofsmooth].id = FindFace (q, 0); 158 smooth[nrofsmooth].id = face_find (q);
423 q = p + 1; 159 q = p + 1;
424 smooth[nrofsmooth].smooth = FindFace (q, 0); 160 smooth[nrofsmooth].smooth = face_find (q);
425 nrofsmooth++; 161 nrofsmooth++;
426 } 162 }
427 fclose (fp); 163 fclose (fp);
428 164
429 LOG (llevDebug, "done (got %d smooth entries)\n", nrofsmooth); 165 LOG (llevDebug, "done (got %d smooth entries)\n", nrofsmooth);
452 if (bp) 188 if (bp)
453 (*smoothed) = bp->smooth; 189 (*smoothed) = bp->smooth;
454 return bp ? 1 : 0; 190 return bp ? 1 : 0;
455} 191}
456 192
457/**
458 * Deallocates memory allocated by ReadBmapNames() and ReadSmooth().
459 */
460void
461free_all_images (void)
462{
463 int i;
464
465 for (i = 0; i < nroffiles; i++)
466 free (xbm[i].name);
467
468 delete[]xbm;
469 delete[]new_faces;
470 delete[]smooth;
471}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines