--- deliantra/server/common/readable.C 2009/10/16 00:02:22 1.49 +++ deliantra/server/common/readable.C 2010/04/15 21:49:15 1.58 @@ -1,9 +1,9 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team - * Copyright (©) 1992,2007 Frank Tore Johansen + * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2002 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992 Frank Tore Johansen * * 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 @@ -110,20 +110,9 @@ static int nrofmon = 0, need_to_write_bookarchive = 0; - -/* this is needed to keep track of status of initialisation - * of the message file */ -static int nrofmsg = 0; - -/* first_msg is the started of the linked list of messages as read from - * the messages file - */ -static linked_char *first_msg = NULL; - /* * Spellpath information */ - static uint32 spellpathdef[NRSPELLPATHS] = { PATH_PROT, PATH_FIRE, @@ -499,7 +488,7 @@ {MSG_TYPE_MONUMENT, MSG_TYPE_MONUMENT_WALL_2, "readable-monument-wall-2"}, {MSG_TYPE_MONUMENT, MSG_TYPE_MONUMENT_WALL_3, "readable-monument-wall-3"} }; -int last_readable_subtype = sizeof (readable_message_types) / sizeof (readable_message_type); +static int last_readable_subtype = sizeof (readable_message_types) / sizeof (readable_message_type); static int max_titles[6] = { ((sizeof (light_book_name) / sizeof (char *)) + (sizeof (heavy_book_name) / sizeof (char *))) * (sizeof (book_author) / sizeof (char *)), @@ -517,7 +506,7 @@ *****************************************************************************/ static titlelist * -get_empty_booklist (void) +get_empty_booklist () { titlelist *bl = new titlelist; @@ -528,7 +517,7 @@ } static title * -get_empty_book (void) +get_empty_book () { title *t = new title; @@ -547,6 +536,9 @@ static titlelist * get_titlelist (int i) { + if (!booklist) + booklist = get_empty_booklist (); + titlelist *tl = booklist; int number = i; @@ -559,7 +551,7 @@ tl->next = get_empty_booklist (); tl = tl->next; - number--; + --number; } return tl; @@ -621,16 +613,6 @@ return (char *) rbuf; } -static int -book_overflow (const char *buf1, const char *buf2, int booksize) -{ - if (buf_overflow (buf1, buf2, BOOK_BUF - 2) /* 2 less so always room for trailing \n */ - || buf_overflow (buf1, buf2, booksize)) - return 1; - - return 0; -} - /***************************************************************************** * * Start of initialisation related functions. @@ -642,91 +624,72 @@ * created and updated across multiple runs of the program. */ static void -init_book_archive (void) +init_book_archive () { - FILE *fp; - int comp, nroftitle = 0; - char buf[MAX_BUF], fname[MAX_BUF], *cp; - title *book = NULL; + int nroftitle = 0; + char fname[MAX_BUF]; titlelist *bl = get_empty_booklist (); - static int did_init_barch; - - if (did_init_barch) - return; - - did_init_barch = 1; - - if (!booklist) - booklist = bl; sprintf (fname, "%s/bookarch", settings.localdir); LOG (llevDebug, " Reading bookarch from %s...\n", fname); - if ((fp = open_and_uncompress (fname, 0, &comp)) != NULL) + object_thawer thawer (fname); + + if (!thawer) { - int value, type = 0; - size_t i; + LOG (llevDebug, "could not read bookarch file\n"); + return; + } + + while (thawer.kw) + { + if (thawer.kw != KW_title) + if (!thawer.parse_error ("bookarch file")) + break; - while (fgets (buf, MAX_BUF, fp) != NULL) + title *book = get_empty_book (); /* init new book entry */ + thawer.get (book->name); + + int type = -1; + + for (;;) { - if (*buf == '#') - continue; - if ((cp = strchr (buf, '\n')) != NULL) - *cp = '\0'; - cp = buf; - while (*cp == ' ') /* Skip blanks */ - cp++; - if (!strncmp (cp, "title", 4)) - { - book = get_empty_book (); /* init new book entry */ - book->name = strchr (cp, ' ') + 1; - type = -1; - nroftitle++; - continue; - } - if (!strncmp (cp, "authour", 4)) - { - book->authour = strchr (cp, ' ') + 1; - } - if (!strncmp (cp, "arch", 4)) - { - book->archname = strchr (cp, ' ') + 1; - } - else if (sscanf (cp, "level %d", &value)) - { - book->level = (uint16) value; - } - else if (sscanf (cp, "type %d", &value)) - { - type = (uint16) value; - } - else if (sscanf (cp, "size %d", &value)) - { - book->size = (uint16) value; - } - else if (sscanf (cp, "index %d", &value)) + thawer.next (); + + switch (thawer.kw) { - book->msg_index = (uint16) value; + case KW_type: thawer.get (type ); break; + case KW_authour: thawer.get (book->authour ); break; + case KW_arch: thawer.get (book->archname ); break; + case KW_level: thawer.get (book->level ); break; + case KW_size: thawer.get (book->size ); break; + case KW_index: thawer.get (book->msg_index); break; + + case KW_end: + /* link it */ + bl = get_titlelist (type); + book->next = bl->first_book; + bl->first_book = book; + bl->number++; + ++nroftitle; + goto book_done; + + default: + delete book; + goto book_done; } - else if (!strncmp (cp, "end", 3)) - { /* link it */ - bl = get_titlelist (type); - book->next = bl->first_book; - bl->first_book = book; - bl->number++; - } - } - LOG (llevDebug, "book archives(used/avail): \n"); - for (bl = booklist, i = 0; bl != NULL && i < sizeof (max_titles) / sizeof (*max_titles); bl = bl->next, i++) - { - LOG (llevDebug, " (%d/%d)\n", bl->number, max_titles[i]); } - close_and_delete (fp, comp); + +book_done: + thawer.next (); } -#ifdef BOOK_MSG_DEBUG + LOG (llevDebug, "book archives(used/avail): \n"); + int i; + for (bl = booklist, i = 0; bl && i < sizeof (max_titles) / sizeof (*max_titles); bl = bl->next, i++) + LOG (llevDebug, " (%d/%d)\n", bl->number, max_titles[i]); + LOG (llevDebug, "init_book_archive() got %d titles.\n", nroftitle); -#endif LOG (llevDebug, " done.\n"); } @@ -767,7 +730,7 @@ * all the readable information. */ void -init_readable (void) +init_readable () { static int did_this; @@ -1228,7 +1191,7 @@ * of a randomly selected monster. */ static const char * -mon_info_msg (int level, int booksize) +mon_info_msg (int level) { static dynbuf_text buf; buf.clear (); @@ -1264,7 +1227,7 @@ * of 1-6 artifacts drawn sequentially from the artifact list. */ static const char * -artifact_msg (int level, int booksize) +artifact_msg (int level) { artifactlist *al = NULL; artifact *art; @@ -1371,7 +1334,7 @@ tmp = object::create (); add_abilities (tmp, art->item); tmp->type = type; - SET_FLAG (tmp, FLAG_IDENTIFIED); + tmp->set_flag (FLAG_IDENTIFIED); if ((ch = describe_item (tmp, 0)) && strlen (ch) > 1) buf << "\rProperties of this artifact include:\r" << ch << "\n"; @@ -1393,7 +1356,7 @@ * a given spellpath. */ static char * -spellpath_msg (int level, int booksize) +spellpath_msg (int level) { static dynbuf_text buf; buf.clear (); @@ -1429,7 +1392,7 @@ /* Geez, no spells were generated. */ if (!seen) if (rndm (4)) /* usually, lets make a recursive call... */ - return spellpath_msg (level, booksize); + return spellpath_msg (level); else /* give up, cause knowing no spells exist for path is info too. */ buf << "- no known spells exist.\n"; @@ -1570,7 +1533,7 @@ * of a random god. Used by the book hack. b.t. */ static const char * -god_info_msg (int level, int booksize) +god_info_msg (int level) { const char *name = NULL; object *god = pntr_to_god_obj (get_rand_god ()); @@ -1762,9 +1725,7 @@ void tailor_readable_ob (object *book, int msg_type) { - char msgbuf[BOOK_BUF]; int level = book->level ? rndm (book->level) + 1 : 1; - int book_buf_size; /* safety */ if (book->type != BOOK) @@ -1773,9 +1734,6 @@ if (level <= 0) return; /* if no level no point in doing any more... */ - /* Max text length this book can have. */ - book_buf_size = BOOKSIZE (book); - /* &&& The message switch &&& */ /* Below all of the possible types of messages in the "book"s. */ @@ -1787,24 +1745,25 @@ * and add_authour(). * 4) you may want separate authour/book name arrays in read.h */ + const char *new_msg = ""; msg_type = msg_type > 0 ? msg_type : rndm (8); switch (msg_type) { case 1: /* monster attrib */ - strcpy (msgbuf, mon_info_msg (level, book_buf_size)); + new_msg = mon_info_msg (level); break; case 2: /* artifact attrib */ - strcpy (msgbuf, artifact_msg (level, book_buf_size)); + new_msg = artifact_msg (level); break; case 3: /* grouping incantations/prayers by path */ - strcpy (msgbuf, spellpath_msg (level, book_buf_size)); + new_msg = spellpath_msg (level); break; case 4: /* describe an alchemy formula */ make_formula_book (book, level); /* make_formula_book already gives title */ return; case 5: /* bits of information about a god */ - strcpy (msgbuf, god_info_msg (level, book_buf_size)); + new_msg = god_info_msg (level); break; case 0: /* use info list in lib/ */ default: @@ -1813,68 +1772,22 @@ return; } - if (strlen (msgbuf) > 1) + if (strlen (new_msg) > 1) { - book->msg = msgbuf; + book->msg = new_msg; /* lets give the "book" a new name, which may be a compound word */ change_book (book, msg_type); } } - -/***************************************************************************** - * - * Cleanup routine for readble stuff. - * - *****************************************************************************/ - -void -free_all_readable (void) -{ - titlelist *tlist, *tnext; - title *title1, *titlenext; - linked_char *lmsg, *nextmsg; - objectlink *monlink, *nextmon; - - LOG (llevDebug, "freeing all book information\n"); - - for (tlist = booklist; tlist; tlist = tnext) - { - tnext = tlist->next; - - for (title1 = tlist->first_book; title1; title1 = titlenext) - { - titlenext = title1->next; - delete title1; - } - - delete tlist; - } - - for (lmsg = first_msg; lmsg; lmsg = nextmsg) - { - nextmsg = lmsg->next; - delete lmsg; - } - - for (monlink = first_mon_info; monlink; monlink = nextmon) - { - nextmon = monlink->next; - delete monlink; - } -} - - /***************************************************************************** * * Writeback routine for updating the bookarchive. * ****************************************************************************/ - /* write_book_archive() - write out the updated book archive */ - void -write_book_archive (void) +write_book_archive () { FILE *fp; int index = 0; @@ -1885,15 +1798,14 @@ /* If nothing changed, don't write anything */ if (!need_to_write_bookarchive) return; + need_to_write_bookarchive = 0; sprintf (fname, "%s/bookarch", settings.localdir); LOG (llevDebug, "Updating book archive: %s...\n", fname); if ((fp = fopen (fname, "w")) == NULL) - { - LOG (llevDebug, "Can't open book archive file %s\n", fname); - } + LOG (llevDebug, "Can't open book archive file %s\n", fname); else { while (bl) @@ -1910,13 +1822,16 @@ fprintf (fp, "index %d\n", book->msg_index); fprintf (fp, "end\n"); } + bl = bl->next; index++; } + fclose (fp); chmod (fname, SAVE_MODE); } } + readable_message_type * get_readable_message_type (object *readable) {