ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/init.C
Revision: 1.78
Committed: Fri Mar 26 00:59:22 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.77: +2 -2 lines
Log Message:
remove bogus 2007 copyright that was added wrongly by the script, update to affero license

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.59 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.34 *
4 root 1.77 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.78 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992 Frank Tore Johansen
7 pippijn 1.34 *
8 root 1.71 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 pippijn 1.34 *
13 root 1.56 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.34 *
18 root 1.71 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 root 1.52 *
22 root 1.59 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.34 */
24 elmex 1.1
25     #include <global.h>
26     #include <material.h>
27 root 1.22 #include <sproto.h>
28 elmex 1.1
29     /* This loads the settings file. There could be debate whether this should
30     * be here or in the common directory - but since only the server needs this
31     * information, having it here probably makes more sense.
32     */
33 root 1.66 void
34 root 1.76 load_settings ()
35 elmex 1.1 {
36 root 1.9 char buf[MAX_BUF], *cp;
37     int has_val, comp;
38     FILE *fp;
39    
40     sprintf (buf, "%s/settings", settings.confdir);
41    
42     /* We don't require a settings file at current time, but down the road,
43     * there will probably be so many values that not having a settings file
44     * will not be a good thing.
45     */
46 root 1.43 if (!(fp = open_and_uncompress (buf, 0, &comp)))
47 root 1.9 {
48 root 1.43 LOG (llevError, "Error: No settings file found\n");
49     exit (1);
50 elmex 1.1 }
51 root 1.43
52 root 1.9 while (fgets (buf, MAX_BUF - 1, fp) != NULL)
53     {
54     if (buf[0] == '#')
55     continue;
56     /* eliminate newline */
57     if ((cp = strrchr (buf, '\n')) != NULL)
58     *cp = '\0';
59    
60     /* Skip over empty lines */
61     if (buf[0] == 0)
62     continue;
63    
64     /* Skip all the spaces and set them to nulls. If not space,
65     * set cp to "" to make strcpy's and the like easier down below.
66     */
67     if ((cp = strchr (buf, ' ')) != NULL)
68     {
69     while (*cp == ' ')
70     *cp++ = 0;
71     has_val = 1;
72     }
73     else
74     {
75 root 1.44 cp = (char *)"";
76 root 1.9 has_val = 0;
77     }
78    
79 root 1.72 if (!strcasecmp (buf, "not_permadeth"))
80 root 1.9 {
81     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
82     {
83     settings.not_permadeth = TRUE;
84     }
85     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
86     {
87     settings.not_permadeth = FALSE;
88     }
89     else
90     {
91     LOG (llevError, "load_settings: Unknown value for not_permadeth" ": %s\n", cp);
92     }
93     }
94     else if (!strcasecmp (buf, "resurrection"))
95     {
96     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
97     {
98     settings.resurrection = TRUE;
99     }
100     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
101     {
102     settings.resurrection = FALSE;
103     }
104     else
105     {
106     LOG (llevError, "load_settings: Unknown value for resurrection" ": %s\n", cp);
107     }
108     }
109     else if (!strcasecmp (buf, "set_title"))
110     {
111     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
112     {
113     settings.set_title = TRUE;
114     }
115     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
116     {
117     settings.set_title = FALSE;
118     }
119     else
120     {
121     LOG (llevError, "load_settings: Unknown value for set_title" ": %s\n", cp);
122     }
123     }
124     else if (!strcasecmp (buf, "search_items"))
125     {
126     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
127     {
128     settings.search_items = TRUE;
129     }
130     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
131     {
132     settings.search_items = FALSE;
133     }
134     else
135     {
136     LOG (llevError, "load_settings: Unknown value for search_items" ": %s\n", cp);
137     }
138     }
139     else if (!strcasecmp (buf, "spell_encumbrance"))
140     {
141     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
142     {
143     settings.spell_encumbrance = TRUE;
144     }
145     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
146     {
147     settings.spell_encumbrance = FALSE;
148     }
149     else
150     {
151     LOG (llevError, "load_settings: Unknown value for " "spell_encumbrance: %s\n", cp);
152     }
153     }
154     else if (!strcasecmp (buf, "spell_failure_effects"))
155     {
156     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
157     {
158     settings.spell_failure_effects = TRUE;
159     }
160     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
161     {
162     settings.spell_failure_effects = FALSE;
163     }
164     else
165     {
166     LOG (llevError, "load_settings: Unknown value for " "spell_failure_effects: %s\n", cp);
167     }
168     }
169     else if (!strcasecmp (buf, "spellpoint_level_depend"))
170     {
171     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
172     {
173     settings.spellpoint_level_depend = TRUE;
174     }
175     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
176     {
177     settings.spellpoint_level_depend = FALSE;
178     }
179     else
180     {
181     LOG (llevError, "load_settings: Unknown value for " "spellpoint_level_depend: %s\n", cp);
182     }
183     }
184     else if (!strcasecmp (buf, "stat_loss_on_death"))
185     {
186     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
187     {
188     settings.stat_loss_on_death = TRUE;
189     }
190     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
191     {
192     settings.stat_loss_on_death = FALSE;
193     }
194     else
195     {
196     LOG (llevError, "load_settings: Unknown value for " "stat_loss_on_death: %s\n", cp);
197     }
198     }
199     else if (!strcasecmp (buf, "use_permanent_experience"))
200     {
201     LOG (llevError, "use_permanent_experience is deprecated, use" "permenent_experience_percentage instead\n");
202     }
203     else if (!strcasecmp (buf, "permanent_experience_percentage"))
204     {
205     int val = atoi (cp);
206    
207     if (val < 0 || val > 100)
208     LOG (llevError, "load_settings: permenent_experience_percentage" "must be between 0 and 100, %d is invalid\n", val);
209     else
210     settings.permanent_exp_ratio = val;
211     }
212     else if (!strcasecmp (buf, "death_penalty_percentage"))
213     {
214     int val = atoi (cp);
215    
216     if (val < 0 || val > 100)
217     LOG (llevError, "load_settings: death_penalty_percentage" "must be between 0 and 100, %d is invalid\n", val);
218     else
219     settings.death_penalty_ratio = val;
220     }
221     else if (!strcasecmp (buf, "death_penalty_levels"))
222     {
223     int val = atoi (cp);
224    
225     if (val < 0 || val > 255)
226     LOG (llevError, "load_settings: death_penalty_levels" "can not be negative, %d is invalid\n", val);
227     else
228     settings.death_penalty_level = val;
229     }
230     else if (!strcasecmp (buf, "balanced_stat_loss"))
231     {
232     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
233     {
234     settings.balanced_stat_loss = TRUE;
235     }
236     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
237     {
238     settings.balanced_stat_loss = FALSE;
239     }
240     else
241     {
242     LOG (llevError, "load_settings: Unknown value for " "balanced_stat_loss: %s\n", cp);
243     }
244     }
245     else if (!strcasecmp (buf, "simple_exp"))
246     {
247     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
248     {
249     settings.simple_exp = TRUE;
250     }
251     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
252     {
253     settings.simple_exp = FALSE;
254     }
255     else
256     {
257     LOG (llevError, "load_settings: Unknown value for simple_exp: %s\n", cp);
258     }
259     }
260     else if (!strcasecmp (buf, "item_power_factor"))
261     {
262     float tmp = atof (cp);
263    
264     if (tmp < 0)
265     LOG (llevError, "load_settings: item_power_factor must be a positive number (%f < 0)\n", tmp);
266     else
267     settings.item_power_factor = tmp;
268     }
269     else if (!strcasecmp (buf, "pk_luck_penalty"))
270     {
271     sint16 val = atoi (cp);
272    
273     if (val < -100 || val > 100)
274     LOG (llevError, "load_settings: pk_luck_penalty must be between -100 and 100" ", %d is invalid\n", val);
275     else
276     settings.pk_luck_penalty = val;
277     }
278     else if (!strcasecmp (buf, "set_friendly_fire"))
279     {
280     int val = atoi (cp);
281 elmex 1.1
282 root 1.9 if (val < 0 || val > 100)
283     LOG (llevError, "load_settings: set_friendly_fire must be between 0 an 100" ", %d is invalid\n", val);
284     else
285     settings.set_friendly_fire = val;
286     }
287     else if (!strcasecmp (buf, "armor_max_enchant"))
288     {
289     int max_e = atoi (cp);
290    
291     if (max_e <= 0)
292     LOG (llevError, "load_settings: armor_max_enchant is %d\n", max_e);
293     else
294 elmex 1.1 settings.armor_max_enchant = max_e;
295 root 1.9 }
296     else if (!strcasecmp (buf, "armor_weight_reduction"))
297     {
298     int wr = atoi (cp);
299    
300     if (wr < 0)
301     LOG (llevError, "load_settings: armor_weight_reduction is %d\n", wr);
302     else
303 elmex 1.1 settings.armor_weight_reduction = wr;
304     }
305 root 1.9 else if (!strcasecmp (buf, "armor_weight_linear"))
306     {
307     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
308     {
309     settings.armor_weight_linear = TRUE;
310     }
311     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
312     {
313     settings.armor_weight_linear = FALSE;
314     }
315     else
316     {
317     LOG (llevError, "load_settings: unknown value for armor_weight_linear: %s\n", cp);
318     }
319    
320     }
321     else if (!strcasecmp (buf, "armor_speed_improvement"))
322     {
323     int wr = atoi (cp);
324 elmex 1.1
325 root 1.9 if (wr < 0)
326     LOG (llevError, "load_settings: armor_speed_improvement is %d\n", wr);
327     else
328 elmex 1.1 settings.armor_speed_improvement = wr;
329     }
330 root 1.9 else if (!strcasecmp (buf, "armor_speed_linear"))
331     {
332     if (!strcasecmp (cp, "on") || !strcasecmp (cp, "true"))
333     {
334     settings.armor_speed_linear = TRUE;
335     }
336     else if (!strcasecmp (cp, "off") || !strcasecmp (cp, "false"))
337     {
338     settings.armor_speed_linear = FALSE;
339     }
340     else
341     {
342     LOG (llevError, "load_settings: unknown value for armor_speed_linear: %s\n", cp);
343     }
344    
345     }
346     else
347 root 1.50 LOG (llevError, "Unknown value in settings file: %s\n", buf);
348 elmex 1.1 }
349 root 1.20
350 root 1.9 close_and_delete (fp, comp);
351 elmex 1.1 }
352    
353     /*
354     * init() is called only once, when starting the program.
355     */
356 root 1.9 void
357     init (int argc, char **argv)
358     {
359 root 1.37 init_done = 0; /* Must be done before init_signal() */
360 root 1.36
361 root 1.42 init_environ ();
362 root 1.14 cfperl_init ();
363 root 1.9 init_done = 1;
364 elmex 1.1 }
365    
366 root 1.9 void
367 root 1.76 usage ()
368 root 1.9 {
369 root 1.62 fprintf (stderr, "Usage: deliantra-server [-h] [-<flags>]...\n");
370 elmex 1.1 }
371    
372 root 1.9 void
373 root 1.76 help ()
374 root 1.9 {
375    
376 elmex 1.1 /* The information in usage is redundant with what is given below, so why call it? */
377 root 1.9
378 elmex 1.1 /* usage();*/
379 root 1.9 printf ("Flags:\n");
380     printf (" -csport <port> Specifies the port to use for the new client/server code.\n");
381     printf (" -d Turns on some debugging.\n");
382     printf (" +d Turns off debugging (useful if server compiled with debugging\n");
383     printf (" as default).\n");
384     printf (" -detach The server will go in the background, closing all\n");
385     printf (" connections to the tty.\n");
386     printf (" -h Display this information.\n");
387     printf (" -log <file> Specifies which file to send output to.\n");
388     printf (" Only has meaning if -detach is specified.\n");
389     printf (" -mon Turns on monster debugging.\n");
390     printf (" -o Prints out info on what was defined at compile time.\n");
391     printf (" -s Display the high-score list.\n");
392     printf (" -score <name or class> Displays all high scores with matching name/class.\n");
393     printf (" -v Print version and contributors.\n");
394     printf (" -data Sets the lib dir (archetypes, treasures, etc.)\n");
395     printf (" -local Read/write local data (hiscore, unique items, etc.)\n");
396     printf (" -maps Sets the directory for maps.\n");
397     printf (" -arch Sets the archetype file to use.\n");
398     printf (" -regions Sets the regions file to use.\n");
399     printf (" -playerdir Sets the directory for the player files.\n");
400     printf (" -templatedir Sets the directory for template generate maps.\n");
401     printf (" -treasures Sets the treasures file to use.\n");
402     printf (" -uniquedir Sets the unique items/maps directory.\n");
403     printf (" -tmpdir Sets the directory for temporary files (mostly maps.)\n");
404     printf (" -m Lists out suggested experience for all monsters.\n");
405     printf (" -m2 Dumps out abilities.\n");
406     printf (" -m3 Dumps out artifact information.\n");
407     printf (" -m4 Dumps out spell information.\n");
408     printf (" -m5 Dumps out skill information.\n");
409     printf (" -m6 Dumps out race information.\n");
410     printf (" -m7 Dumps out alchemy information.\n");
411     printf (" -m8 Dumps out gods information.\n");
412     printf (" -m9 Dumps out more alchemy information (formula checking).\n");
413     printf (" -mt <name> Dumps out list of treasures for a monster.\n");
414     exit (0);
415     }
416    
417 elmex 1.1 /* Signal handlers: */
418    
419 root 1.48 static void
420 root 1.33 rec_sigabrt (int i)
421     {
422     signal (SIGABRT, SIG_DFL);
423    
424     LOG (llevError, "SIGABRT received.\n");
425     cleanup ("SIGABRT received", 1);
426     }
427    
428 root 1.48 static void
429 root 1.9 rec_sigsegv (int i)
430     {
431 root 1.33 signal (SIGSEGV, SIG_DFL);
432    
433 root 1.21 LOG (llevError, "SIGSEGV received.\n");
434 root 1.29 cleanup ("SIGSEGV received", 1);
435 elmex 1.1 }
436    
437 root 1.48 static void
438 root 1.9 rec_sigquit (int i)
439     {
440 root 1.33 signal (SIGQUIT, SIG_IGN);
441    
442 root 1.21 LOG (llevInfo, "SIGQUIT received\n");
443 root 1.29 cleanup ("SIGQUIT received", 1);
444 elmex 1.1 }
445    
446 root 1.48 static void
447 root 1.9 rec_sigbus (int i)
448     {
449 root 1.33 signal (SIGBUS, SIG_DFL);
450    
451 root 1.21 LOG (llevError, "SIGBUS received\n");
452 root 1.29 cleanup ("SIGBUS received", 1);
453 elmex 1.1 }
454    
455 root 1.9 void
456 root 1.48 reset_signals ()
457     {
458     signal (SIGABRT, SIG_DFL);
459     signal (SIGQUIT, SIG_DFL);
460     signal (SIGSEGV, SIG_DFL);
461     signal (SIGBUS , SIG_DFL);
462     signal (SIGINT , SIG_DFL);
463     signal (SIGTERM, SIG_DFL);
464     }
465    
466     void
467 root 1.76 init_signals ()
468 root 1.9 {
469 root 1.37 // large stack, but it's important data we want to save, and it is not usually
470     // being physically allocated anyways
471     const size_t stacksize = 8 * 1024 * 1024 + SIGSTKSZ;
472    
473     stack_t ss;
474     ss.ss_sp = malloc (stacksize);
475     ss.ss_flags = 0;
476     ss.ss_size = stacksize;
477     sigaltstack (&ss, 0);
478    
479     struct sigaction sa;
480    
481     sigfillset (&sa.sa_mask);
482 root 1.49 sa.sa_flags = SA_RESTART;
483 root 1.37
484     sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, 0);
485     sa.sa_handler = rec_sigabrt; sigaction (SIGABRT, &sa, 0);
486     sa.sa_handler = rec_sigquit; sigaction (SIGQUIT, &sa, 0);
487 root 1.49 sa.sa_handler = rec_sigbus; sigaction (SIGBUS, &sa, 0);
488    
489     sa.sa_flags |= SA_ONSTACK;
490 root 1.37 sa.sa_handler = rec_sigsegv; sigaction (SIGSEGV, &sa, 0);
491 elmex 1.1 }
492    
493 root 1.74 static racelink *
494     get_racelist ()
495     {
496     racelink *list = new racelink;
497    
498     list->name = 0;
499     list->nrof = 0;
500     list->next = 0;
501     list->member = get_objectlink ();
502    
503     return list;
504     }
505    
506     racelink *
507     find_racelink (const char *name)
508     {
509     if (name)
510     for (racelink *link = first_race; link; link = link->next)
511     if (!link->name || !strcmp (name, link->name))
512     return link;
513    
514     return 0;
515     }
516    
517     static void
518     add_to_racelist (const char *race_name, object *op)
519     {
520     racelink *race;
521    
522     if (!op || !race_name)
523     return;
524    
525     race = find_racelink (race_name);
526    
527     if (!race)
528     { /* add in a new race list */
529     race = get_racelist ();
530     race->next = first_race;
531     first_race = race;
532     race->name = race_name;
533     }
534    
535     if (race->member->ob)
536     {
537     objectlink *tmp = get_objectlink ();
538    
539     tmp->next = race->member;
540     race->member = tmp;
541     }
542    
543     race->nrof++;
544     race->member->ob = op;
545     }
546    
547 elmex 1.1 /* init_races() - reads the races file in the lib/ directory, then
548     * overwrites old 'race' entries. This routine allow us to quickly
549     * re-configure the 'alignment' of monsters, objects. Useful for
550     * putting together lists of creatures, etc that belong to gods.
551     */
552 root 1.74 static void
553 root 1.76 init_races ()
554 elmex 1.8 {
555 elmex 1.1 FILE *file;
556     char race[MAX_BUF], fname[MAX_BUF], buf[MAX_BUF], *cp, variable[MAX_BUF];
557 elmex 1.8 archetype *mon = NULL;
558     static int init_done = 0;
559 elmex 1.1
560 elmex 1.8 if (init_done)
561 elmex 1.1 return;
562 elmex 1.8 init_done = 1;
563 root 1.10 first_race = 0;
564 elmex 1.1
565 elmex 1.8 sprintf (fname, "%s/races", settings.datadir);
566 pippijn 1.25 LOG (llevDebug, "Reading races from %s...\n", fname);
567 elmex 1.8 if (!(file = fopen (fname, "r")))
568     {
569 root 1.9 LOG (llevError, "Cannot open races file %s: %s\n", fname, strerror (errno));
570 elmex 1.8 return;
571 elmex 1.1 }
572 elmex 1.8
573     while (fgets (buf, MAX_BUF, file) != NULL)
574     {
575     int set_race = 1, set_list = 1;
576 root 1.9
577 elmex 1.8 if (*buf == '#')
578     continue;
579 root 1.10
580 elmex 1.8 if ((cp = strchr (buf, '\n')) != NULL)
581     *cp = '\0';
582 root 1.10
583 elmex 1.8 cp = buf;
584     while (*cp == ' ' || *cp == '!' || *cp == '@')
585     {
586 root 1.65 if (*cp == '!') set_race = 0;
587     if (*cp == '@') set_list = 0;
588    
589 elmex 1.8 cp++;
590     }
591 root 1.10
592 elmex 1.8 if (sscanf (cp, "RACE %s", variable))
593 root 1.40 /* set new race value */
594     strcpy (race, variable);
595 elmex 1.8 else
596     {
597     char *cp1;
598 root 1.9
599 elmex 1.8 /* Take out beginning spaces */
600     for (cp1 = cp; *cp1 == ' '; cp1++)
601     ;
602     /* Remove newline and trailing spaces */
603     for (cp1 = cp + strlen (cp) - 1; *cp1 == '\n' || *cp1 == ' '; cp1--)
604     {
605     *cp1 = '\0';
606     if (cp == cp1)
607     break;
608     }
609    
610     if (cp[strlen (cp) - 1] == '\n')
611     cp[strlen (cp) - 1] = '\0';
612 root 1.10
613 elmex 1.8 /* set creature race to race value */
614 root 1.12 if ((mon = archetype::find (cp)) == NULL)
615 pippijn 1.25 LOG (llevError, "Creature %s in race file lacks archetype\n", cp);
616 elmex 1.8 else
617     {
618 root 1.70 if (set_race && (!mon->race || strcmp (&mon->race, race)))
619 elmex 1.8 {
620 root 1.54 if (mon->race)
621     LOG (llevDebug, "Resetting race to %s from %s for archetype %s\n", race, &mon->race, &mon->archname);
622 root 1.10
623 root 1.54 mon->race = race;
624 elmex 1.1 }
625 root 1.10
626 elmex 1.8 /* if the arch is a monster, add it to the race list */
627 root 1.54 if (set_list && QUERY_FLAG (mon, FLAG_MONSTER))
628     add_to_racelist (race, mon);
629 elmex 1.8 }
630 elmex 1.1 }
631     }
632 root 1.10
633 elmex 1.8 fclose (file);
634     LOG (llevDebug, "done.\n");
635 elmex 1.1 }
636    
637 root 1.9 void
638 root 1.76 init_beforeplay ()
639 root 1.9 {
640 root 1.74 init_artifacts (); /* If not called before, reads all artifacts from file */
641     init_races (); /* overwrite race designations using entries in lib/races file */
642     init_gods (); /* init linked list of gods from archs */
643     init_readable (); /* inits useful arrays for readable texts */
644     init_formulae (); /* If not called before, reads formulae from file */
645 elmex 1.1 }
646