ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/image.C
Revision: 1.18
Committed: Sun Mar 4 19:36:12 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_0
Changes since 1.17: +1 -3 lines
Log Message:
remove default_smoothed images - unused.
remove references to mythical sdefault.001 / default_smoothed.111 image
from server code.

File Contents

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