00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include <global.h>
00035 #include <stdio.h>
00036 #include "image.h"
00037
00038 New_Face *new_faces;
00039
00052 struct bmappair {
00053 char *name;
00054 unsigned int number;
00055 };
00060 static struct bmappair *xbm = NULL;
00061
00066 New_Face *blank_face, *empty_face, *smooth_face;
00067
00068
00070 static int nroffiles = 0;
00071
00076 int nrofpixmaps = 0;
00077
00078 face_sets facesets[MAX_FACE_SETS];
00087 static const char *const colorname[] = {
00088 "black",
00089 "white",
00090 "blue",
00091 "red",
00092 "orange",
00093 "light_blue",
00094 "dark_orange",
00095 "green",
00096 "light_green",
00097 "grey",
00098 "brown",
00099 "yellow",
00100 "khaki"
00101 };
00102
00106 static int compar(const struct bmappair *a, const struct bmappair *b) {
00107 return strcmp(a->name, b->name);
00108 }
00109
00123 static uint8 find_color(const char *name) {
00124 uint8 i;
00125
00126 for (i = 0; i < sizeof(colorname)/sizeof(*colorname); i++)
00127 if (!strcmp(name, colorname[i]))
00128 return i;
00129
00130 LOG(llevError, "Unknown color: %s\n", name);
00131 return 0;
00132 }
00133
00141 static void read_face_data(void) {
00142 char buf[MAX_BUF], *cp;
00143 New_Face *on_face = NULL;
00144 FILE *fp;
00145
00146 snprintf(buf, sizeof(buf), "%s/faces", settings.datadir);
00147 LOG(llevDebug, "Reading faces from %s...\n", buf);
00148 if ((fp = fopen(buf, "r")) == NULL) {
00149 LOG(llevError, "Cannot open faces file: %s\n", strerror_local(errno, buf, sizeof(buf)));
00150 exit(-1);
00151 }
00152
00153 while (fgets(buf, MAX_BUF, fp) != NULL) {
00154 if (*buf == '#')
00155 continue;
00156 if (!strncmp(buf, "end", 3)) {
00157 on_face = NULL;
00158 } else if (!strncmp(buf, "face", 4)) {
00159 unsigned tmp;
00160
00161 cp = buf+5;
00162 cp[strlen(cp)-1] = '\0';
00163
00164 if ((tmp = find_face(cp, (unsigned)-1)) == (unsigned)-1) {
00165 LOG(llevError, "Could not find face %s\n", cp);
00166 continue;
00167 }
00168 on_face = &new_faces[tmp];
00169 on_face->visibility = 0;
00170 } else if (on_face == NULL) {
00171 LOG(llevError, "Got line with no face set: %s\n", buf);
00172 } else if (!strncmp(buf, "visibility", 10)) {
00173 on_face->visibility = atoi(buf+11);
00174 } else if (!strncmp(buf, "magicmap", 8)) {
00175 cp = buf+9;
00176 cp[strlen(cp)-1] = '\0';
00177 on_face->magicmap = find_color(cp);
00178 } else if (!strncmp(buf, "is_floor", 8)) {
00179 int value = atoi(buf+9);
00180 if (value)
00181 on_face->magicmap |= FACE_FLOOR;
00182 } else
00183 LOG(llevDebug, "Got unknown line in faces file: %s\n", buf);
00184 }
00185 LOG(llevDebug, "done\n");
00186 fclose(fp);
00187 }
00188
00198 void read_bmap_names(void) {
00199 char buf[MAX_BUF], *p, *q;
00200 FILE *fp;
00201 int value, nrofbmaps = 0, i;
00202 size_t l;
00203
00204 bmaps_checksum = 0;
00205 snprintf(buf, sizeof(buf), "%s/bmaps", settings.datadir);
00206 LOG(llevDebug, "Reading bmaps from %s...\n", buf);
00207 if ((fp = fopen(buf, "r")) == NULL) {
00208 LOG(llevError, "Cannot open bmaps file: %s\n", strerror_local(errno, buf, sizeof(buf)));
00209 exit(-1);
00210 }
00211
00212
00213 while (fgets(buf, MAX_BUF, fp) != NULL)
00214 if (buf[0] != '#' && buf[0] != '\n')
00215 nrofbmaps++;
00216 rewind(fp);
00217
00218 xbm = (struct bmappair *)malloc(sizeof(struct bmappair)*nrofbmaps);
00219 if (xbm == NULL) {
00220 LOG(llevError, "read_bmap_names: xbm memory allocation failure.\n");
00221 abort();
00222 }
00223 memset(xbm, 0, sizeof(struct bmappair)*nrofbmaps);
00224
00225 nroffiles = 0;
00226 while (nroffiles < nrofbmaps && fgets(buf, MAX_BUF, fp) != NULL) {
00227 if (*buf == '#')
00228 continue;
00229
00230 p = (*buf == '\\') ? (buf+1) : buf;
00231 if (!(p = strtok(p, " \t")) || !(q = strtok(NULL, " \t\n"))) {
00232 LOG(llevDebug, "Warning, syntax error: %s\n", buf);
00233 continue;
00234 }
00235 value = atoi(p);
00236 xbm[nroffiles].name = strdup_local(q);
00237
00238
00239
00240
00241
00242
00243
00244
00245 ROTATE_RIGHT(bmaps_checksum);
00246 bmaps_checksum += value&0xff;
00247 bmaps_checksum &= 0xffffffff;
00248
00249 ROTATE_RIGHT(bmaps_checksum);
00250 bmaps_checksum += (value>>8)&0xff;
00251 bmaps_checksum &= 0xffffffff;
00252 for (l = 0; l < strlen(q); l++) {
00253 ROTATE_RIGHT(bmaps_checksum);
00254 bmaps_checksum += q[l];
00255 bmaps_checksum &= 0xffffffff;
00256 }
00257
00258 xbm[nroffiles].number = value;
00259 nroffiles++;
00260 if (value >= nrofpixmaps)
00261 nrofpixmaps = value+1;
00262 }
00263 fclose(fp);
00264
00265 LOG(llevDebug, "done (got %d/%d/%d)\n", nrofpixmaps, nrofbmaps, nroffiles);
00266
00267 new_faces = (New_Face *)malloc(sizeof(New_Face)*nrofpixmaps);
00268 if (new_faces == NULL) {
00269 LOG(llevError, "read_bmap_names: new_faces memory allocation failure.\n");
00270 abort();
00271 }
00272
00273 for (i = 0; i < nrofpixmaps; i++) {
00274 new_faces[i].name = "";
00275 new_faces[i].number = i;
00276 new_faces[i].visibility = 0;
00277 new_faces[i].magicmap = 255;
00278 new_faces[i].smoothface = (uint16)-1;
00279 }
00280
00281 for (i = 0; i < nroffiles; i++) {
00282 new_faces[xbm[i].number].name = xbm[i].name;
00283 }
00284
00285 qsort(xbm, nroffiles, sizeof(struct bmappair), (int (*)(const void *, const void *))compar);
00286
00287 read_face_data();
00288
00289 for (i = 0; i < nrofpixmaps; i++) {
00290 if (new_faces[i].magicmap == 255) {
00291 new_faces[i].magicmap = 0;
00292 }
00293 }
00294
00295
00296
00297 blank_face = &new_faces[find_face(BLANK_FACE_NAME, 0)];
00298 blank_face->magicmap = find_color("khaki")|FACE_FLOOR;
00299
00300 empty_face = &new_faces[find_face(EMPTY_FACE_NAME, 0)];
00301
00302 smooth_face = &new_faces[find_face(SMOOTH_FACE_NAME, 0)];
00303 }
00304
00324 unsigned find_face(const char *name, unsigned error) {
00325 struct bmappair *bp, tmp;
00326 char *p;
00327
00328 if ((p = strchr(name, '\n')))
00329 *p = '\0';
00330
00331 tmp.name = (char *)name;
00332 bp = (struct bmappair *)bsearch(&tmp, xbm, nroffiles, sizeof(struct bmappair), (int (*)(const void *, const void *))compar);
00333
00334 return bp ? bp->number : error;
00335 }
00336
00348 int read_smooth(void) {
00349 char buf[MAX_BUF], *p, *q;
00350 FILE *fp;
00351 int regular, smoothed, nrofsmooth = 0;
00352
00353 snprintf(buf, sizeof(buf), "%s/smooth", settings.datadir);
00354 LOG(llevDebug, "Reading smooth from %s...\n", buf);
00355 if ((fp = fopen(buf, "r")) == NULL) {
00356 LOG(llevError, "Cannot open smooth file %s: %s\n", strerror_local(errno, buf, sizeof(buf)));
00357 exit(-1);
00358 }
00359
00360 while (fgets(buf, MAX_BUF, fp) != NULL) {
00361 if (*buf == '#')
00362 continue;
00363
00364 p = strchr(buf, ' ');
00365 if (!p)
00366 continue;
00367
00368 *p = '\0';
00369 q = buf;
00370 regular = find_face(q, (unsigned)-1);
00371 if (regular == (unsigned)-1) {
00372 LOG(llevError, "invalid regular face: %s\n", q);
00373 continue;
00374 }
00375 q = p+1;
00376 smoothed = find_face(q, (unsigned)-1);
00377 if (smoothed == (unsigned)-1) {
00378 LOG(llevError, "invalid smoothed face: %s\n", q);
00379 continue;
00380 }
00381
00382 new_faces[regular].smoothface = smoothed;
00383
00384 nrofsmooth++;
00385 }
00386 fclose(fp);
00387
00388 LOG(llevDebug, "done (got %d smooth entries)\n", nrofsmooth);
00389 return nrofsmooth;
00390 }
00391
00401 int find_smooth(uint16 face, uint16 *smoothed) {
00402 (*smoothed) = 0;
00403
00404 if (face < nrofpixmaps) {
00405 if (new_faces[face].smoothface == ((uint16)-1))
00406 return 0;
00407
00408 (*smoothed) = new_faces[face].smoothface;
00409 return 1;
00410 }
00411
00412 return 0;
00413 }
00414
00418 void free_all_images(void) {
00419 int i;
00420
00421 for (i = 0; i < nroffiles; i++)
00422 free(xbm[i].name);
00423 free(xbm);
00424 free(new_faces);
00425 }
00426
00435 static void check_faceset_fallback(int faceset, int togo) {
00436 int fallback = facesets[faceset].fallback;
00437
00438
00439 if (fallback == 0)
00440 return;
00441
00442 if (!facesets[fallback].prefix) {
00443 LOG(llevError, "Face set %d falls to non set faceset %d\n", faceset, fallback);
00444 abort();
00445 }
00446 togo--;
00447 if (togo == 0) {
00448 LOG(llevError, "Infinite loop found in facesets. aborting.\n");
00449 abort();
00450 }
00451 check_faceset_fallback(fallback, togo);
00452 }
00453
00471 void read_client_images(void) {
00472 char filename[400];
00473 char buf[HUGE_BUF];
00474 char *cp, *cps[7];
00475 FILE *infile;
00476 int num, len, compressed, fileno, i, badline;
00477
00478 memset(facesets, 0, sizeof(facesets));
00479 snprintf(filename, sizeof(filename), "%s/image_info", settings.datadir);
00480 if ((infile = open_and_uncompress(filename, 0, &compressed)) == NULL) {
00481 LOG(llevError, "Unable to open %s\n", filename);
00482 abort();
00483 }
00484 while (fgets(buf, HUGE_BUF-1, infile) != NULL) {
00485 badline = 0;
00486
00487 if (buf[0] == '#')
00488 continue;
00489 if (!(cps[0] = strtok(buf, ":")))
00490 badline = 1;
00491 for (i = 1; i < 7; i++) {
00492 if (!(cps[i] = strtok(NULL, ":")))
00493 badline = 1;
00494 }
00495 if (badline) {
00496 LOG(llevError, "Bad line in image_info file, ignoring line:\n %s", buf);
00497 } else {
00498 len = atoi(cps[0]);
00499 if (len >= MAX_FACE_SETS) {
00500 LOG(llevError, "To high a setnum in image_info file: %d > %d\n", len, MAX_FACE_SETS);
00501 abort();
00502 }
00503 facesets[len].prefix = strdup_local(cps[1]);
00504 facesets[len].fullname = strdup_local(cps[2]);
00505 facesets[len].fallback = atoi(cps[3]);
00506 facesets[len].size = strdup_local(cps[4]);
00507 facesets[len].extension = strdup_local(cps[5]);
00508 facesets[len].comment = strdup_local(cps[6]);
00509 }
00510 }
00511 close_and_delete(infile, compressed);
00512 for (i = 0; i < MAX_FACE_SETS; i++) {
00513 if (facesets[i].prefix)
00514 check_faceset_fallback(i, MAX_FACE_SETS);
00515 }
00516
00517
00518
00519
00520 for (fileno = 0; fileno < MAX_FACE_SETS; fileno++) {
00521
00522 if (!facesets[fileno].prefix)
00523 continue;
00524 facesets[fileno].faces = calloc(nrofpixmaps, sizeof(face_info));
00525
00526 snprintf(filename, sizeof(filename), "%s/crossfire.%d", settings.datadir, fileno);
00527 LOG(llevDebug, "Loading image file %s\n", filename);
00528
00529 if ((infile = open_and_uncompress(filename, 0, &compressed)) == NULL) {
00530 LOG(llevError, "Unable to open %s\n", filename);
00531 abort();
00532 }
00533 while (fgets(buf, HUGE_BUF-1, infile) != NULL) {
00534 if (strncmp(buf, "IMAGE ", 6) != 0) {
00535 LOG(llevError, "read_client_images:Bad image line - not IMAGE, instead\n%s", buf);
00536 abort();
00537 }
00538 num = atoi(buf+6);
00539 if (num < 0 || num >= nrofpixmaps) {
00540 LOG(llevError, "read_client_images: Image num %d not in 0..%d\n%s", num, nrofpixmaps, buf);
00541 abort();
00542 }
00543
00544 for (cp = buf+6; *cp != ' '; cp++)
00545 ;
00546 len = atoi(cp);
00547 if (len == 0 || len > MAX_IMAGE_SIZE) {
00548 LOG(llevError, "read_client_images: length not valid: %d > %d \n%s", len, MAX_IMAGE_SIZE, buf);
00549 abort();
00550 }
00551
00552
00553
00554 facesets[fileno].faces[num].datalen = len;
00555 facesets[fileno].faces[num].data = malloc(len);
00556 if ((i = fread(facesets[fileno].faces[num].data, len, 1, infile)) != 1) {
00557 LOG(llevError, "read_client_images: Did not read desired amount of data, wanted %d, got %d\n%s", len, i, buf);
00558 abort();
00559 }
00560 facesets[fileno].faces[num].checksum = 0;
00561 for (i = 0; i < len; i++) {
00562 ROTATE_RIGHT(facesets[fileno].faces[num].checksum);
00563 facesets[fileno].faces[num].checksum += facesets[fileno].faces[num].data[i];
00564 facesets[fileno].faces[num].checksum &= 0xffffffff;
00565 }
00566 }
00567 close_and_delete(infile, compressed);
00568 }
00569 }
00570
00575 int is_valid_faceset(int fsn) {
00576 if (fsn >= 0 && fsn < MAX_FACE_SETS && facesets[fsn].prefix)
00577 return TRUE;
00578 return FALSE;
00579 }
00580
00584 void free_socket_images(void) {
00585 int num, q;
00586
00587 for (num = 0; num < MAX_FACE_SETS; num++) {
00588 if (facesets[num].prefix) {
00589 for (q = 0; q < nrofpixmaps; q++)
00590 if (facesets[num].faces[q].data)
00591 free(facesets[num].faces[q].data);
00592 free(facesets[num].prefix);
00593 free(facesets[num].fullname);
00594 free(facesets[num].size);
00595 free(facesets[num].extension);
00596 free(facesets[num].comment);
00597 free(facesets[num].faces);
00598 }
00599 }
00600 }
00601
00614 int get_face_fallback(int faceset, int imageno) {
00615
00616
00617
00618
00619
00620
00621 if (faceset == 0)
00622 return 0;
00623
00624 if (!facesets[faceset].prefix) {
00625 LOG(llevError, "get_face_fallback called with unused set (%d)?\n", faceset);
00626 return 0;
00627 }
00628 if (facesets[faceset].faces[imageno].data)
00629 return faceset;
00630 return get_face_fallback(facesets[faceset].fallback, imageno);
00631 }