ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/init.C
Revision: 1.80
Committed: Thu Apr 15 22:03:23 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.79: +57 -85 lines
Log Message:
*** empty log message ***

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