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.16 by root, Thu Feb 15 15:43:36 2007 UTC vs.
Revision 1.22 by root, Wed Mar 14 20:33:10 2007 UTC

24 24
25 25
26#include <global.h> 26#include <global.h>
27#include <stdio.h> 27#include <stdio.h>
28 28
29facetile *new_faces; 29#include "face.h"
30#include "crc.h"
30 31
31/* bmappair and xbm are used when looking for the image id numbers 32faceidx blank_face, empty_face;
32 * of a face by name. xbm is sorted alphabetically so that bsearch
33 * can be used to quickly find the entry for a name. the number is
34 * then an index into the new_faces array.
35 * This data is redundant with new_face information - the difference
36 * is that this data gets sorted, and that doesn't necessarily happen
37 * with the new_face data - when accessing new_face[some number],
38 * that some number corresponds to the face at that number - for
39 * xbm, it may not. At current time, these do in fact match because
40 * the bmaps file is created in a sorted order.
41 */
42 33
43struct bmappair 34facehash_t facehash;
44{ 35std::vector<faceinfo> faces;
45 char *name;
46 unsigned int number;
47};
48
49static struct bmappair *xbm = NULL;
50
51facetile *blank_face, *dark_faces[3], *empty_face, *smooth_face;
52
53/* nroffiles is the actual number of bitmaps defined.
54 * nrofpixmaps is the number of bitmaps loaded. With
55 * the automatic generation of the bmaps file, this is now equal
56 * to nroffiles.
57 *
58 * The xbm array (which contains name and number information, and
59 * is then sorted) contains nroffiles entries. the xbm_names
60 * array (which is used for converting the numeric face to
61 * a name) contains nrofpixmaps entries.
62 */
63static int nroffiles = 0;
64int nrofpixmaps = 0;
65
66/**
67 * id is the face to smooth, smooth is the 16x2 face used to smooth id.
68 */
69struct smoothing : zero_initialised
70{
71 uint16 id;
72 uint16 smooth;
73};
74
75/**
76 * Contains all defined smoothing entries. smooth is an array of nrofsmooth
77 * entries. It is sorted by smooth[].id.
78 */
79static struct smoothing *smooth = NULL;
80int nrofsmooth = 0;
81 36
82/* the only thing this table is used for now is to 37/* the only thing this table is used for now is to
83 * translate the colorname in the magicmap field of the 38 * translate the colorname in the magicmap field of the
84 * face into a numeric index that is then sent to the 39 * face into a numeric index that is then sent to the
85 * client for magic map commands. The order of this table 40 * client for magic map commands. The order of this table
99 "brown", /* 10 */ 54 "brown", /* 10 */
100 "yellow", /* 11 */ 55 "yellow", /* 11 */
101 "khaki" /* 12 */ 56 "khaki" /* 12 */
102}; 57};
103 58
104static int
105compar (const struct bmappair *a, const struct bmappair *b)
106{
107 return strcmp (a->name, b->name);
108}
109
110static int
111compar_smooth (const struct smoothing *a, const struct smoothing *b)
112{
113 if (a->id < b->id)
114 return -1;
115 if (b->id < a->id)
116 return 1;
117 return 0;
118}
119
120/* 59/*
121 * Returns the matching color in the coloralias if found, 60 * Returns the matching color in the coloralias if found,
122 * 0 otherwise. Note that 0 will actually be black, so there is no 61 * 0 otherwise. Note that 0 will actually be black, so there is no
123 * way the calling function can tell if an error occurred or not 62 * way the calling function can tell if an error occurred or not
124 */ 63 */
128 uint8 i; 67 uint8 i;
129 68
130 for (i = 0; i < sizeof (colorname) / sizeof (*colorname); i++) 69 for (i = 0; i < sizeof (colorname) / sizeof (*colorname); i++)
131 if (!strcmp (name, colorname[i])) 70 if (!strcmp (name, colorname[i]))
132 return i; 71 return i;
72
133 LOG (llevError, "Unknown color: %s\n", name); 73 LOG (llevError, "Unknown color: %s\n", name);
134 return 0; 74 return 0;
135} 75}
136 76
137/* This reads the lib/faces file, getting color and visibility information. 77faceidx
138 * it is called by ReadBmapNames. 78face_find (const char *name, faceidx defidx)
139 */
140static void
141ReadFaceData (void)
142{ 79{
143 char buf[MAX_BUF], *cp; 80 if (!name)
144 facetile *on_face = NULL; 81 return defidx;
145 FILE *fp;
146 82
147 sprintf (buf, "%s/faces", settings.datadir); 83 facehash_t::iterator i = facehash.find (name);
148 LOG (llevDebug, "Reading faces from %s...\n", buf);
149 if ((fp = fopen (buf, "r")) == NULL)
150 {
151 LOG (llevError, "Cannot open faces file %s: %s\n", buf, strerror (errno));
152 exit (-1);
153 }
154 while (fgets (buf, MAX_BUF, fp) != NULL)
155 {
156 if (*buf == '#')
157 continue;
158 if (!strncmp (buf, "end", 3))
159 {
160 on_face = NULL;
161 }
162 else if (!strncmp (buf, "face", 4))
163 {
164 int tmp;
165 84
166 cp = buf + 5; 85 return i == facehash.end ()
167 cp[strlen (cp) - 1] = '\0'; /* remove newline */ 86 ? defidx : i->second;
168
169 if ((tmp = FindFace (cp, -1)) == -1)
170 {
171 LOG (llevError, "Could not find face %s\n", cp);
172 continue;
173 }
174 on_face = &new_faces[tmp];
175 on_face->visibility = 0;
176 }
177 else if (on_face == NULL)
178 {
179 LOG (llevError, "Got line with no face set: %s\n", buf);
180 }
181 else if (!strncmp (buf, "color_fg", 8))
182 {
183 cp = buf + 9;
184 cp[strlen (cp) - 1] = '\0';
185 if (on_face->magicmap == 255)
186 on_face->magicmap = find_color (cp);
187 }
188 else if (!strncmp (buf, "color_bg", 8))
189 {
190 /* ignore it */
191 }
192 else if (!strncmp (buf, "visibility", 10))
193 {
194 on_face->visibility = atoi (buf + 11);
195 }
196 else if (!strncmp (buf, "magicmap", 8))
197 {
198 cp = buf + 9;
199 cp[strlen (cp) - 1] = '\0';
200 on_face->magicmap = find_color (cp);
201 }
202 else if (!strncmp (buf, "is_floor", 8))
203 {
204 int value = atoi (buf + 9);
205
206 if (value)
207 on_face->magicmap |= FACE_FLOOR;
208 }
209 else
210 LOG (llevDebug, "Got unknown line in faces file: %s\n", buf);
211 }
212
213 LOG (llevDebug, "done\n");
214 fclose (fp);
215} 87}
216 88
217/* This reads the bmaps file to get all the bitmap names and 89faceinfo *
218 * stuff. It only needs to be done once, because it is player 90face_info (faceidx idx)
219 * independent (ie, what display the person is on will not make a
220 * difference.)
221 */
222void
223ReadBmapNames (void)
224{ 91{
225 char buf[MAX_BUF], *p, *q; 92 assert (0 < (faceidx)-1); // faceidx must be unsigned
226 FILE *fp;
227 int value, nrofbmaps = 0, i;
228 size_t l;
229 93
230 bmaps_checksum = 0; 94 if (idx >= faces.size ())
231 sprintf (buf, "%s/bmaps", settings.datadir); 95 return 0;
232 LOG (llevDebug, "Reading bmaps from %s...\n", buf);
233 if ((fp = fopen (buf, "r")) == NULL)
234 {
235 LOG (llevError, "Cannot open bmaps file %s: %s\n", buf, strerror (errno));
236 exit (-1);
237 }
238 96
239 /* First count how many bitmaps we have, so we can allocate correctly */ 97 return &faces [idx];
240 while (fgets (buf, MAX_BUF, fp) != NULL)
241 if (buf[0] != '#' && buf[0] != '\n')
242 nrofbmaps++;
243 rewind (fp);
244
245 xbm = new bmappair[nrofbmaps];
246 memset (xbm, 0, sizeof (struct bmappair) * nrofbmaps);
247
248 while (nroffiles < nrofbmaps && fgets (buf, MAX_BUF, fp) != NULL)
249 {
250 if (*buf == '#')
251 continue;
252
253 p = (*buf == '\\') ? (buf + 1) : buf;
254 if (!(p = strtok (p, " \t")) || !(q = strtok (NULL, " \t\n")))
255 {
256 LOG (llevDebug, "Warning, syntax error: %s\n", buf);
257 continue;
258 }
259 value = atoi (p);
260 xbm[nroffiles].name = strdup (q);
261
262 /* We need to calculate the checksum of the bmaps file
263 * name->number mapping to send to the client. This does not
264 * need to match what sum or other utility may come up with -
265 * as long as we get the same results on the same real file
266 * data, it does the job as it lets the client know if
267 * the file has the same data or not.
268 */
269 rotate_right (bmaps_checksum);
270 bmaps_checksum += value & 0xff;
271 bmaps_checksum &= 0xffffffff;
272
273 rotate_right (bmaps_checksum);
274 bmaps_checksum += (value >> 8) & 0xff;
275 bmaps_checksum &= 0xffffffff;
276 for (l = 0; l < strlen (q); l++)
277 {
278 rotate_right (bmaps_checksum);
279 bmaps_checksum += q[l];
280 bmaps_checksum &= 0xffffffff;
281 }
282
283 xbm[nroffiles].number = value;
284 nroffiles++;
285 if (value >= nrofpixmaps)
286 nrofpixmaps = value + 1;
287 }
288 fclose (fp);
289
290 LOG (llevDebug, "done (got %d/%d/%d)\n", nrofpixmaps, nrofbmaps, nroffiles);
291
292 new_faces = new facetile[nrofpixmaps];
293
294 for (i = 0; i < nrofpixmaps; i++)
295 {
296 new_faces[i].name = "";
297 new_faces[i].number = i;
298 new_faces[i].visibility = 0;
299 new_faces[i].magicmap = 255;
300 }
301
302 for (i = 0; i < nroffiles; i++)
303 new_faces[xbm[i].number].name = xbm[i].name;
304
305 // non-pod datatype, likely not allowed
306 qsort (xbm, nroffiles, sizeof (struct bmappair), (int (*)(const void *, const void *)) compar);
307
308 ReadFaceData ();
309
310 for (i = 0; i < nrofpixmaps; i++)
311 {
312 if (new_faces[i].magicmap == 255)
313 {
314#if 0 /* Useful for initial debugging, not needed now */
315 LOG (llevDebug, "Face %s still had default magicmap, resetting to black\n", new_faces[i].name);
316#endif
317 new_faces[i].magicmap = 0;
318 }
319 }
320 /* Actually forcefully setting the colors here probably should not
321 * be done - it could easily create confusion.
322 */
323 blank_face = &new_faces[FindFace (BLANK_FACE_NAME, 0)];
324 blank_face->magicmap = find_color ("khaki") | FACE_FLOOR;
325
326 empty_face = &new_faces[FindFace (EMPTY_FACE_NAME, 0)];
327
328 dark_faces[0] = &new_faces[FindFace (DARK_FACE1_NAME, 0)];
329 dark_faces[1] = &new_faces[FindFace (DARK_FACE2_NAME, 0)];
330 dark_faces[2] = &new_faces[FindFace (DARK_FACE3_NAME, 0)];
331
332 smooth_face = &new_faces[FindFace (SMOOTH_FACE_NAME, 0)];
333} 98}
334 99
335/* This returns an the face number of face 'name'. Number is constant 100facedata *
336 * during an invocation, but not necessarily between versions (this 101face_data (faceidx idx, int faceset)
337 * is because the faces are arranged in alphabetical order, so
338 * if a face is removed or added, all faces after that will now
339 * have a different number.
340 *
341 * the parameter error determines behaviour. If a face is
342 * not found, then error is returned. This can be useful if
343 * you want some default face used, or can be set to negative
344 * so that it will be known that the face could not be found
345 * (needed in client, so that it will know to request that image
346 * from the server)
347 */
348int
349FindFace (const char *name, int error)
350{ 102{
351 struct bmappair *bp, tmp; 103 if (faceinfo *f = face_info (idx))
352 char *p; 104 return &(faceset ? f->data32 : f->data64);
353 105
354 if (!name) 106 return 0;
355 return error;
356
357 if ((p = strchr (name, '\n')))
358 *p = '\0';
359
360 tmp.name = (char *) name;
361 bp = (struct bmappair *) bsearch (&tmp, xbm, nroffiles, sizeof (struct bmappair), (int (*)(const void *, const void *)) compar);
362
363 return bp ? bp->number : error;
364} 107}
365 108
366/* Reads the smooth file to know how to smooth datas.
367 * the smooth file if made of 2 elements lines.
368 * lines starting with # are comment
369 * the first element of line is face to smooth
370 * the next element is the 16x2 faces picture
371 * used for smoothing
372 */
373int
374ReadSmooth (void)
375{
376 char buf[MAX_BUF], *p, *q;
377 FILE *fp;
378 int smoothcount = 0;
379
380 bmaps_checksum = 0;
381 sprintf (buf, "%s/smooth", settings.datadir);
382 LOG (llevDebug, "Reading smooth from %s...\n", buf);
383 if ((fp = fopen (buf, "r")) == NULL)
384 {
385 LOG (llevError, "Cannot open smooth file %s: %s\n", strerror (errno));
386 exit (-1);
387 }
388
389 /* First count how many smooth we have, so we can allocate correctly */
390 while (fgets (buf, MAX_BUF, fp) != NULL)
391 if (buf[0] != '#' && buf[0] != '\n')
392 smoothcount++;
393 rewind (fp);
394
395 smooth = new smoothing[smoothcount];
396
397 while (nrofsmooth < smoothcount && fgets (buf, MAX_BUF, fp) != NULL)
398 {
399 if (*buf == '#')
400 continue;
401 p = strchr (buf, ' ');
402 if (!p)
403 continue;
404 *p = '\0';
405 q = buf;
406 smooth[nrofsmooth].id = FindFace (q, 0);
407 q = p + 1;
408 smooth[nrofsmooth].smooth = FindFace (q, 0);
409 nrofsmooth++;
410 }
411 fclose (fp);
412
413 LOG (llevDebug, "done (got %d smooth entries)\n", nrofsmooth);
414 qsort (smooth, nrofsmooth, sizeof (struct smoothing), (int (*)(const void *, const void *)) compar_smooth);
415 return nrofsmooth;
416}
417
418/**
419 * Find the smooth face for a given face.
420 *
421 * @param face the face to find the smoothing face for
422 *
423 * @param smoothed return value: set to smooth face
424 *
425 * @return 1=smooth face found, 0=no smooth face found
426 */
427int
428FindSmooth (uint16 face, uint16 * smoothed)
429{
430 struct smoothing *bp, tmp;
431
432 tmp.id = face;
433 bp = (struct smoothing *) bsearch
434 (&tmp, smooth, nrofsmooth, sizeof (struct smoothing), (int (*)(const void *, const void *)) compar_smooth);
435 (*smoothed) = 0;
436 if (bp)
437 (*smoothed) = bp->smooth;
438 return bp ? 1 : 0;
439}
440
441/**
442 * Deallocates memory allocated by ReadBmapNames() and ReadSmooth().
443 */
444void
445free_all_images (void)
446{
447 int i;
448
449 for (i = 0; i < nroffiles; i++)
450 free (xbm[i].name);
451
452 delete[]xbm;
453 delete[]new_faces;
454 delete[]smooth;
455}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines