--- deliantra/server/common/image.C 2006/09/08 16:51:42 1.5
+++ deliantra/server/common/image.C 2012/11/11 05:53:11 1.43
@@ -1,428 +1,108 @@
/*
- * static char *rcsid_image_c =
- * "$Id: image.C,v 1.5 2006/09/08 16:51:42 root Exp $";
+ * This file is part of Deliantra, the Roguelike Realtime MMORPG.
+ *
+ * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ *
+ * Deliantra is free software: you can redistribute it and/or modify it under
+ * the terms of the Affero GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the Affero GNU General Public License
+ * and the GNU General Public License along with this program. If not, see
+ * .
+ *
+ * The authors can be reached via e-mail to
*/
-/*
- CrossFire, A Multiplayer game for X-windows
-
- Copyright (C) 2002 Mark Wedel & Crossfire Development Team
- Copyright (C) 1992 Frank Tore Johansen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- The maintainer of this code can be reached at crossfire-devel@real-time.com
-*/
-
-
#include
#include
-New_Face *new_faces;
-
-/* bmappair and xbm are used when looking for the image id numbers
- * of a face by name. xbm is sorted alphabetically so that bsearch
- * can be used to quickly find the entry for a name. the number is
- * then an index into the new_faces array.
- * This data is redundant with new_face information - the difference
- * is that this data gets sorted, and that doesn't necessarily happen
- * with the new_face data - when accessing new_face[some number],
- * that some number corresponds to the face at that number - for
- * xbm, it may not. At current time, these do in fact match because
- * the bmaps file is created in a sorted order.
- */
-
-struct bmappair
-{
- char *name;
- unsigned int number;
-};
-
-void free (bmappair *); // guard to catch free when delete should be used
-
-static struct bmappair *xbm=NULL;
-
-/* Following can just as easily be pointers, but
- * it is easier to keep them like this.
- */
-New_Face *blank_face, *dark_faces[3], *empty_face, *smooth_face;
-
-
-/* nroffiles is the actual number of bitmaps defined.
- * nrofpixmaps is the number of bitmaps loaded. With
- * the automatic generation of the bmaps file, this is now equal
- * to nroffiles.
- *
- * The xbm array (which contains name and number information, and
- * is then sorted) contains nroffiles entries. the xbm_names
- * array (which is used for converting the numeric face to
- * a name) contains nrofpixmaps entries.
- */
-static int nroffiles = 0;
-int nrofpixmaps = 0;
-
-/**
- * id is the face to smooth, smooth is the 16x2 face used to smooth id.
- */
-struct smoothing : zero_initialised
-{
- uint16 id;
- uint16 smooth;
-};
-
-void free (smoothing *); // guard to catch free when delete should be used
-
-/**
- * Contains all defined smoothing entries. smooth is an array of nrofsmooth
- * entries. It is sorted by smooth[].id.
- */
-static struct smoothing *smooth=NULL;
-int nrofsmooth=0;
-
-/* the only thing this table is used for now is to
- * translate the colorname in the magicmap field of the
- * face into a numeric index that is then sent to the
- * client for magic map commands. The order of this table
- * must match that of the NDI colors in include/newclient.h.
- */
-static const char *const colorname[] = {
-"black", /* 0 */
-"white", /* 1 */
-"blue", /* 2 */
-"red", /* 3 */
-"orange", /* 4 */
-"light_blue", /* 5 */
-"dark_orange", /* 6 */
-"green", /* 7 */
-"light_green", /* 8 */
-"grey", /* 9 */
-"brown", /* 10 */
-"yellow", /* 11 */
-"khaki" /* 12 */
-};
-
-static int compar (const struct bmappair *a, const struct bmappair *b) {
- return strcmp (a->name, b->name);
-}
-static int compar_smooth (const struct smoothing *a, const struct smoothing *b) {
- if (a->idid)
- return -1;
- if (b->idid)
- return 1;
- return 0;
-}
-
+#include "face.h"
+#include "crc.h"
-/*
- * Returns the matching color in the coloralias if found,
- * 0 otherwise. Note that 0 will actually be black, so there is no
- * way the calling function can tell if an error occurred or not
- */
+faceidx blank_face, empty_face, magicmouth_face;
-static uint8 find_color(const char *name) {
- uint8 i;
- for(i=0;i faces;
-/* This reads the lib/faces file, getting color and visibility information.
- * it is called by ReadBmapNames.
- */
+static std::vector faces_freelist;
-static void ReadFaceData(void)
+faceidx face_alloc ()
{
- char buf[MAX_BUF], *cp;
- New_Face *on_face=NULL;
- FILE *fp;
-
- sprintf(buf,"%s/faces", settings.datadir);
- LOG(llevDebug,"Reading faces from %s...",buf);
- if ((fp=fopen(buf,"r"))==NULL) {
- LOG(llevError, "Cannot open faces file %s: %s\n", buf, strerror(errno));
- exit(-1);
- }
- while (fgets(buf, MAX_BUF, fp)!=NULL) {
- if (*buf=='#') continue;
- if (!strncmp(buf,"end",3)) {
- on_face = NULL;
- }
- else if (!strncmp(buf,"face",4)) {
- int tmp;
-
- cp = buf + 5;
- cp[strlen(cp)-1] = '\0'; /* remove newline */
-
- if ((tmp=FindFace(cp,-1))==-1) {
- LOG(llevError,"Could not find face %s\n", cp);
- continue;
- }
- on_face = &new_faces[tmp];
- on_face->visibility=0;
- }
- else if (on_face==NULL) {
- LOG(llevError,"Got line with no face set: %s\n", buf);
- }
- else if (!strncmp(buf,"color_fg",8)) {
- cp = buf + 9;
- cp[strlen(cp)-1] = '\0';
- if (on_face->magicmap==255) on_face->magicmap=find_color(cp);
- }
- else if (!strncmp(buf,"color_bg",8)) {
- /* ignore it */
- }
- else if (!strncmp(buf,"visibility",10)) {
- on_face->visibility = atoi(buf + 11);
- }
- else if (!strncmp(buf,"magicmap",8)) {
- cp=buf+9;
- cp[strlen(cp)-1] = '\0';
- on_face->magicmap=find_color(cp);
- }
- else if (!strncmp(buf,"is_floor",8)) {
- int value = atoi(buf+9);
- if (value) on_face->magicmap |= FACE_FLOOR;
- }
- else LOG(llevDebug,"Got unknown line in faces file: %s\n", buf);
- }
- LOG(llevDebug,"done\n");
- fclose(fp);
-}
+ faceidx idx;
-/* This reads the bmaps file to get all the bitmap names and
- * stuff. It only needs to be done once, because it is player
- * independent (ie, what display the person is on will not make a
- * difference.)
- */
-
-void ReadBmapNames (void) {
- char buf[MAX_BUF], *p, *q;
- FILE *fp;
- int value, nrofbmaps = 0, i;
- size_t l;
-
- bmaps_checksum=0;
- sprintf (buf,"%s/bmaps", settings.datadir);
- LOG(llevDebug,"Reading bmaps from %s...",buf);
- if ((fp=fopen(buf,"r"))==NULL) {
- LOG(llevError, "Cannot open bmaps file %s: %s\n", buf, strerror(errno));
- exit(-1);
- }
-
- /* First count how many bitmaps we have, so we can allocate correctly */
- while (fgets (buf, MAX_BUF, fp)!=NULL)
- if(buf[0] != '#' && buf[0] != '\n' )
- nrofbmaps++;
- rewind(fp);
-
- xbm = new bmappair [nrofbmaps];
- memset (xbm, 0, sizeof (struct bmappair) * nrofbmaps);
-
- while(nroffiles < nrofbmaps && fgets (buf, MAX_BUF, fp) != NULL) {
- if (*buf == '#')
- continue;
-
- p = (*buf == '\\') ? (buf + 1): buf;
- if (!(p = strtok (p , " \t")) || !(q = strtok (NULL , " \t\n"))) {
- LOG(llevDebug,"Warning, syntax error: %s\n", buf);
- continue;
- }
- value = atoi (p);
- xbm[nroffiles].name = strdup_local(q);
-
- /* We need to calculate the checksum of the bmaps file
- * name->number mapping to send to the client. This does not
- * need to match what sum or other utility may come up with -
- * as long as we get the same results on the same real file
- * data, it does the job as it lets the client know if
- * the file has the same data or not.
- */
- ROTATE_RIGHT(bmaps_checksum);
- bmaps_checksum += value & 0xff;
- bmaps_checksum &= 0xffffffff;
-
- ROTATE_RIGHT(bmaps_checksum);
- bmaps_checksum += (value >> 8) & 0xff;
- bmaps_checksum &= 0xffffffff;
- for (l=0; l= nrofpixmaps)
- nrofpixmaps = value+1;
+ if (!faces_freelist.empty ())
+ {
+ idx = faces_freelist.back ();
+ faces_freelist.pop_back ();
}
- fclose(fp);
+ else
+ {
+ idx = faces.size ();
- LOG(llevDebug,"done (got %d/%d/%d)\n",nrofpixmaps,nrofbmaps,nroffiles);
+ if (!idx) // skip index 0
+ idx = 1;
- new_faces = new New_Face [nrofpixmaps];
- for (i = 0; i < nrofpixmaps; i++) {
- new_faces[i].name = "";
- new_faces[i].number = i;
- new_faces[i].visibility=0;
- new_faces[i].magicmap=255;
- }
- for (i = 0; i < nroffiles; i++) {
- new_faces[xbm[i].number].name = xbm[i].name;
+ faces.resize (idx + 1);
}
- // non-pod datatype, likely not allowed
- qsort (xbm, nroffiles, sizeof(struct bmappair), (int (*)(const void*, const void*))compar);
+ return idx;
+}
- ReadFaceData();
+void
+faceinfo::unref ()
+{
+ if (--refcnt)
+ return;
- for (i = 0; i < nrofpixmaps; i++) {
- if (new_faces[i].magicmap==255) {
-#if 0 /* Useful for initial debugging, not needed now */
- LOG(llevDebug,"Face %s still had default magicmap, resetting to black\n",
- new_faces[i].name);
-#endif
- new_faces[i].magicmap=0;
- }
- }
- /* Actually forcefully setting the colors here probably should not
- * be done - it could easily create confusion.
- */
- blank_face = &new_faces[FindFace(BLANK_FACE_NAME, 0)];
- blank_face->magicmap = find_color ("khaki") | FACE_FLOOR;
-
- empty_face = &new_faces[FindFace(EMPTY_FACE_NAME, 0)];
-
- dark_faces[0] = &new_faces[FindFace (DARK_FACE1_NAME,0)];
- dark_faces[1] = &new_faces[FindFace (DARK_FACE2_NAME,0)];
- dark_faces[2] = &new_faces[FindFace (DARK_FACE3_NAME,0)];
+ refcnt = 1;
- smooth_face = &new_faces[FindFace(SMOOTH_FACE_NAME,0)];
}
-/* This returns an the face number of face 'name'. Number is constant
- * during an invocation, but not necessarily between versions (this
- * is because the faces are arranged in alphabetical order, so
- * if a face is removed or added, all faces after that will now
- * have a different number.
- *
- * the parameter error determines behaviour. If a face is
- * not found, then error is returned. This can be useful if
- * you want some default face used, or can be set to negative
- * so that it will be known that the face could not be found
- * (needed in client, so that it will know to request that image
- * from the server)
- */
-int FindFace (const char *name, int error) {
- struct bmappair *bp, tmp;
- char *p;
-
- if (!name)
- return error;
-
- if ((p = strchr (name, '\n')))
- *p = '\0';
+faceidx
+face_find (const char *name, faceidx defidx)
+{
+ if (!name)
+ return defidx;
- tmp.name = (char *)name;
- bp = (struct bmappair *)bsearch
- (&tmp, xbm, nroffiles, sizeof(struct bmappair), (int (*)(const void*, const void*))compar);
+ facehash_t::iterator i = facehash.find (name);
- return bp ? bp->number : error;
+ return i == facehash.end ()
+ ? defidx : i->second;
}
-/* Reads the smooth file to know how to smooth datas.
- * the smooth file if made of 2 elements lines.
- * lines starting with # are comment
- * the first element of line is face to smooth
- * the next element is the 16x2 faces picture
- * used for smoothing
- */
-int ReadSmooth (void) {
- char buf[MAX_BUF], *p, *q;
- FILE *fp;
- int smoothcount = 0;
-
- bmaps_checksum=0;
- sprintf (buf,"%s/smooth", settings.datadir);
- LOG(llevDebug,"Reading smooth from %s...",buf);
- if ((fp=fopen(buf,"r"))==NULL) {
- LOG(llevError, "Cannot open smooth file %s: %s\n", strerror(errno));
- exit(-1);
- }
+faceinfo *
+face_info (faceidx idx)
+{
+ assert (0 < (faceidx)-1); // faceidx must be unsigned
- /* First count how many smooth we have, so we can allocate correctly */
- while (fgets (buf, MAX_BUF, fp)!=NULL)
- if(buf[0] != '#' && buf[0] != '\n' )
- smoothcount++;
- rewind(fp);
-
- smooth = new smoothing [smoothcount];
-
- while(nrofsmooth < smoothcount && fgets (buf, MAX_BUF, fp)!=NULL) {
- if (*buf == '#')
- continue;
- p=strchr(buf,' ');
- if (!p)
- continue;
- *p='\0';
- q=buf;
- smooth[nrofsmooth].id=FindFace(q,0);
- q=p+1;
- smooth[nrofsmooth].smooth=FindFace(q,0);
- nrofsmooth++;
- }
- fclose(fp);
+ if (idx >= faces.size ())
+ return 0;
- LOG(llevDebug,"done (got %d smooth entries)\n",nrofsmooth);
- qsort (smooth, nrofsmooth, sizeof(struct smoothing), (int (*)(const void*, const void*))compar_smooth);
- return nrofsmooth;
+ return &faces [idx];
}
-/**
- * Find the smooth face for a given face.
- *
- * @param face the face to find the smoothing face for
- *
- * @param smoothed return value: set to smooth face
- *
- * @return 1=smooth face found, 0=no smooth face found
- */
-int FindSmooth (uint16 face, uint16* smoothed) {
- struct smoothing *bp, tmp;
+facedata *
+faceinfo::data (int faceset) const
+{
+ if (!face [faceset].chksum_len)
+ faceset = 0;
- tmp.id = face;
- bp = (struct smoothing *)bsearch
- (&tmp, smooth, nrofsmooth, sizeof(struct smoothing), (int (*)(const void*, const void*))compar_smooth);
- (*smoothed)=0;
- if (bp)
- (*smoothed)=bp->smooth;
- return bp ? 1 : 0;
+ return (facedata *)(face + faceset);
}
-/**
- * Deallocates memory allocated by ReadBmapNames() and ReadSmooth().
- */
-void free_all_images(void)
+facedata *
+face_data (faceidx idx, int faceset)
{
- int i;
-
- for (i=0; idata (faceset);
- delete [] xbm;
- delete [] new_faces;
- delete [] smooth;
+ return 0;
}
+