Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 * static char *rcsid_init_c = 00003 * "$Id: init.c 11578 2009-02-23 22:02:27Z lalo $"; 00004 */ 00005 00006 /* 00007 CrossFire, A Multiplayer game for X-windows 00008 00009 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 00010 Copyright (C) 1992 Frank Tore Johansen 00011 00012 This program is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 2 of the License, or 00015 (at your option) any later version. 00016 00017 This program is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with this program; if not, write to the Free Software 00024 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00025 00026 The authors can be reached via e-mail at crossfire-devel@real-time.com 00027 */ 00028 00034 #define EXTERN 00035 #define INIT_C 00036 #include <global.h> 00037 #include <object.h> 00038 00039 static void init_environ(void); 00040 static void init_defaults(void); 00041 static void init_dynamic(void); 00042 static void init_clocks(void); 00043 static void init_attackmess(void); 00044 00048 struct Settings settings = { 00049 LOGFILE, /* Logfile */ 00050 CSPORT, /* Client/server port */ 00051 00052 /* Debug level */ 00053 #ifdef DEBUG 00054 llevDebug, 00055 #else 00056 llevInfo, 00057 #endif 00058 0, NULL, 0, /* dumpvalues, dumparg, daemonmode */ 00059 0, /* argc */ 00060 NULL, /* argv */ 00061 CONFDIR, 00062 DATADIR, 00063 LOCALDIR, 00064 PLAYERDIR, MAPDIR, ARCHETYPES, REGIONS, TREASURES, 00065 UNIQUE_DIR, TEMPLATE_DIR, 00066 TMPDIR, 00067 STAT_LOSS_ON_DEATH, 00068 PK_LUCK_PENALTY, 00069 PERMANENT_EXPERIENCE_RATIO, 00070 DEATH_PENALTY_RATIO, 00071 DEATH_PENALTY_LEVEL, 00072 BALANCED_STAT_LOSS, 00073 NOT_PERMADETH, 00074 SIMPLE_EXP, 00075 RESET_LOCATION_TIME, 00076 SET_TITLE, 00077 RESURRECTION, 00078 SEARCH_ITEMS, 00079 SPELL_ENCUMBRANCE, 00080 SPELL_FAILURE_EFFECTS, 00081 CASTING_TIME, 00082 REAL_WIZ, 00083 RECYCLE_TMP_MAPS, 00084 EXPLORE_MODE, 00085 SPELLPOINT_LEVEL_DEPEND, 00086 SET_FRIENDLY_FIRE, 00087 "", /* Who format specifier */ 00088 "", /* who wiz format specifier */ 00089 MOTD, 00090 "rules", 00091 "news", 00092 "", /* DM_MAIL */ 00093 0, /* This and the next 3 values are metaserver values */ 00094 "", 00095 "", 00096 0, 00097 "", 00098 0, 0, 0, 0, 0, 0, 0, /* worldmap settings*/ 00099 EMERGENCY_MAPPATH, EMERGENCY_X, EMERGENCY_Y, 00100 0, 00101 1.0, 00102 /* Armor enchantment stuff */ 00103 ARMOR_MAX_ENCHANT, 00104 ARMOR_WEIGHT_REDUCTION, 00105 ARMOR_WEIGHT_LINEAR, 00106 ARMOR_SPEED_IMPROVEMENT, 00107 ARMOR_SPEED_LINEAR, 00108 1, /* no_player_stealing */ 00109 0, /* create_home_portals */ 00110 1, /* personalized_blessings */ 00111 5000000, /* pk_max_experience */ 00112 10, /* pk_max_experience_percent */ 00113 0, /* allow_denied_spells_writing */ 00114 0, /* allow_broken_converters */ 00115 0, /* log_timestamp */ 00116 NULL, /* log_timestamp_format */ 00117 }; 00118 00119 struct Statistics statistics; 00120 00126 const char *const spellpathnames[NRSPELLPATHS] = { 00127 "Protection", 00128 "Fire", 00129 "Frost", 00130 "Electricity", 00131 "Missiles", 00132 "Self", 00133 "Summoning", 00134 "Abjuration", 00135 "Restoration", 00136 "Detonation", 00137 "Mind", 00138 "Creation", 00139 "Teleportation", 00140 "Information", 00141 "Transmutation", 00142 "Transferrence", 00143 "Turning", 00144 "Wounding", 00145 "Death", 00146 "Light" 00147 }; 00148 00149 00161 static void init_emergency_mappath(void) { 00162 char filename[MAX_BUF], tmpbuf[MAX_BUF]; 00163 FILE *fp; 00164 int online = 0; 00165 00166 /* If this file doesn't exist, not a big deal */ 00167 snprintf(filename, sizeof(filename), "%s/%s/.emergency", settings.datadir, settings.mapdir); 00168 if ((fp = fopen(filename, "r")) != NULL) { 00169 while (fgets(tmpbuf, MAX_BUF-1, fp)) { 00170 if (tmpbuf[0] == '#') 00171 continue; /* ignore comments */ 00172 00173 if (online == 0) { 00174 tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */ 00175 settings.emergency_mapname = strdup_local(tmpbuf); 00176 } else if (online == 1) { 00177 settings.emergency_x = atoi(tmpbuf); 00178 } else if (online == 2) { 00179 settings.emergency_y = atoi(tmpbuf); 00180 } 00181 online++; 00182 if (online > 2) 00183 break; 00184 } 00185 fclose(fp); 00186 if (online <= 2) 00187 LOG(llevError, "Online read partial data from %s\n", filename); 00188 LOG(llevDebug, "Emergency mappath reset to %s (%d, %d)\n", settings.emergency_mapname, settings.emergency_x, settings.emergency_y); 00189 } 00190 } 00191 00192 00201 void init_library(void) { 00202 init_environ(); 00203 init_globals(); 00204 init_hash_table(); 00205 i18n_init(); 00206 init_objects(); 00207 init_vars(); 00208 init_block(); 00209 read_bmap_names(); 00210 read_smooth(); 00211 init_anim(); /* Must be after we read in the bitmaps */ 00212 init_archetypes(); /* Reads all archetypes from file */ 00213 init_attackmess(); 00214 init_clocks(); 00215 init_emergency_mappath(); 00216 init_experience(); 00217 init_dynamic(); 00218 } 00219 00225 static void init_environ(void) { 00226 char *cp; 00227 00228 cp = getenv("CROSSFIRE_LIBDIR"); 00229 if (cp) 00230 settings.datadir = cp; 00231 cp = getenv("CROSSFIRE_LOCALDIR"); 00232 if (cp) 00233 settings.localdir = cp; 00234 cp = getenv("CROSSFIRE_PLAYERDIR"); 00235 if (cp) 00236 settings.playerdir = cp; 00237 cp = getenv("CROSSFIRE_MAPDIR"); 00238 if (cp) 00239 settings.mapdir = cp; 00240 cp = getenv("CROSSFIRE_ARCHETYPES"); 00241 if (cp) 00242 settings.archetypes = cp; 00243 cp = getenv("CROSSFIRE_TREASURES"); 00244 if (cp) 00245 settings.treasures = cp; 00246 cp = getenv("CROSSFIRE_UNIQUEDIR"); 00247 if (cp) 00248 settings.uniquedir = cp; 00249 cp = getenv("CROSSFIRE_TEMPLATEDIR"); 00250 if (cp) 00251 settings.templatedir = cp; 00252 cp = getenv("CROSSFIRE_TMPDIR"); 00253 if (cp) 00254 settings.tmpdir = cp; 00255 } 00256 00263 void init_globals(void) { 00264 00265 memset(&statistics, 0, sizeof(struct Statistics)); 00266 if (settings.logfilename[0] == 0) { 00267 logfile = stderr; 00268 } else if ((logfile = fopen(settings.logfilename, "a")) == NULL) { 00269 fprintf(stderr, "Unable to open %s as the logfile - will use stderr instead\n", settings.logfilename); 00270 logfile = stderr; 00271 } else { 00272 setvbuf(logfile, NULL, _IOLBF, 0); 00273 } 00274 exiting = 0; 00275 first_player = NULL; 00276 first_friendly_object = NULL; 00277 first_map = NULL; 00278 first_treasurelist = NULL; 00279 first_artifactlist = NULL; 00280 first_archetype = NULL; 00281 *first_map_ext_path = 0; 00282 warn_archetypes = 0; 00283 nroftreasures = 0; 00284 nrofartifacts = 0; 00285 nrofallowedstr = 0; 00286 ring_arch = NULL; 00287 amulet_arch = NULL; 00288 staff_arch = NULL; 00289 undead_name = add_string("undead"); 00290 trying_emergency_save = 0; 00291 num_animations = 0; 00292 animations = NULL; 00293 animations_allocated = 0; 00294 init_defaults(); 00295 } 00296 00307 void free_globals(void) { 00308 int msg, attack; 00309 objectlink *friend; 00310 region *reg; 00311 00312 FREE_AND_CLEAR_STR(undead_name); 00313 for (msg = 0; msg < NROFATTACKMESS; msg++) 00314 for (attack = 0; attack < MAXATTACKMESS; attack++) { 00315 free(attack_mess[msg][attack].buf1); 00316 free(attack_mess[msg][attack].buf2); 00317 free(attack_mess[msg][attack].buf3); 00318 } 00319 00320 free(settings.emergency_mapname); 00321 00322 while (first_friendly_object) { 00323 friend = first_friendly_object->next; 00324 FREE_AND_CLEAR(first_friendly_object); 00325 first_friendly_object = friend; 00326 } 00327 00328 free_experience(); 00329 00330 while (first_region) { 00331 reg = first_region->next; 00332 FREE_AND_CLEAR(first_region->name); 00333 FREE_AND_CLEAR(first_region->parent_name); 00334 FREE_AND_CLEAR(first_region->jailmap); 00335 FREE_AND_CLEAR(first_region->msg); 00336 FREE_AND_CLEAR(first_region->longname); 00337 FREE_AND_CLEAR(first_region); 00338 first_region = reg; 00339 } 00340 } 00341 00347 void init_objects(void) { 00348 int i; 00349 /* Initialize all objects: */ 00350 objects = NULL; 00351 active_objects = NULL; 00352 00353 #ifdef MEMORY_DEBUG 00354 free_objects = NULL; 00355 #else 00356 free_objects = objarray; 00357 objarray[0].prev = NULL, 00358 objarray[0].next = &objarray[1], 00359 SET_FLAG(&objarray[0], FLAG_REMOVED); 00360 SET_FLAG(&objarray[0], FLAG_FREED); 00361 for (i = 1; i < STARTMAX-1; i++) { 00362 objarray[i].next = &objarray[i+1]; 00363 objarray[i].prev = &objarray[i-1]; 00364 SET_FLAG(&objarray[i], FLAG_REMOVED); 00365 SET_FLAG(&objarray[i], FLAG_FREED); 00366 } 00367 objarray[STARTMAX-1].next = NULL; 00368 objarray[STARTMAX-1].prev = &objarray[STARTMAX-2]; 00369 SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED); 00370 SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED); 00371 #endif 00372 } 00373 00378 static void init_defaults(void) { 00379 nroferrors = 0; 00380 } 00381 00390 static void init_dynamic(void) { 00391 archetype *at = first_archetype; 00392 while (at) { 00393 if (at->clone.type == MAP) { 00394 if (at->clone.race) { 00395 strcpy(first_map_ext_path, at->clone.race); 00396 } 00397 if (EXIT_PATH(&at->clone)) { 00398 mapstruct *first; 00399 00400 snprintf(first_map_path, sizeof(first_map_path), "%s", EXIT_PATH(&at->clone)); 00401 first = ready_map_name(first_map_path, 0); 00402 if (!first) { 00403 LOG(llevError, "Initial map %s can't be found! Please ensure maps are correctly installed.\n", first_map_path); 00404 LOG(llevError, "Unable to continue without initial map.\n"); 00405 abort(); 00406 } 00407 delete_map(first); 00408 return; 00409 } 00410 } 00411 at = at->next; 00412 } 00413 LOG(llevError, "You need a archetype called 'map' and it have to contain start map\n"); 00414 exit(-1); 00415 } 00416 00418 unsigned long todtick; 00419 00424 void write_todclock(void) { 00425 char filename[MAX_BUF]; 00426 FILE *fp; 00427 00428 snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir); 00429 if ((fp = fopen(filename, "w")) == NULL) { 00430 LOG(llevError, "Cannot open %s for writing\n", filename); 00431 return; 00432 } 00433 fprintf(fp, "%lu", todtick); 00434 fclose(fp); 00435 } 00436 00441 static void init_clocks(void) { 00442 char filename[MAX_BUF]; 00443 FILE *fp; 00444 static int has_been_done = 0; 00445 00446 if (has_been_done) 00447 return; 00448 else 00449 has_been_done = 1; 00450 00451 snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir); 00452 LOG(llevDebug, "Reading clockdata from %s...\n", filename); 00453 if ((fp = fopen(filename, "r")) == NULL) { 00454 LOG(llevError, "Can't open %s.\n", filename); 00455 todtick = 0; 00456 write_todclock(); 00457 return; 00458 } 00459 fscanf(fp, "%lu", &todtick); 00460 LOG(llevDebug, "todtick=%lu\n", todtick); 00461 fclose(fp); 00462 } 00463 00465 attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS]; 00466 00473 static void init_attackmess(void) { 00474 char buf[MAX_BUF]; 00475 char filename[MAX_BUF]; 00476 char *cp, *p; 00477 FILE *fp; 00478 static int has_been_done = 0; 00479 int mess, level, comp; 00480 int mode = 0, total = 0; 00481 00482 if (has_been_done) 00483 return; 00484 else 00485 has_been_done = 1; 00486 00487 snprintf(filename, sizeof(filename), "%s/attackmess", settings.datadir); 00488 LOG(llevDebug, "Reading attack messages from %s...\n", filename); 00489 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) { 00490 LOG(llevError, "Can't open %s.\n", filename); 00491 return; 00492 } 00493 00494 level = 0; 00495 while (fgets(buf, MAX_BUF, fp) != NULL) { 00496 if (*buf == '#') 00497 continue; 00498 if ((cp = strchr(buf, '\n')) != NULL) 00499 *cp = '\0'; 00500 cp = buf; 00501 while (*cp == ' ') /* Skip blanks */ 00502 cp++; 00503 00504 if (strncmp(cp, "TYPE:", 5) == 0) { 00505 p = strtok(buf, ":"); 00506 p = strtok(NULL, ":"); 00507 if (mode == 1) { 00508 attack_mess[mess][level].level = -1; 00509 attack_mess[mess][level].buf1 = NULL; 00510 attack_mess[mess][level].buf2 = NULL; 00511 attack_mess[mess][level].buf3 = NULL; 00512 } 00513 level = 0; 00514 mess = atoi(p); 00515 mode = 1; 00516 continue; 00517 } 00518 if (mode == 1) { 00519 p = strtok(buf, "="); 00520 attack_mess[mess][level].level = atoi(buf); 00521 p = strtok(NULL, "="); 00522 if (p != NULL) 00523 attack_mess[mess][level].buf1 = strdup_local(p); 00524 else 00525 attack_mess[mess][level].buf1 = strdup_local(""); 00526 mode = 2; 00527 continue; 00528 } else if (mode == 2) { 00529 p = strtok(buf, "="); 00530 attack_mess[mess][level].level = atoi(buf); 00531 p = strtok(NULL, "="); 00532 if (p != NULL) 00533 attack_mess[mess][level].buf2 = strdup_local(p); 00534 else 00535 attack_mess[mess][level].buf2 = strdup_local(""); 00536 mode = 3; 00537 continue; 00538 } else if (mode == 3) { 00539 p = strtok(buf, "="); 00540 attack_mess[mess][level].level = atoi(buf); 00541 p = strtok(NULL, "="); 00542 if (p != NULL) 00543 attack_mess[mess][level].buf3 = strdup_local(p); 00544 else 00545 attack_mess[mess][level].buf3 = strdup_local(""); 00546 mode = 1; 00547 level++; 00548 total++; 00549 continue; 00550 } 00551 } 00552 LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1); 00553 close_and_delete(fp, comp); 00554 }