ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.C
Revision: 1.5
Committed: Mon Sep 4 11:07:59 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +1 -21 lines
Log Message:
Changes...

- alternative shstr representation, saves code
- use glibs splice memory allocator (seems slower)
- use simpler memory/lifetime management for objects, no recycling

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *rcsid_init_c =
3 root 1.5 * "$Id: init.C,v 1.4 2006-09-03 07:57:54 root Exp $";
4 elmex 1.1 */
5    
6     /*
7     CrossFire, A Multiplayer game for X-windows
8    
9     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10     Copyright (C) 1992 Frank Tore Johansen
11    
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16    
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20     GNU General Public License for more details.
21    
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25    
26     The authors can be reached via e-mail at crossfire-devel@real-time.com
27     */
28    
29     #define EXTERN
30     #define INIT_C
31     #include <global.h>
32     #include <object.h>
33    
34     /* You unforunately need to looking in include/global.h to see what these
35     * correspond to.
36     */
37     struct Settings settings = {
38     LOGFILE, /* Logfile */
39     CSPORT, /* Client/server port */
40    
41     /* Debug level */
42     #ifdef DEBUG
43     llevDebug,
44     #else
45     llevInfo,
46     #endif
47    
48     0, NULL, 0, /* dumpvalues, dumparg, daemonmode */
49     0, /* argc */
50     NULL, /* argv */
51     CONFDIR,
52     DATADIR,
53     LOCALDIR,
54     PLAYERDIR, MAPDIR, ARCHETYPES,REGIONS,TREASURES,
55     UNIQUE_DIR, TEMPLATE_DIR,
56     TMPDIR,
57     STAT_LOSS_ON_DEATH,
58     PK_LUCK_PENALTY,
59     PERMANENT_EXPERIENCE_RATIO,
60     DEATH_PENALTY_RATIO,
61     DEATH_PENALTY_LEVEL,
62     BALANCED_STAT_LOSS,
63     NOT_PERMADETH,
64     SIMPLE_EXP,
65     RESET_LOCATION_TIME,
66     SET_TITLE,
67     RESURRECTION,
68     SEARCH_ITEMS,
69     SPELL_ENCUMBRANCE,
70     SPELL_FAILURE_EFFECTS,
71     CASTING_TIME,
72     REAL_WIZ,
73     RECYCLE_TMP_MAPS,
74     EXPLORE_MODE,
75     SPELLPOINT_LEVEL_DEPEND,
76     SET_FRIENDLY_FIRE,
77     "", /* Who format specifier */
78     "", /* who wiz format specifier */
79     MOTD,
80     "rules",
81     "news",
82     "", /* DM_MAIL */
83     0, /* This and the next 3 values are metaserver values */
84     "",
85     "",
86     0,
87     "",
88     0,0,0,0,0,0,0,0, /* worldmap settings*/
89     EMERGENCY_MAPPATH, EMERGENCY_X, EMERGENCY_Y,
90     0,
91     1.0,
92     /* Armor enchantment stuff */
93     ARMOR_MAX_ENCHANT,
94     ARMOR_WEIGHT_REDUCTION,
95     ARMOR_WEIGHT_LINEAR,
96     ARMOR_SPEED_IMPROVEMENT,
97     ARMOR_SPEED_LINEAR,
98     1, /* no_player_stealing */
99     1, /* create_home_portals */
100     };
101    
102     /* perhaps not the best place for this, but needs to be
103     * in some file in the common area so that standalone
104     * programs, like the random map generator, can be built.
105     */
106     const char* const spellpathnames[NRSPELLPATHS] = {
107     "Protection",
108     "Fire",
109     "Frost",
110     "Electricity",
111     "Missiles",
112     "Self",
113     "Summoning",
114     "Abjuration",
115     "Restoration",
116     "Detonation",
117     "Mind",
118     "Creation",
119     "Teleportation",
120     "Information",
121     "Transmutation",
122     "Transferrence",
123     "Turning",
124     "Wounding",
125     "Death",
126     "Light"
127     };
128    
129    
130     /* This loads the emergency map information from a
131     * .emergency file in the map directory. Doing this makes
132     * it easier to switch between map distributions (don't need
133     * to recompile. Note that there is no reason I see that
134     * this could not be re-loaded during play, but it seems
135     * like there should be little reason to do that.
136     */
137     static void init_emergency_mappath(void)
138     {
139     char filename[MAX_BUF], tmpbuf[MAX_BUF];
140     FILE *fp;
141     int online=0;
142    
143     /* If this file doesn't exist, not a big deal */
144     sprintf(filename,"%s/%s/.emergency",settings.datadir, settings.mapdir);
145     if ((fp = fopen(filename, "r"))!=NULL) {
146 root 1.2 while (fgets(tmpbuf, MAX_BUF-1, fp)) {
147     if (tmpbuf[0] == '#') continue; /* ignore comments */
148    
149     if (online == 0) {
150     tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */
151     settings.emergency_mapname = strdup_local(tmpbuf);
152     }
153     else if (online == 1) {
154     settings.emergency_x = atoi(tmpbuf);
155     }
156    
157     else if (online == 2) {
158     settings.emergency_y = atoi(tmpbuf);
159     }
160     online++;
161     if (online>2) break;
162     }
163     fclose(fp);
164     if (online<=2)
165     LOG(llevError,"Online read partial data from %s\n", filename);
166     LOG(llevDebug,"Emergency mappath reset to %s (%d, %d)\n", settings.emergency_mapname,
167     settings.emergency_x, settings.emergency_y);
168 elmex 1.1 }
169     }
170    
171    
172     /*
173     * It is vital that init_library() is called by any functions
174     * using this library.
175     * If you want to lessen the size of the program using the library,
176     * you can replace the call to init_library() with init_globals() and
177     * init_function_pointers(). Good idea to also call init_vars and
178     * init_hash_table if you are doing any object loading.
179     */
180    
181     void init_library(void) {
182     init_environ();
183     init_globals();
184     init_objects();
185     init_vars();
186     init_block();
187     ReadBmapNames ();
188     ReadSmooth();
189     init_anim(); /* Must be after we read in the bitmaps */
190     init_archetypes(); /* Reads all archetypes from file */
191     init_dynamic ();
192     init_attackmess();
193     init_clocks();
194     init_emergency_mappath();
195     init_experience();
196     }
197    
198    
199     /* init_environ initializes values from the environmental variables.
200     * it needs to be called very early, since command line options should
201     * overwrite these if specified.
202     */
203     void init_environ(void) {
204     char *cp;
205    
206     cp=getenv("CROSSFIRE_LIBDIR");
207     if (cp) settings.datadir=cp;
208     cp=getenv("CROSSFIRE_LOCALDIR");
209     if (cp) settings.localdir=cp;
210     cp=getenv("CROSSFIRE_PLAYERDIR");
211     if (cp) settings.playerdir=cp;
212     cp=getenv("CROSSFIRE_MAPDIR");
213     if (cp) settings.mapdir=cp;
214     cp=getenv("CROSSFIRE_ARCHETYPES");
215     if (cp) settings.archetypes=cp;
216     cp=getenv("CROSSFIRE_TREASURES");
217     if (cp) settings.treasures=cp;
218     cp=getenv("CROSSFIRE_UNIQUEDIR");
219     if (cp) settings.uniquedir=cp;
220     cp=getenv("CROSSFIRE_TEMPLATEDIR");
221     if (cp) settings.templatedir=cp;
222     cp=getenv("CROSSFIRE_TMPDIR");
223     if (cp) settings.tmpdir=cp;
224     }
225    
226    
227     /*
228     * Initialises all global variables.
229     * Might use environment-variables as default for some of them.
230     */
231    
232     void init_globals(void) {
233     if (settings.logfilename[0] == 0) {
234 root 1.2 logfile = stderr;
235 elmex 1.1 }
236     else if ((logfile=fopen(settings.logfilename, "a"))==NULL) {
237 root 1.2 fprintf(stderr,"Unable to open %s as the logfile - will use stderr instead\n",
238     settings.logfilename);
239     logfile = stderr;
240 elmex 1.1 }
241     else {
242 root 1.2 setvbuf(logfile, NULL, _IOLBF, 0);
243 elmex 1.1 }
244     exiting = 0;
245     first_player=NULL;
246     first_friendly_object=NULL;
247     first_map=NULL;
248     first_treasurelist=NULL;
249     first_artifactlist=NULL;
250     first_archetype=NULL;
251     *first_map_ext_path=0;
252     warn_archetypes=0;
253     nroftreasures = 0;
254     nrofartifacts = 0;
255     nrofallowedstr=0;
256     ring_arch = NULL;
257     amulet_arch = NULL;
258     staff_arch = NULL;
259     trying_emergency_save = 0;
260     num_animations=0;
261     animations_allocated=0;
262     init_defaults();
263     }
264    
265     /*
266     * Sets up and initialises the linked list of free and used objects.
267     * Allocates a certain chunk of objects and puts them on the free list.
268     * Called by init_library();
269     */
270    
271     void init_objects(void) {
272     int i;
273     /* Initialize all objects: */
274     objects=NULL;
275     active_objects = NULL;
276     }
277    
278     /*
279     * Initialises global variables which can be changed by options.
280     * Called by init_library().
281     */
282    
283     void init_defaults(void) {
284     editor=0;
285     nroferrors=0;
286     }
287    
288    
289     void init_dynamic (void) {
290     archetype *at = first_archetype;
291     while (at) {
292 root 1.2 if (at->clone.type == MAP) {
293 elmex 1.1 if (at->clone.race) {
294     strcpy (first_map_ext_path, at->clone.race);
295     }
296     if (EXIT_PATH (&at->clone)) {
297     strcpy (first_map_path, EXIT_PATH (&at->clone));
298     return;
299     }
300 root 1.2 }
301     at = at->next;
302 elmex 1.1 }
303     LOG(llevDebug,"You Need a archetype called 'map' and it have to contain start map\n");
304     exit (-1);
305     }
306    
307     unsigned long todtick;
308    
309     /*
310     * Write out the current time to the file so time does not
311     * reset every time the server reboots.
312     */
313    
314     void write_todclock(void)
315     {
316     char filename[MAX_BUF];
317     FILE *fp;
318    
319     sprintf(filename, "%s/clockdata", settings.localdir);
320     if ((fp = fopen(filename, "w")) == NULL) {
321 root 1.2 LOG(llevError, "Cannot open %s for writing\n", filename);
322     return;
323 elmex 1.1 }
324     fprintf(fp, "%lu", todtick);
325     fclose(fp);
326     }
327    
328     /*
329     * Initializes the gametime and TOD counters
330     * Called by init_library().
331     */
332    
333     void init_clocks(void)
334     {
335     char filename[MAX_BUF];
336     FILE *fp;
337     static int has_been_done=0;
338    
339     if (has_been_done)
340     return;
341     else
342     has_been_done = 1;
343    
344     sprintf(filename, "%s/clockdata", settings.localdir);
345     LOG(llevDebug, "Reading clockdata from %s...", filename);
346     if ((fp = fopen(filename, "r")) == NULL) {
347     LOG(llevError, "Can't open %s.\n", filename);
348 root 1.2 todtick = 0;
349     write_todclock();
350     return;
351 elmex 1.1 }
352     fscanf(fp, "%lu", &todtick);
353     LOG(llevDebug, "todtick=%lu\n", todtick);
354     fclose(fp);
355     }
356    
357     /*
358     * Initializes the attack messages.
359     * Called by init_library().
360     */
361    
362     //attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS];
363    
364     void init_attackmess(void){
365     char buf[MAX_BUF];
366     char filename[MAX_BUF];
367     char *cp, *p;
368     FILE *fp;
369     static int has_been_done=0;
370     int mess, level, comp;
371     int mode=0, total=0;
372    
373     if (has_been_done)
374     return;
375     else
376     has_been_done = 1;
377    
378     sprintf(filename, "%s/attackmess", settings.datadir);
379     LOG(llevDebug, "Reading attack messages from %s...", filename);
380     if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
381     LOG(llevError, "Can't open %s.\n", filename);
382 root 1.2 return;
383 elmex 1.1 }
384    
385     level = 0;
386     while (fgets(buf, MAX_BUF, fp)!=NULL) {
387     if (*buf=='#') continue;
388 root 1.2 if((cp=strchr(buf,'\n'))!=NULL)
389 elmex 1.1 *cp='\0';
390 root 1.2 cp=buf;
391     while(*cp==' ') /* Skip blanks */
392     cp++;
393    
394     if (strncmp(cp, "TYPE:", 5)==0) {
395     p = strtok(buf, ":");
396     p = strtok(NULL, ":");
397     if (mode == 1) {
398     attack_mess[mess][level].level = -1;
399     attack_mess[mess][level].buf1 = NULL;
400     attack_mess[mess][level].buf2 = NULL;
401     attack_mess[mess][level].buf3 = NULL;
402     }
403     level = 0;
404     mess = atoi(p);
405     mode = 1;
406     continue;
407     }
408     if (mode==1) {
409     p = strtok(buf, "=");
410     attack_mess[mess][level].level = atoi(buf);
411     p = strtok(NULL, "=");
412     if (p != NULL)
413     attack_mess[mess][level].buf1 = strdup_local(p);
414     else
415     attack_mess[mess][level].buf1 = strdup_local("");
416     mode = 2;
417     continue;
418     } else if (mode==2) {
419     p = strtok(buf, "=");
420     attack_mess[mess][level].level = atoi(buf);
421     p = strtok(NULL, "=");
422     if (p != NULL)
423     attack_mess[mess][level].buf2 = strdup_local(p);
424     else
425     attack_mess[mess][level].buf2 = strdup_local("");
426     mode = 3;
427     continue;
428     } else if (mode==3) {
429     p = strtok(buf, "=");
430     attack_mess[mess][level].level = atoi(buf);
431     p = strtok(NULL, "=");
432     if (p != NULL)
433     attack_mess[mess][level].buf3 = strdup_local(p);
434     else
435     attack_mess[mess][level].buf3 = strdup_local("");
436     mode = 1;
437     level++;
438     total++;
439     continue;
440     }
441 elmex 1.1 }
442     LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1);
443     close_and_delete(fp, comp);
444     }