Crossfire Server, Trunk  R213250
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  * Anything with non-zero defaults in include/global.h must be set here.
38  */
39 struct Settings settings = {
40  .csport = CSPORT,
41  .debug = llevInfo,
42  .confdir = CONFDIR,
43  .datadir = DATADIR,
44  .localdir = LOCALDIR,
45  .playerdir = PLAYERDIR,
46  .mapdir = MAPDIR,
47  .archetypes = ARCHETYPES,
48  .regions = REGIONS,
49  .treasures = TREASURES,
50  .uniquedir = UNIQUE_DIR,
51  .templatedir = TEMPLATE_DIR,
52  .tmpdir = TMPDIR,
53  .stat_loss_on_death = STAT_LOSS_ON_DEATH,
54  .pk_luck_penalty = PK_LUCK_PENALTY,
55  .permanent_exp_ratio = PERMANENT_EXPERIENCE_RATIO,
56  .death_penalty_ratio = DEATH_PENALTY_RATIO,
57  .death_penalty_level = DEATH_PENALTY_LEVEL,
58  .balanced_stat_loss = BALANCED_STAT_LOSS,
59  .not_permadeth = NOT_PERMADETH,
60  .simple_exp = SIMPLE_EXP,
61  .reset_loc_time = RESET_LOCATION_TIME,
62  .set_title = SET_TITLE,
63  .resurrection = RESURRECTION,
64  .search_items = SEARCH_ITEMS,
65  .spell_encumbrance = SPELL_ENCUMBRANCE,
66  .spell_failure_effects = SPELL_FAILURE_EFFECTS,
67  .casting_time = CASTING_TIME,
68  .real_wiz = REAL_WIZ,
69  .recycle_tmp_maps = RECYCLE_TMP_MAPS,
70  .always_show_hp = ALWAYS_SHOW_HP,
71  .spellpoint_level_depend = SPELLPOINT_LEVEL_DEPEND,
72  .set_friendly_fire = SET_FRIENDLY_FIRE,
73  .motd = MOTD,
74  .rules = "rules",
75  .news = "news",
76  .emergency_x = EMERGENCY_X,
77  .emergency_y = EMERGENCY_Y,
78  .item_power_factor = 1.0,
79  /* Armor enchantment stuff */
80  .armor_max_enchant = ARMOR_MAX_ENCHANT,
81  .armor_weight_reduction = ARMOR_WEIGHT_REDUCTION,
82  .armor_weight_linear = ARMOR_WEIGHT_LINEAR,
83  .armor_speed_improvement = ARMOR_SPEED_IMPROVEMENT,
84  .armor_speed_linear = ARMOR_SPEED_LINEAR,
85  .no_player_stealing = 1,
86  .create_home_portals = 0,
87  .personalized_blessings = 1,
88  .pk_max_experience = 5000000,
89  .pk_max_experience_percent = 10,
90  .starting_stat_min = 3,
91  .starting_stat_max = 18,
92  .starting_stat_points = 85,
93  .roll_stat_points = 115,
94  .max_stat = 0, /* max_stat - will be loaded from stats file */
95  .special_break_map = 1, /* special_break_map, 1 for historical reasons */
96 };
97 
99 
105 const char *const spellpathnames[NRSPELLPATHS] = {
106  "Protection",
107  "Fire",
108  "Frost",
109  "Electricity",
110  "Missiles",
111  "Self",
112  "Summoning",
113  "Abjuration",
114  "Restoration",
115  "Detonation",
116  "Mind",
117  "Creation",
118  "Teleportation",
119  "Information",
120  "Transmutation",
121  "Transferrence",
122  "Turning",
123  "Wounding",
124  "Death",
125  "Light"
126 };
127 
128 
140 static void init_emergency_mappath(void) {
141  char filename[MAX_BUF], tmpbuf[MAX_BUF];
142  FILE *fp;
143  int online = 0;
144 
146 
147  /* If this file doesn't exist, not a big deal */
148  snprintf(filename, sizeof(filename), "%s/%s/.emergency", settings.datadir, settings.mapdir);
149  fp = fopen(filename, "r");
150  if (fp != NULL) {
151  while (fgets(tmpbuf, MAX_BUF-1, fp)) {
152  if (tmpbuf[0] == '#')
153  continue; /* ignore comments */
154 
155  if (online == 0) {
156  tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */
157  free(settings.emergency_mapname);
158  settings.emergency_mapname = strdup_local(tmpbuf);
159  } else if (online == 1) {
160  settings.emergency_x = atoi(tmpbuf);
161  } else if (online == 2) {
162  settings.emergency_y = atoi(tmpbuf);
163  }
164  online++;
165  if (online > 2)
166  break;
167  }
168  fclose(fp);
169  if (online <= 2)
170  LOG(llevError, "Online read partial data from %s\n", filename);
171  LOG(llevDebug, "emergency map set to %s (%d, %d)\n",
172  settings.emergency_mapname,
173  settings.emergency_x, settings.emergency_y);
174  }
175 }
176 
177 
186 void init_library(void) {
187  init_environ();
188  init_globals();
189  init_stats(FALSE); /* Needs to be fairly early, since the loader will check
190  * against the settings.max_stat value
191  */
192  init_hash_table();
193  i18n_init();
194  init_objects();
195  init_block();
196  read_bmap_names();
197  read_smooth();
198  init_anim(); /* Must be after we read in the bitmaps */
199  init_archetypes(); /* Reads all archetypes from file */
200  init_attackmess();
201  init_clocks();
203  init_experience();
204 
205  /* init_dynamic() loads a map, so needs a region */
206  if (init_regions() != 0) {
207  LOG(llevError, "Please check that your maps are correctly installed.\n");
208  exit(EXIT_FAILURE);
209  }
210 
211  init_dynamic();
212 }
213 
219 static void init_environ(void) {
220  char *cp;
221 
222  cp = getenv("CROSSFIRE_LIBDIR");
223  if (cp)
224  settings.datadir = cp;
225  cp = getenv("CROSSFIRE_LOCALDIR");
226  if (cp)
227  settings.localdir = cp;
228  cp = getenv("CROSSFIRE_PLAYERDIR");
229  if (cp)
230  settings.playerdir = cp;
231  cp = getenv("CROSSFIRE_MAPDIR");
232  if (cp)
233  settings.mapdir = cp;
234  cp = getenv("CROSSFIRE_ARCHETYPES");
235  if (cp)
236  settings.archetypes = cp;
237  cp = getenv("CROSSFIRE_TREASURES");
238  if (cp)
239  settings.treasures = cp;
240  cp = getenv("CROSSFIRE_UNIQUEDIR");
241  if (cp)
242  settings.uniquedir = cp;
243  cp = getenv("CROSSFIRE_TEMPLATEDIR");
244  if (cp)
245  settings.templatedir = cp;
246  cp = getenv("CROSSFIRE_TMPDIR");
247  if (cp)
248  settings.tmpdir = cp;
249 }
250 
257 void init_globals(void) {
258  memset(&statistics, 0, sizeof(struct Statistics));
259 
260  /* Log to stderr by default. */
261  logfile = stderr;
262 
263  /* Try to open the log file specified on the command-line. */
264  if (settings.logfilename != NULL) {
265  logfile = fopen(settings.logfilename, "a");
266 
267  /* If writable, set buffer mode to per-line. */
268  if (logfile != NULL) {
269  setvbuf(logfile, NULL, _IOLBF, 0);
270  } else {
271  logfile = stderr;
272 
273  LOG(llevError, "Could not open '%s' for logging.\n",
274  settings.logfilename);
275  }
276  }
277 
278  exiting = 0;
279  first_player = NULL;
280  first_friendly_object = NULL;
281  first_map = NULL;
282  first_treasurelist = NULL;
283  first_artifactlist = NULL;
284  first_archetype = NULL;
285  *first_map_ext_path = 0;
286  nroftreasures = 0;
287  nrofartifacts = 0;
288  nrofallowedstr = 0;
289  ring_arch = NULL;
290  amulet_arch = NULL;
291  undead_name = add_string("undead");
293  num_animations = 0;
294  animations = NULL;
296  init_defaults();
297 }
298 
309 void free_globals(void) {
310  int msg, attack;
311  objectlink *friend;
312  region *reg;
313 
315  for (msg = 0; msg < NROFATTACKMESS; msg++)
316  for (attack = 0; attack < MAXATTACKMESS; attack++) {
317  free(attack_mess[msg][attack].buf1);
318  free(attack_mess[msg][attack].buf2);
319  free(attack_mess[msg][attack].buf3);
320  }
321 
322  free(settings.emergency_mapname);
323 
324  while (first_friendly_object) {
325  friend = first_friendly_object->next;
327  first_friendly_object = friend;
328  }
329 
330  free_experience();
331 
332  while (first_region) {
333  reg = first_region->next;
340  first_region = reg;
341  }
342 }
343 
348 static void init_defaults(void) {
349  nroferrors = 0;
350 }
351 
360 static void init_dynamic(void) {
362  while (at) {
363  if (at->clone.type == MAP && at->clone.subtype == MAP_TYPE_LEGACY) {
364  if (at->clone.race) {
366  sizeof(first_map_ext_path));
367  }
368  if (EXIT_PATH(&at->clone)) {
369  mapstruct *first;
370 
372  first = ready_map_name(first_map_path, 0);
373  if (!first) {
374  LOG(llevError, "Initial map %s can't be found! Please ensure maps are correctly installed.\n", first_map_path);
375  LOG(llevError, "Unable to continue without initial map.\n");
376  abort();
377  }
378  delete_map(first);
379  return;
380  }
381  }
382  at = at->next;
383  }
384  LOG(llevError, "You need a archetype called 'map' and it have to contain start map\n");
385  exit(-1);
386 }
387 
389 unsigned long todtick;
390 
395 void write_todclock(void) {
396  char filename[MAX_BUF];
397  FILE *fp;
398  OutputFile of;
399 
400  snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir);
401  fp = of_open(&of, filename);
402  if (fp == NULL)
403  return;
404  fprintf(fp, "%lu", todtick);
405  of_close(&of);
406 }
407 
412 static void init_clocks(void) {
413  char filename[MAX_BUF];
414  FILE *fp;
415  static int has_been_done = 0;
416 
417  if (has_been_done)
418  return;
419  else
420  has_been_done = 1;
421 
422  snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir);
423  fp = fopen(filename, "r");
424  if (fp == NULL) {
425  LOG(llevError, "Can't open %s.\n", filename);
426  todtick = 0;
427  write_todclock();
428  return;
429  }
430  /* Read TOD and default to 0 on failure. */
431  if (fscanf(fp, "%lu", &todtick) == 1) {
432  LOG(llevDebug, "clockdata: todtick is %lu\n", todtick);
433  fclose(fp);
434  } else {
435  LOG(llevError, "Couldn't parse todtick, using default value 0\n");
436  todtick = 0;
437  fclose(fp);
438  write_todclock();
439  }
440 }
441 
448 static void init_attackmess(void) {
449  char buf[MAX_BUF];
450  char filename[MAX_BUF];
451  char *cp, *p;
452  FILE *fp;
453  static int has_been_done = 0;
454  int mess = -1, level;
455  int mode = 0, total = 0;
456 
457  if (has_been_done)
458  return;
459  else
460  has_been_done = 1;
461 
462  snprintf(filename, sizeof(filename), "%s/attackmess", settings.datadir);
463  fp = fopen(filename, "r");
464  if (fp == NULL) {
465  LOG(llevError, "Can't open %s.\n", filename);
466  return;
467  }
468 
469  level = 0;
470  while (fgets(buf, MAX_BUF, fp) != NULL) {
471  if (*buf == '#')
472  continue;
473  // Find the end of the line and strip the newline
474  cp = strchr(buf, '\n');
475  if (cp != NULL)
476  *cp = '\0';
477  /*
478  * Skip blanks -- strspn is slightly faster than a loop w/ optimization on
479  * Also, note we go from the beginning of the line again, since cp was at the end.
480  * While here, also skip tabs for more complete whitespace handling.
481  *
482  * SilverNexus 2018-01-21
483  */
484  cp = buf + strspn(buf, " \t");
485 
486  if (strncmp(cp, "TYPE:", 5) == 0) {
487  p = strtok(buf, ":");
488  p = strtok(NULL, ":");
489  if (mode == 1) {
490  attack_mess[mess][level].level = -1;
491  attack_mess[mess][level].buf1 = NULL;
492  attack_mess[mess][level].buf2 = NULL;
493  attack_mess[mess][level].buf3 = NULL;
494  }
495  level = 0;
496  mess = atoi(p);
497  mode = 1;
498  continue;
499  }
500  if (mode == 1) {
501  p = strtok(buf, "=");
502  attack_mess[mess][level].level = atoi(buf);
503  p = strtok(NULL, "=");
504  if (p != NULL)
505  attack_mess[mess][level].buf1 = strdup_local(p);
506  else
507  attack_mess[mess][level].buf1 = strdup_local("");
508  mode = 2;
509  continue;
510  } else if (mode == 2) {
511  p = strtok(buf, "=");
512  attack_mess[mess][level].level = atoi(buf);
513  p = strtok(NULL, "=");
514  if (p != NULL)
515  attack_mess[mess][level].buf2 = strdup_local(p);
516  else
517  attack_mess[mess][level].buf2 = strdup_local("");
518  mode = 3;
519  continue;
520  } else if (mode == 3) {
521  p = strtok(buf, "=");
522  attack_mess[mess][level].level = atoi(buf);
523  p = strtok(NULL, "=");
524  if (p != NULL)
525  attack_mess[mess][level].buf3 = strdup_local(p);
526  else
527  attack_mess[mess][level].buf3 = strdup_local("");
528  mode = 1;
529  level++;
530  total++;
531  continue;
532  }
533  }
534  LOG(llevDebug, "attackmsg: %d messages in %d categories\n", total, mess+1);
535  fclose(fp);
536 }
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:98
Definition: object.h:444
const char * race
Definition: object.h:318
void init_block(void)
Definition: los.c:88
#define TEMPLATE_DIR
Definition: config.h:515
#define DEATH_PENALTY_RATIO
Definition: config.h:151
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
void init_objects(void)
Definition: object.c:93
uint16_t csport
Definition: global.h:243
#define EMERGENCY_MAPPATH
Definition: config.h:505
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1821
const char * playerdir
Definition: global.h:250
object clone
Definition: object.h:472
void init_archetypes(void)
Definition: arch.c:182
#define TMPDIR
Definition: config.h:487
void init_globals(void)
Definition: init.c:257
#define ARMOR_SPEED_LINEAR
Definition: config.h:172
uint8_t subtype
Definition: object.h:340
#define NOT_PERMADETH
Definition: config.h:163
#define ARMOR_MAX_ENCHANT
Definition: config.h:168
void init_library(void)
Definition: init.c:186
static void init_attackmess(void)
Definition: init.c:448
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:254
Definition: object.h:467
const char * logfilename
Definition: global.h:242
const char *const spellpathnames[NRSPELLPATHS]
Definition: init.c:105
uint16_t emergency_y
Definition: global.h:303
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:395
static void init_emergency_mappath(void)
Definition: init.c:140
static void init_defaults(void)
Definition: init.c:348
static void init_environ(void)
Definition: init.c:219
EXTERN const char * undead_name
Definition: global.h:161
const char * tmpdir
Definition: global.h:257
#define ALWAYS_SHOW_HP
Definition: config.h:160
#define EMERGENCY_Y
Definition: config.h:508
struct regiondef * next
Definition: map.h:277
Definition: map.h:276
#define EMERGENCY_X
Definition: config.h:507
#define snprintf
Definition: win32.h:46
#define MAXATTACKMESS
Definition: attack.h:19
#define RESET_LOCATION_TIME
Definition: config.h:632
int of_close(OutputFile *of)
Definition: output_file.c:61
#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:303
EXTERN Animations * animations
Definition: global.h:163
#define REGIONS
Definition: config.h:517
static void init_dynamic(void)
Definition: init.c:360
#define NROFATTACKMESS
Definition: attack.h:18
#define LOCALDIR
Definition: win32.h:103
#define PLAYERDIR
Definition: config.h:552
const char * templatedir
Definition: global.h:256
void free_experience(void)
Definition: exp.c:262
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:206
const char * archetypes
Definition: global.h:252
void free_globals(void)
Definition: init.c:309
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:516
#define RECYCLE_TMP_MAPS
Definition: config.h:159
void read_bmap_names(void)
Definition: image.c:180
const char * uniquedir
Definition: global.h:255
#define CSPORT
Definition: config.h:361
EXTERN long nrofartifacts
Definition: global.h:146
const char * datadir
Definition: global.h:248
#define TREASURES
Definition: config.h:519
EXTERN long nrofallowedstr
Definition: global.h:147
EXTERN attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS]
Definition: attack.h:131
const char * localdir
Definition: global.h:249
#define DATADIR
Definition: win32.h:98
char * jailmap
Definition: map.h:297
struct oblnk * next
Definition: object.h:446
void init_stats(int reload)
Definition: living.c:2587
const char * mapdir
Definition: global.h:251
EXTERN int exiting
Definition: global.h:144
uint8_t type
Definition: object.h:339
struct Settings settings
Definition: init.c:39
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:469
EXTERN int animations_allocated
Definition: global.h:164
void delete_map(mapstruct *m)
Definition: map.c:1759
EXTERN char first_map_path[MAX_BUF]
Definition: global.h:151
#define MAPDIR
Definition: config.h:514
#define UNIQUE_DIR
Definition: config.h:495
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:447
#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:412
char * buf3
Definition: attack.h:122
unsigned long todtick
Definition: init.c:389
char * emergency_mapname
Definition: global.h:302
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
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:366
EXTERN long nroftreasures
Definition: global.h:145