Crossfire Server, Trunk  R20739
init.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #define EXTERN
20 #define INIT_C
21 
22 #include "global.h"
23 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "object.h"
28 #include "output_file.h"
29 
30 static void init_environ(void);
31 static void init_defaults(void);
32 static void init_dynamic(void);
33 static void init_clocks(void);
34 static void init_attackmess(void);
35 
36 /*
37  * You unforunately need to looking in include/global.h to see what these
38  * correspond to.
39  */
40 struct Settings settings = {
41  NULL, /* Logfile */
42  CSPORT, /* Client/server port */
43 
44  llevInfo, /* Debug level */
45  0, NULL, /* dumpvalues, dumparg */
46  CONFDIR,
47  DATADIR,
48  LOCALDIR,
51  TMPDIR,
59  SIMPLE_EXP,
61  SET_TITLE,
67  REAL_WIZ,
72  "", /* Who format specifier */
73  "", /* who wiz format specifier */
74  MOTD,
75  "rules",
76  "news",
77  "", /* DM_MAIL */
78  0, /* This and the next 3 values are metaserver values */
79  "",
80  "",
81  0,
82  "",
83  0, 0, 0, 0, 0, 0, 0, /* worldmap settings*/
84  NULL, EMERGENCY_X, EMERGENCY_Y,
85  0,
86  1.0,
87  /* Armor enchantment stuff */
93  1, /* no_player_stealing */
94  0, /* create_home_portals */
95  1, /* personalized_blessings */
96  5000000, /* pk_max_experience */
97  10, /* pk_max_experience_percent */
98  0, /* allow_denied_spells_writing */
99  0, /* allow_broken_converters */
100  0, /* log_timestamp */
101  NULL, /* log_timestamp_format */
102  3, /* starting_stat_min */
103  18, /* starting_stat_max */
104  85, /* starting_stat_points */
105  115, /* roll_stat_points */
106  0, /* max_stat - will be loaded from stats file */
107  1, /* special_break_map, 1 for historical reasons */
108  NULL, /* disabled_plugins */
109  0, /* ignore_plugin_compatibility */
110  FALSE, /* account_block_create */
111  NULL, /* Trusted host for account creation. */
112  0, /* Unless explicitly set, use legacy crypt mode */
113 };
114 
116 
122 const char *const spellpathnames[NRSPELLPATHS] = {
123  "Protection",
124  "Fire",
125  "Frost",
126  "Electricity",
127  "Missiles",
128  "Self",
129  "Summoning",
130  "Abjuration",
131  "Restoration",
132  "Detonation",
133  "Mind",
134  "Creation",
135  "Teleportation",
136  "Information",
137  "Transmutation",
138  "Transferrence",
139  "Turning",
140  "Wounding",
141  "Death",
142  "Light"
143 };
144 
145 
157 static void init_emergency_mappath(void) {
158  char filename[MAX_BUF], tmpbuf[MAX_BUF];
159  FILE *fp;
160  int online = 0;
161 
163 
164  /* If this file doesn't exist, not a big deal */
165  snprintf(filename, sizeof(filename), "%s/%s/.emergency", settings.datadir, settings.mapdir);
166  fp = fopen(filename, "r");
167  if (fp != NULL) {
168  while (fgets(tmpbuf, MAX_BUF-1, fp)) {
169  if (tmpbuf[0] == '#')
170  continue; /* ignore comments */
171 
172  if (online == 0) {
173  tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */
174  free(settings.emergency_mapname);
175  settings.emergency_mapname = strdup_local(tmpbuf);
176  } else if (online == 1) {
177  settings.emergency_x = atoi(tmpbuf);
178  } else if (online == 2) {
179  settings.emergency_y = atoi(tmpbuf);
180  }
181  online++;
182  if (online > 2)
183  break;
184  }
185  fclose(fp);
186  if (online <= 2)
187  LOG(llevError, "Online read partial data from %s\n", filename);
188  LOG(llevDebug, "emergency map set to %s (%d, %d)\n",
189  settings.emergency_mapname,
190  settings.emergency_x, settings.emergency_y);
191  }
192 }
193 
194 
203 void init_library(void) {
204  init_environ();
205  init_globals();
206  init_stats(FALSE); /* Needs to be fairly early, since the loader will check
207  * against the settings.max_stat value
208  */
209  init_hash_table();
210  i18n_init();
211  init_objects();
212  init_block();
213  read_bmap_names();
214  read_smooth();
215  init_anim(); /* Must be after we read in the bitmaps */
216  init_archetypes(); /* Reads all archetypes from file */
217  init_attackmess();
218  init_clocks();
220  init_experience();
221 
222  /* init_dynamic() loads a map, so needs a region */
223  if (init_regions() != 0) {
224  LOG(llevError, "Please check that your maps are correctly installed.\n");
225  exit(EXIT_FAILURE);
226  }
227 
228  init_dynamic();
229 }
230 
236 static void init_environ(void) {
237  char *cp;
238 
239  cp = getenv("CROSSFIRE_LIBDIR");
240  if (cp)
241  settings.datadir = cp;
242  cp = getenv("CROSSFIRE_LOCALDIR");
243  if (cp)
244  settings.localdir = cp;
245  cp = getenv("CROSSFIRE_PLAYERDIR");
246  if (cp)
247  settings.playerdir = cp;
248  cp = getenv("CROSSFIRE_MAPDIR");
249  if (cp)
250  settings.mapdir = cp;
251  cp = getenv("CROSSFIRE_ARCHETYPES");
252  if (cp)
253  settings.archetypes = cp;
254  cp = getenv("CROSSFIRE_TREASURES");
255  if (cp)
256  settings.treasures = cp;
257  cp = getenv("CROSSFIRE_UNIQUEDIR");
258  if (cp)
259  settings.uniquedir = cp;
260  cp = getenv("CROSSFIRE_TEMPLATEDIR");
261  if (cp)
262  settings.templatedir = cp;
263  cp = getenv("CROSSFIRE_TMPDIR");
264  if (cp)
265  settings.tmpdir = cp;
266 }
267 
274 void init_globals(void) {
275  memset(&statistics, 0, sizeof(struct Statistics));
276 
277  /* Log to stderr by default. */
278  logfile = stderr;
279 
280  /* Try to open the log file specified on the command-line. */
281  if (settings.logfilename != NULL) {
282  logfile = fopen(settings.logfilename, "a");
283 
284  /* If writable, set buffer mode to per-line. */
285  if (logfile != NULL) {
286  setvbuf(logfile, NULL, _IOLBF, 0);
287  } else {
288  logfile = stderr;
289 
290  LOG(llevError, "Could not open '%s' for logging.\n",
291  settings.logfilename);
292  }
293  }
294 
295  exiting = 0;
296  first_player = NULL;
297  first_friendly_object = NULL;
298  first_map = NULL;
299  first_treasurelist = NULL;
300  first_artifactlist = NULL;
301  first_archetype = NULL;
302  *first_map_ext_path = 0;
303  nroftreasures = 0;
304  nrofartifacts = 0;
305  nrofallowedstr = 0;
306  ring_arch = NULL;
307  amulet_arch = NULL;
308  staff_arch = NULL;
309  undead_name = add_string("undead");
311  num_animations = 0;
312  animations = NULL;
314  init_defaults();
315 }
316 
327 void free_globals(void) {
328  int msg, attack;
329  objectlink *friend;
330  region *reg;
331 
333  for (msg = 0; msg < NROFATTACKMESS; msg++)
334  for (attack = 0; attack < MAXATTACKMESS; attack++) {
335  free(attack_mess[msg][attack].buf1);
336  free(attack_mess[msg][attack].buf2);
337  free(attack_mess[msg][attack].buf3);
338  }
339 
340  free(settings.emergency_mapname);
341 
342  while (first_friendly_object) {
343  friend = first_friendly_object->next;
345  first_friendly_object = friend;
346  }
347 
348  free_experience();
349 
350  while (first_region) {
351  reg = first_region->next;
358  first_region = reg;
359  }
360 }
361 
367 void init_objects(void) {
368 #ifndef MEMORY_DEBUG
369  int i;
370 #endif
371  /* Initialize all objects: */
372  objects = NULL;
373  active_objects = NULL;
374 
375 #ifdef MEMORY_DEBUG
376  free_objects = NULL;
377 #else
379  objarray[0].prev = NULL,
380  objarray[0].next = &objarray[1],
383  for (i = 1; i < STARTMAX-1; i++) {
384  objarray[i].next = &objarray[i+1];
385  objarray[i].prev = &objarray[i-1];
388  }
389  objarray[STARTMAX-1].next = NULL;
390  objarray[STARTMAX-1].prev = &objarray[STARTMAX-2];
391  SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED);
392  SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED);
393 #endif
394 }
395 
400 static void init_defaults(void) {
401  nroferrors = 0;
402 }
403 
412 static void init_dynamic(void) {
414  while (at) {
415  if (at->clone.type == MAP && at->clone.subtype == MAP_TYPE_LEGACY) {
416  if (at->clone.race) {
418  sizeof(first_map_ext_path));
419  }
420  if (EXIT_PATH(&at->clone)) {
421  mapstruct *first;
422 
423  snprintf(first_map_path, sizeof(first_map_path), "%s", EXIT_PATH(&at->clone));
424  first = ready_map_name(first_map_path, 0);
425  if (!first) {
426  LOG(llevError, "Initial map %s can't be found! Please ensure maps are correctly installed.\n", first_map_path);
427  LOG(llevError, "Unable to continue without initial map.\n");
428  abort();
429  }
430  delete_map(first);
431  return;
432  }
433  }
434  at = at->next;
435  }
436  LOG(llevError, "You need a archetype called 'map' and it have to contain start map\n");
437  exit(-1);
438 }
439 
441 unsigned long todtick;
442 
447 void write_todclock(void) {
448  char filename[MAX_BUF];
449  FILE *fp;
450  OutputFile of;
451 
452  snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir);
453  fp = of_open(&of, filename);
454  if (fp == NULL)
455  return;
456  fprintf(fp, "%lu", todtick);
457  of_close(&of);
458 }
459 
464 static void init_clocks(void) {
465  char filename[MAX_BUF];
466  FILE *fp;
467  static int has_been_done = 0;
468 
469  if (has_been_done)
470  return;
471  else
472  has_been_done = 1;
473 
474  snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir);
475  fp = fopen(filename, "r");
476  if (fp == NULL) {
477  LOG(llevError, "Can't open %s.\n", filename);
478  todtick = 0;
479  write_todclock();
480  return;
481  }
482  /* Read TOD and default to 0 on failure. */
483  if (fscanf(fp, "%lu", &todtick) == 1) {
484  LOG(llevDebug, "clockdata: todtick is %lu\n", todtick);
485  fclose(fp);
486  } else {
487  LOG(llevError, "Couldn't parse todtick, using default value 0\n");
488  todtick = 0;
489  fclose(fp);
490  write_todclock();
491  }
492 }
493 
500 static void init_attackmess(void) {
501  char buf[MAX_BUF];
502  char filename[MAX_BUF];
503  char *cp, *p;
504  FILE *fp;
505  static int has_been_done = 0;
506  int mess = -1, level;
507  int mode = 0, total = 0;
508 
509  if (has_been_done)
510  return;
511  else
512  has_been_done = 1;
513 
514  snprintf(filename, sizeof(filename), "%s/attackmess", settings.datadir);
515  fp = fopen(filename, "r");
516  if (fp == NULL) {
517  LOG(llevError, "Can't open %s.\n", filename);
518  return;
519  }
520 
521  level = 0;
522  while (fgets(buf, MAX_BUF, fp) != NULL) {
523  if (*buf == '#')
524  continue;
525  // Find the end of the line and strip the newline
526  cp = strchr(buf, '\n');
527  if (cp != NULL)
528  *cp = '\0';
529  /*
530  * Skip blanks -- strspn is slightly faster than a loop w/ optimization on
531  * Also, note we go from the beginning of the line again, since cp was at the end.
532  * While here, also skip tabs for more complete whitespace handling.
533  *
534  * SilverNexus 2018-01-21
535  */
536  cp = buf + strspn(buf, " \t");
537 
538  if (strncmp(cp, "TYPE:", 5) == 0) {
539  p = strtok(buf, ":");
540  p = strtok(NULL, ":");
541  if (mode == 1) {
542  attack_mess[mess][level].level = -1;
543  attack_mess[mess][level].buf1 = NULL;
544  attack_mess[mess][level].buf2 = NULL;
545  attack_mess[mess][level].buf3 = NULL;
546  }
547  level = 0;
548  mess = atoi(p);
549  mode = 1;
550  continue;
551  }
552  if (mode == 1) {
553  p = strtok(buf, "=");
554  attack_mess[mess][level].level = atoi(buf);
555  p = strtok(NULL, "=");
556  if (p != NULL)
557  attack_mess[mess][level].buf1 = strdup_local(p);
558  else
559  attack_mess[mess][level].buf1 = strdup_local("");
560  mode = 2;
561  continue;
562  } else if (mode == 2) {
563  p = strtok(buf, "=");
564  attack_mess[mess][level].level = atoi(buf);
565  p = strtok(NULL, "=");
566  if (p != NULL)
567  attack_mess[mess][level].buf2 = strdup_local(p);
568  else
569  attack_mess[mess][level].buf2 = strdup_local("");
570  mode = 3;
571  continue;
572  } else if (mode == 3) {
573  p = strtok(buf, "=");
574  attack_mess[mess][level].level = atoi(buf);
575  p = strtok(NULL, "=");
576  if (p != NULL)
577  attack_mess[mess][level].buf3 = strdup_local(p);
578  else
579  attack_mess[mess][level].buf3 = strdup_local("");
580  mode = 1;
581  level++;
582  total++;
583  continue;
584  }
585  }
586  LOG(llevDebug, "attackmsg: %d messages in %d categories\n", total, mess+1);
587  fclose(fp);
588 }
EXTERN FILE * logfile
Definition: global.h:142
#define RESURRECTION
Definition: config.h:161
#define STAT_LOSS_ON_DEATH
Definition: config.h:164
#define SPELL_FAILURE_EFFECTS
Definition: config.h:157
#define BALANCED_STAT_LOSS
Definition: config.h:149
#define SPELLPOINT_LEVEL_DEPEND
Definition: config.h:155
int init_regions(void)
Definition: region.c:292
void init_anim(void)
Definition: anim.c:44
Definition: object.h:125
struct Statistics statistics
Definition: init.c:115
Definition: object.h:442
const char * race
Definition: object.h:318
void init_block(void)
Definition: los.c:88
#define TEMPLATE_DIR
Definition: config.h:566
#define DEATH_PENALTY_RATIO
Definition: config.h:151
#define SET_FLAG(xyz, p)
Definition: define.h:223
int level
Definition: attack.h:119
#define SEARCH_ITEMS
Definition: config.h:162
EXTERN int num_animations
Definition: global.h:164
#define strdup_local
Definition: compat.h:25
EXTERN objectlink * first_friendly_object
Definition: global.h:123
#define PERMANENT_EXPERIENCE_RATIO
Definition: config.h:150
#define ARMOR_SPEED_IMPROVEMENT
Definition: config.h:171
char * buf1
Definition: attack.h:120
#define PK_LUCK_PENALTY
Definition: config.h:165
#define EMERGENCY_MAPPATH
Definition: config.h:556
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1817
const char * playerdir
Definition: global.h:244
object clone
Definition: object.h:470
struct obj * prev
Definition: object.h:278
void init_archetypes(void)
Definition: arch.c:182
#define TMPDIR
Definition: config.h:538
void init_globals(void)
Definition: init.c:274
#define ARMOR_SPEED_LINEAR
Definition: config.h:172
uint8_t subtype
Definition: object.h:339
#define NOT_PERMADETH
Definition: config.h:163
#define ARMOR_MAX_ENCHANT
Definition: config.h:168
void init_library(void)
Definition: init.c:203
static void init_attackmess(void)
Definition: init.c:500
void init_experience(void)
Definition: exp.c:167
#define FALSE
Definition: compat.h:11
#define MAP_TYPE_LEGACY
Definition: map.h:57
#define SPELL_ENCUMBRANCE
Definition: config.h:156
EXTERN char first_map_ext_path[MAX_BUF]
Definition: global.h:152
#define DEATH_PENALTY_LEVEL
Definition: config.h:152
#define safe_strncpy
Definition: compat.h:23
const char * treasures
Definition: global.h:248
Definition: object.h:465
const char * logfilename
Definition: global.h:236
const char *const spellpathnames[NRSPELLPATHS]
Definition: init.c:122
uint16_t emergency_y
Definition: global.h:297
#define FLAG_REMOVED
Definition: define.h:232
object * active_objects
Definition: object.c:62
EXTERN archetype * amulet_arch
Definition: global.h:160
char * name
Definition: map.h:278
void init_hash_table(void)
Definition: shstr.c:55
void i18n_init(void)
Definition: languages.c:168
#define ARMOR_WEIGHT_LINEAR
Definition: config.h:170
int read_smooth(void)
Definition: image.c:323
void write_todclock(void)
Definition: init.c:447
#define STARTMAX
Definition: config.h:574
static void init_emergency_mappath(void)
Definition: init.c:157
static void init_defaults(void)
Definition: init.c:400
static void init_environ(void)
Definition: init.c:236
EXTERN const char * undead_name
Definition: global.h:161
const char * tmpdir
Definition: global.h:251
#define ALWAYS_SHOW_HP
Definition: config.h:160
#define EMERGENCY_Y
Definition: config.h:559
struct regiondef * next
Definition: map.h:277
Definition: map.h:276
#define EMERGENCY_X
Definition: config.h:558
#define snprintf
Definition: win32.h:46
#define MAXATTACKMESS
Definition: attack.h:19
#define RESET_LOCATION_TIME
Definition: config.h:683
int of_close(OutputFile *of)
Definition: output_file.c:61
object * objects
Definition: object.c:60
#define SIMPLE_EXP
Definition: config.h:154
char * parent_name
Definition: map.h:279
#define EXIT_PATH(xyz)
Definition: define.h:455
EXTERN long nroferrors
Definition: global.h:134
uint16_t emergency_x
Definition: global.h:297
EXTERN Animations * animations
Definition: global.h:163
#define REGIONS
Definition: config.h:568
static void init_dynamic(void)
Definition: init.c:412
#define NROFATTACKMESS
Definition: attack.h:18
#define LOCALDIR
Definition: win32.h:103
#define PLAYERDIR
Definition: config.h:603
const char * templatedir
Definition: global.h:250
void free_experience(void)
Definition: exp.c:261
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:206
const char * archetypes
Definition: global.h:246
void free_globals(void)
Definition: init.c:327
EXTERN treasurelist * first_treasurelist
Definition: global.h:120
EXTERN artifactlist * first_artifactlist
Definition: global.h:121
#define MAX_BUF
Definition: define.h:35
#define NRSPELLPATHS
Definition: spells.h:40
#define ARCHETYPES
Definition: config.h:567
object * free_objects
Definition: object.c:61
#define RECYCLE_TMP_MAPS
Definition: config.h:159
void read_bmap_names(void)
Definition: image.c:180
struct obj * next
Definition: object.h:277
const char * uniquedir
Definition: global.h:249
#define CSPORT
Definition: config.h:364
EXTERN long nrofartifacts
Definition: global.h:146
const char * datadir
Definition: global.h:242
#define TREASURES
Definition: config.h:570
EXTERN long nrofallowedstr
Definition: global.h:147
void init_objects(void)
Definition: init.c:367
EXTERN attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS]
Definition: attack.h:131
const char * localdir
Definition: global.h:243
#define DATADIR
Definition: win32.h:98
char * jailmap
Definition: map.h:297
struct oblnk * next
Definition: object.h:444
void init_stats(int reload)
Definition: living.c:2511
EXTERN archetype * staff_arch
Definition: global.h:160
const char * mapdir
Definition: global.h:245
EXTERN int exiting
Definition: global.h:144
uint8_t type
Definition: object.h:338
struct Settings settings
Definition: init.c:40
EXTERN long trying_emergency_save
Definition: global.h:133
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.c:30
struct archt * next
Definition: object.h:467
EXTERN int animations_allocated
Definition: global.h:164
object objarray[STARTMAX]
Definition: object.c:55
void delete_map(mapstruct *m)
Definition: map.c:1755
EXTERN char first_map_path[MAX_BUF]
Definition: global.h:151
#define MAPDIR
Definition: config.h:565
#define UNIQUE_DIR
Definition: config.h:546
sstring add_string(const char *str)
Definition: shstr.c:124
EXTERN player * first_player
Definition: global.h:117
#define ARMOR_WEIGHT_REDUCTION
Definition: config.h:169
#define MOTD
Definition: config.h:494
#define CASTING_TIME
Definition: config.h:166
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
char * msg
Definition: map.h:293
EXTERN archetype * ring_arch
Definition: global.h:160
EXTERN region * first_region
Definition: global.h:119
static void init_clocks(void)
Definition: init.c:464
char * buf3
Definition: attack.h:122
unsigned long todtick
Definition: init.c:441
char * emergency_mapname
Definition: global.h:296
Definition: map.h:325
char * buf2
Definition: attack.h:121
#define REAL_WIZ
Definition: config.h:158
#define FREE_AND_CLEAR(xyz)
Definition: global.h:201
#define SET_TITLE
Definition: config.h:153
#define SET_FRIENDLY_FIRE
Definition: config.h:167
EXTERN mapstruct * first_map
Definition: global.h:118
EXTERN archetype * first_archetype
Definition: global.h:122
char * longname
Definition: map.h:291
#define CONFDIR
Definition: win32.h:100
#define FLAG_FREED
Definition: define.h:233
EXTERN long nroftreasures
Definition: global.h:145