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, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.79: +57 -85 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen
7 *
8 * 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 *
13 * 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 *
18 * 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 *
22 * The authors can be reached via e-mail to <support@deliantra.net>
23 */
24
25 #include <global.h>
26 #include <material.h>
27 #include <sproto.h>
28
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 void
34 load_settings ()
35 {
36 char fname [1024];
37 sprintf (fname, "%s/settings", settings.confdir);
38 object_thawer thawer (fname);
39
40 if (!thawer)
41 {
42 LOG (llevError, "Error: No settings file found\n");
43 exit (1);
44 }
45
46 while (thawer.kw)
47 {
48 const char *buf = thawer.kw_str;
49 const char *cp = thawer.value_nn;
50
51 if (!strcmp (buf, "not_permadeth"))
52 {
53 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
54 {
55 settings.not_permadeth = TRUE;
56 }
57 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
58 {
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 else if (!strcmp (buf, "resurrection"))
67 {
68 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
69 {
70 settings.resurrection = TRUE;
71 }
72 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
73 {
74 settings.resurrection = FALSE;
75 }
76 else
77 {
78 LOG (llevError, "load_settings: Unknown value for resurrection" ": %s\n", cp);
79 }
80 }
81 else if (!strcmp (buf, "set_title"))
82 {
83 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
84 {
85 settings.set_title = TRUE;
86 }
87 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
88 {
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 else if (!strcmp (buf, "search_items"))
97 {
98 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
99 {
100 settings.search_items = TRUE;
101 }
102 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
103 {
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 else if (!strcmp (buf, "spell_encumbrance"))
112 {
113 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
114 {
115 settings.spell_encumbrance = TRUE;
116 }
117 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
118 {
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 else if (!strcmp (buf, "spell_failure_effects"))
127 {
128 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
129 {
130 settings.spell_failure_effects = TRUE;
131 }
132 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
133 {
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 else if (!strcmp (buf, "spellpoint_level_depend"))
142 {
143 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
144 {
145 settings.spellpoint_level_depend = TRUE;
146 }
147 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
148 {
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 else if (!strcmp (buf, "stat_loss_on_death"))
157 {
158 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
159 {
160 settings.stat_loss_on_death = TRUE;
161 }
162 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
163 {
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 else if (!strcmp (buf, "use_permanent_experience"))
172 {
173 LOG (llevError, "use_permanent_experience is deprecated, use" "permenent_experience_percentage instead\n");
174 }
175 else if (!strcmp (buf, "permanent_experience_percentage"))
176 {
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 else if (!strcmp (buf, "death_penalty_percentage"))
185 {
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 else if (!strcmp (buf, "death_penalty_levels"))
194 {
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 else if (!strcmp (buf, "balanced_stat_loss"))
203 {
204 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
205 {
206 settings.balanced_stat_loss = TRUE;
207 }
208 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
209 {
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 else if (!strcmp (buf, "simple_exp"))
218 {
219 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
220 {
221 settings.simple_exp = TRUE;
222 }
223 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
224 {
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 else if (!strcmp (buf, "item_power_factor"))
233 {
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 else if (!strcmp (buf, "pk_luck_penalty"))
242 {
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 else if (!strcmp (buf, "set_friendly_fire"))
251 {
252 int val = atoi (cp);
253
254 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 else if (!strcmp (buf, "armor_max_enchant"))
260 {
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 settings.armor_max_enchant = max_e;
267 }
268 else if (!strcmp (buf, "armor_weight_reduction"))
269 {
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 settings.armor_weight_reduction = wr;
276 }
277 else if (!strcmp (buf, "armor_weight_linear"))
278 {
279 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
280 {
281 settings.armor_weight_linear = TRUE;
282 }
283 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
284 {
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 else if (!strcmp (buf, "armor_speed_improvement"))
294 {
295 int wr = atoi (cp);
296
297 if (wr < 0)
298 LOG (llevError, "load_settings: armor_speed_improvement is %d\n", wr);
299 else
300 settings.armor_speed_improvement = wr;
301 }
302 else if (!strcmp (buf, "armor_speed_linear"))
303 {
304 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
305 {
306 settings.armor_speed_linear = TRUE;
307 }
308 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
309 {
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 thawer.parse_error ("settings file");
320
321 thawer.next ();
322 }
323 }
324
325 /*
326 * init() is called only once, when starting the program.
327 */
328 void
329 init (int argc, char **argv)
330 {
331 init_done = 0; /* Must be done before init_signal() */
332
333 init_environ ();
334 cfperl_init ();
335 init_done = 1;
336 }
337
338 void
339 usage ()
340 {
341 fprintf (stderr, "Usage: deliantra-server [-h] [-<flags>]...\n");
342 }
343
344 void
345 help ()
346 {
347
348 /* The information in usage is redundant with what is given below, so why call it? */
349
350 /* usage();*/
351 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 /* Signal handlers: */
390
391 static void
392 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 static void
401 rec_sigsegv (int i)
402 {
403 signal (SIGSEGV, SIG_DFL);
404
405 LOG (llevError, "SIGSEGV received.\n");
406 cleanup ("SIGSEGV received", 1);
407 }
408
409 static void
410 rec_sigquit (int i)
411 {
412 signal (SIGQUIT, SIG_IGN);
413
414 LOG (llevInfo, "SIGQUIT received\n");
415 cleanup ("SIGQUIT received", 1);
416 }
417
418 static void
419 rec_sigbus (int i)
420 {
421 signal (SIGBUS, SIG_DFL);
422
423 LOG (llevError, "SIGBUS received\n");
424 cleanup ("SIGBUS received", 1);
425 }
426
427 void
428 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 init_signals ()
440 {
441 // 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 sa.sa_flags = SA_RESTART;
455
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 sa.sa_handler = rec_sigbus; sigaction (SIGBUS, &sa, 0);
460
461 sa.sa_flags |= SA_ONSTACK;
462 sa.sa_handler = rec_sigsegv; sigaction (SIGSEGV, &sa, 0);
463 }
464
465 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 /* 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 static void
525 init_races ()
526 {
527 FILE *file;
528 char race[MAX_BUF], fname[MAX_BUF], buf[MAX_BUF], *cp, variable[MAX_BUF];
529 archetype *mon = NULL;
530 static int init_done = 0;
531
532 if (init_done)
533 return;
534 init_done = 1;
535 first_race = 0;
536
537 sprintf (fname, "%s/races", settings.datadir);
538 LOG (llevDebug, "Reading races from %s...\n", fname);
539 if (!(file = fopen (fname, "r")))
540 {
541 LOG (llevError, "Cannot open races file %s: %s\n", fname, strerror (errno));
542 return;
543 }
544
545 while (fgets (buf, MAX_BUF, file) != NULL)
546 {
547 int set_race = 1, set_list = 1;
548
549 if (*buf == '#')
550 continue;
551
552 if ((cp = strchr (buf, '\n')) != NULL)
553 *cp = '\0';
554
555 cp = buf;
556 while (*cp == ' ' || *cp == '!' || *cp == '@')
557 {
558 if (*cp == '!') set_race = 0;
559 if (*cp == '@') set_list = 0;
560
561 cp++;
562 }
563
564 if (sscanf (cp, "RACE %s", variable))
565 /* set new race value */
566 strcpy (race, variable);
567 else
568 {
569 char *cp1;
570
571 /* 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
585 /* set creature race to race value */
586 if ((mon = archetype::find (cp)) == NULL)
587 LOG (llevError, "Creature %s in race file lacks archetype\n", cp);
588 else
589 {
590 if (set_race && (!mon->race || strcmp (&mon->race, race)))
591 {
592 if (mon->race)
593 LOG (llevDebug, "Resetting race to %s from %s for archetype %s\n", race, &mon->race, &mon->archname);
594
595 mon->race = race;
596 }
597
598 /* if the arch is a monster, add it to the race list */
599 if (set_list && mon->flag [FLAG_MONSTER])
600 add_to_racelist (race, mon);
601 }
602 }
603 }
604
605 fclose (file);
606 LOG (llevDebug, "done.\n");
607 }
608
609 void
610 init_beforeplay ()
611 {
612 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 }
618