ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.C
Revision: 1.3
Committed: Sun Sep 3 00:18:39 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -3 lines
Log Message:
THIS CODE WILL NOT COMPILE
use the STABLE tag instead.

- major changes in object lifetime and memory management
- replaced manual refcounting by shstr class
- removed quest system
- many optimisations
- major changes

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *rcsid_init_c =
3 root 1.3 * "$Id: init.C,v 1.2 2006-08-29 08:01:35 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=NULL;
262     animations_allocated=0;
263     init_defaults();
264     }
265    
266     /*
267     * Sets up and initialises the linked list of free and used objects.
268     * Allocates a certain chunk of objects and puts them on the free list.
269     * Called by init_library();
270     */
271    
272     void init_objects(void) {
273     int i;
274     /* Initialize all objects: */
275     objects=NULL;
276     active_objects = NULL;
277    
278     #ifdef MEMORY_DEBUG
279     free_objects=NULL;
280     #else
281     free_objects=objarray;
282     objarray[0].prev=NULL,
283     objarray[0].next= &objarray[1],
284     SET_FLAG(&objarray[0], FLAG_REMOVED);
285     SET_FLAG(&objarray[0], FLAG_FREED);
286     for(i=1;i<STARTMAX-1;i++) {
287     objarray[i].next= &objarray[i+1];
288     objarray[i].prev= &objarray[i-1];
289     SET_FLAG(&objarray[i], FLAG_REMOVED);
290     SET_FLAG(&objarray[i], FLAG_FREED);
291     }
292     objarray[STARTMAX-1].next=NULL;
293     objarray[STARTMAX-1].prev= &objarray[STARTMAX-2];
294     SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED);
295     SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED);
296     #endif
297     }
298    
299     /*
300     * Initialises global variables which can be changed by options.
301     * Called by init_library().
302     */
303    
304     void init_defaults(void) {
305     editor=0;
306     nroferrors=0;
307     }
308    
309    
310     void init_dynamic (void) {
311     archetype *at = first_archetype;
312     while (at) {
313 root 1.2 if (at->clone.type == MAP) {
314 elmex 1.1 if (at->clone.race) {
315     strcpy (first_map_ext_path, at->clone.race);
316     }
317     if (EXIT_PATH (&at->clone)) {
318     strcpy (first_map_path, EXIT_PATH (&at->clone));
319     return;
320     }
321 root 1.2 }
322     at = at->next;
323 elmex 1.1 }
324     LOG(llevDebug,"You Need a archetype called 'map' and it have to contain start map\n");
325     exit (-1);
326     }
327    
328     unsigned long todtick;
329    
330     /*
331     * Write out the current time to the file so time does not
332     * reset every time the server reboots.
333     */
334    
335     void write_todclock(void)
336     {
337     char filename[MAX_BUF];
338     FILE *fp;
339    
340     sprintf(filename, "%s/clockdata", settings.localdir);
341     if ((fp = fopen(filename, "w")) == NULL) {
342 root 1.2 LOG(llevError, "Cannot open %s for writing\n", filename);
343     return;
344 elmex 1.1 }
345     fprintf(fp, "%lu", todtick);
346     fclose(fp);
347     }
348    
349     /*
350     * Initializes the gametime and TOD counters
351     * Called by init_library().
352     */
353    
354     void init_clocks(void)
355     {
356     char filename[MAX_BUF];
357     FILE *fp;
358     static int has_been_done=0;
359    
360     if (has_been_done)
361     return;
362     else
363     has_been_done = 1;
364    
365     sprintf(filename, "%s/clockdata", settings.localdir);
366     LOG(llevDebug, "Reading clockdata from %s...", filename);
367     if ((fp = fopen(filename, "r")) == NULL) {
368     LOG(llevError, "Can't open %s.\n", filename);
369 root 1.2 todtick = 0;
370     write_todclock();
371     return;
372 elmex 1.1 }
373     fscanf(fp, "%lu", &todtick);
374     LOG(llevDebug, "todtick=%lu\n", todtick);
375     fclose(fp);
376     }
377    
378     /*
379     * Initializes the attack messages.
380     * Called by init_library().
381     */
382    
383     //attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS];
384    
385     void init_attackmess(void){
386     char buf[MAX_BUF];
387     char filename[MAX_BUF];
388     char *cp, *p;
389     FILE *fp;
390     static int has_been_done=0;
391     int mess, level, comp;
392     int mode=0, total=0;
393    
394     if (has_been_done)
395     return;
396     else
397     has_been_done = 1;
398    
399     sprintf(filename, "%s/attackmess", settings.datadir);
400     LOG(llevDebug, "Reading attack messages from %s...", filename);
401     if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
402     LOG(llevError, "Can't open %s.\n", filename);
403 root 1.2 return;
404 elmex 1.1 }
405    
406     level = 0;
407     while (fgets(buf, MAX_BUF, fp)!=NULL) {
408     if (*buf=='#') continue;
409 root 1.2 if((cp=strchr(buf,'\n'))!=NULL)
410 elmex 1.1 *cp='\0';
411 root 1.2 cp=buf;
412     while(*cp==' ') /* Skip blanks */
413     cp++;
414    
415     if (strncmp(cp, "TYPE:", 5)==0) {
416     p = strtok(buf, ":");
417     p = strtok(NULL, ":");
418     if (mode == 1) {
419     attack_mess[mess][level].level = -1;
420     attack_mess[mess][level].buf1 = NULL;
421     attack_mess[mess][level].buf2 = NULL;
422     attack_mess[mess][level].buf3 = NULL;
423     }
424     level = 0;
425     mess = atoi(p);
426     mode = 1;
427     continue;
428     }
429     if (mode==1) {
430     p = strtok(buf, "=");
431     attack_mess[mess][level].level = atoi(buf);
432     p = strtok(NULL, "=");
433     if (p != NULL)
434     attack_mess[mess][level].buf1 = strdup_local(p);
435     else
436     attack_mess[mess][level].buf1 = strdup_local("");
437     mode = 2;
438     continue;
439     } else if (mode==2) {
440     p = strtok(buf, "=");
441     attack_mess[mess][level].level = atoi(buf);
442     p = strtok(NULL, "=");
443     if (p != NULL)
444     attack_mess[mess][level].buf2 = strdup_local(p);
445     else
446     attack_mess[mess][level].buf2 = strdup_local("");
447     mode = 3;
448     continue;
449     } else if (mode==3) {
450     p = strtok(buf, "=");
451     attack_mess[mess][level].level = atoi(buf);
452     p = strtok(NULL, "=");
453     if (p != NULL)
454     attack_mess[mess][level].buf3 = strdup_local(p);
455     else
456     attack_mess[mess][level].buf3 = strdup_local("");
457     mode = 1;
458     level++;
459     total++;
460     continue;
461     }
462 elmex 1.1 }
463     LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1);
464     close_and_delete(fp, comp);
465     }