|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00031 #define INIT_C 00032 #define EXTERN 00033 00034 #include <global.h> 00035 00039 struct Settings settings = 00040 { 00041 /* Logfile */ 00042 "", 00043 /* Client/server port */ 00044 CSPORT, 00045 llevDebug, 00046 /* dumpvalues, dumparg, daemonmode */ 00047 0, NULL, 0, 00048 DATADIR, 00049 LOCALDIR, 00050 MAPDIR, PLAYERDIR, ARCHETYPES,TREASURES, 00051 UNIQUE_DIR, TMPDIR, 00052 STAT_LOSS_ON_DEATH, 00053 BALANCED_STAT_LOSS, 00054 /* This and the next 3 values are metaserver values */ 00055 0, 00056 "", 00057 "", 00058 "", 00059 "", 00060 ".", 00061 "", 00062 0, 00063 0, 00064 0, 00065 0, 00066 10, 00067 1.0f, 00068 0 00069 }; 00070 00072 int world_darkness; 00073 00075 unsigned long todtick; 00076 00078 archetype *level_up_arch = NULL; 00079 00081 #define ARCHETYPE_LEVEL_UP "level_up" 00082 00083 static void usage(); 00084 static void help(); 00085 static void init_beforeplay(); 00086 static void fatal_signal(int make_core); 00087 static void init_signals(); 00088 static void dump_level_colors_table(); 00089 static void init_environ(); 00090 static void init_defaults(); 00091 static void init_dynamic(); 00092 static void init_clocks(); 00093 00096 static void init_strings() 00097 { 00098 shstr_cons.none = add_string("none"); 00099 shstr_cons.NONE = add_string("NONE"); 00100 shstr_cons.home = add_string("- home -"); 00101 shstr_cons.force = add_string("force"); 00102 shstr_cons.portal_destination_name = add_string(PORTAL_DESTINATION_NAME); 00103 shstr_cons.portal_active_name = add_string(PORTAL_ACTIVE_NAME); 00104 shstr_cons.spell_quickslot = add_string("spell_quickslot"); 00105 00106 shstr_cons.GUILD_FORCE = add_string("GUILD_FORCE"); 00107 shstr_cons.guild_force = add_string("guild_force"); 00108 shstr_cons.RANK_FORCE = add_string("RANK_FORCE"); 00109 shstr_cons.rank_force = add_string("rank_force"); 00110 shstr_cons.ALIGNMENT_FORCE = add_string("ALIGNMENT_FORCE"); 00111 shstr_cons.alignment_force = add_string("alignment_force"); 00112 00113 shstr_cons.grace_limit = add_string("grace limit"); 00114 shstr_cons.restore_grace = add_string("restore grace"); 00115 shstr_cons.restore_hitpoints = add_string("restore hitpoints"); 00116 shstr_cons.restore_spellpoints = add_string("restore spellpoints"); 00117 shstr_cons.heal_spell = add_string("heal spell"); 00118 shstr_cons.remove_curse = add_string("remove curse"); 00119 shstr_cons.remove_damnation = add_string("remove damnation"); 00120 shstr_cons.heal_depletion = add_string("heal depletion"); 00121 shstr_cons.message = add_string("message"); 00122 shstr_cons.enchant_weapon = add_string("enchant weapon"); 00123 00124 shstr_cons.player_info = add_string("player_info"); 00125 shstr_cons.BANK_GENERAL = add_string("BANK_GENERAL"); 00126 shstr_cons.of_poison = add_string("of poison"); 00127 shstr_cons.of_hideous_poison = add_string("of hideous poison"); 00128 } 00129 00132 void free_strings() 00133 { 00134 int nrof_strings = sizeof(shstr_cons) / sizeof(const char *); 00135 const char **ptr = (const char **) &shstr_cons; 00136 int i = 0; 00137 00138 LOG(llevDebug, "Freeing all string constants\n"); 00139 00140 for (i = 0; i < nrof_strings; i++) 00141 { 00142 FREE_ONLY_HASH(ptr[i]); 00143 } 00144 } 00145 00154 void init_library() 00155 { 00156 init_environ(); 00157 init_hash_table(); 00158 init_globals(); 00159 /* Inits the pooling memory manager and the new object system */ 00160 init_mempools(); 00161 init_block(); 00162 LOG(llevInfo, "Atrinik Server, v%s\n", VERSION); 00163 LOG(llevInfo, "Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team.\n"); 00164 read_bmap_names(); 00165 init_materials(); 00166 /* Must be after we read in the bitmaps */ 00167 init_anim(); 00168 /* Reads all archetypes from file */ 00169 init_archetypes(); 00170 init_dynamic(); 00171 init_clocks(); 00172 00173 /* init some often used default archetypes */ 00174 if (level_up_arch == NULL) 00175 { 00176 level_up_arch = find_archetype(ARCHETYPE_LEVEL_UP); 00177 } 00178 00179 if (!level_up_arch) 00180 { 00181 LOG(llevBug, "Can't find '%s' arch\n", ARCHETYPE_LEVEL_UP); 00182 } 00183 } 00184 00190 static void init_environ() 00191 { 00192 char *cp; 00193 00194 cp = getenv("ATRINIK_LIBDIR"); 00195 00196 if (cp) 00197 { 00198 settings.datadir = cp; 00199 } 00200 00201 cp = getenv("ATRINIK_LOCALDIR"); 00202 00203 if (cp) 00204 { 00205 settings.localdir = cp; 00206 } 00207 00208 cp = getenv("ATRINIK_MAPDIR"); 00209 00210 if (cp) 00211 { 00212 settings.mapdir = cp; 00213 } 00214 00215 cp = getenv("ATRINIK_ARCHETYPES"); 00216 00217 if (cp) 00218 { 00219 settings.archetypes = cp; 00220 } 00221 00222 cp = getenv("ATRINIK_TREASURES"); 00223 00224 if (cp) 00225 { 00226 settings.treasures = cp; 00227 } 00228 00229 cp = getenv("ATRINIK_UNIQUEDIR"); 00230 00231 if (cp) 00232 { 00233 settings.uniquedir = cp; 00234 } 00235 00236 cp = getenv("ATRINIK_TMPDIR"); 00237 00238 if (cp) 00239 { 00240 settings.tmpdir = cp; 00241 } 00242 } 00243 00247 void init_globals() 00248 { 00249 if (settings.logfilename[0] == '\0') 00250 { 00251 logfile = stderr; 00252 } 00253 else if ((logfile = fopen(settings.logfilename, "w")) == NULL) 00254 { 00255 logfile = stderr; 00256 LOG(llevBug, "Unable to open %s as the logfile - will use stderr instead\n", settings.logfilename); 00257 } 00258 00259 /* Global round ticker */ 00260 global_round_tag = 1; 00261 /* Global race counter */ 00262 global_race_counter = 0; 00263 00264 first_player = NULL; 00265 last_player = NULL; 00266 first_map = NULL; 00267 first_treasurelist = NULL; 00268 first_artifactlist = NULL; 00269 first_archetype = NULL; 00270 first_map = NULL; 00271 nroftreasures = 0; 00272 nrofartifacts = 0; 00273 nrofallowedstr = 0; 00274 init_strings(); 00275 init_object_initializers(); 00276 num_animations = 0; 00277 animations = NULL; 00278 animations_allocated = 0; 00279 init_defaults(); 00280 } 00281 00286 static void init_defaults() 00287 { 00288 nroferrors = 0; 00289 } 00290 00293 static void init_dynamic() 00294 { 00295 archetype *at = first_archetype; 00296 00297 while (at) 00298 { 00299 if (at->clone.type == MAP && EXIT_PATH(&at->clone)) 00300 { 00301 strcpy(first_map_path, EXIT_PATH(&at->clone)); 00302 return; 00303 } 00304 00305 at = at->next; 00306 } 00307 00308 LOG(llevError, "init_dynamic(): You need an archetype called 'map' and it has to contain start map.\n"); 00309 } 00310 00314 void write_todclock() 00315 { 00316 char filename[MAX_BUF]; 00317 FILE *fp; 00318 00319 snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir); 00320 00321 if ((fp = fopen(filename, "w")) == NULL) 00322 { 00323 LOG(llevBug, "Cannot open %s for writing.\n", filename); 00324 return; 00325 } 00326 00327 fprintf(fp, "%lu", todtick); 00328 fclose(fp); 00329 } 00330 00335 static void init_clocks() 00336 { 00337 char filename[MAX_BUF]; 00338 FILE *fp; 00339 static int has_been_done = 0; 00340 00341 if (has_been_done) 00342 { 00343 return; 00344 } 00345 else 00346 { 00347 has_been_done = 1; 00348 } 00349 00350 snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir); 00351 LOG(llevDebug, "Reading clockdata from %s...", filename); 00352 00353 if ((fp = fopen(filename, "r")) == NULL) 00354 { 00355 LOG(llevDebug, "Can't open %s.\n", filename); 00356 todtick = 0; 00357 write_todclock(); 00358 return; 00359 } 00360 00361 if (fscanf(fp, "%lu", &todtick)) 00362 { 00363 LOG(llevDebug, "todtick=%lu\n", todtick); 00364 } 00365 00366 fclose(fp); 00367 } 00368 00371 static void set_logfile(char *val) 00372 { 00373 settings.logfilename = val; 00374 } 00375 00376 static void call_version() 00377 { 00378 version(NULL); 00379 exit(0); 00380 } 00381 00382 static void showscores() 00383 { 00384 hiscore_display(NULL, 9999, NULL); 00385 exit(0); 00386 } 00387 00388 static void set_debug() 00389 { 00390 settings.debug = llevDebug; 00391 } 00392 00393 static void unset_debug() 00394 { 00395 settings.debug = llevInfo; 00396 } 00397 00398 static void set_timestamp() 00399 { 00400 settings.timestamp = 1; 00401 } 00402 00403 static void set_dumpmon1() 00404 { 00405 settings.dumpvalues = DUMP_VALUE_MONSTERS; 00406 } 00407 00408 static void set_dumpmon2() 00409 { 00410 settings.dumpvalues = DUMP_VALUE_ABILITIES; 00411 } 00412 00413 static void set_dumpmon3() 00414 { 00415 settings.dumpvalues = DUMP_VALUE_ARTIFACTS; 00416 } 00417 00418 static void set_dumpmon4() 00419 { 00420 settings.dumpvalues = DUMP_VALUE_SPELLS; 00421 } 00422 00423 static void set_dumpmon5() 00424 { 00425 settings.dumpvalues = DUMP_VALUE_SKILLS; 00426 } 00427 00428 static void set_dumpmon6() 00429 { 00430 settings.dumpvalues = DUMP_VALUE_RACES; 00431 } 00432 00433 static void set_dumpmon7() 00434 { 00435 settings.dumpvalues = DUMP_VALUE_ALCHEMY; 00436 } 00437 00438 static void set_dumpmon8() 00439 { 00440 settings.dumpvalues = DUMP_VALUE_GODS; 00441 } 00442 00443 static void set_dumpmon9() 00444 { 00445 settings.dumpvalues = DUMP_VALUE_ALCHEMY_COSTS; 00446 } 00447 00448 static void set_dumpmon10() 00449 { 00450 settings.dumpvalues = DUMP_VALUE_ARCHETYPES; 00451 } 00452 00453 static void set_dumpmon11(char *name) 00454 { 00455 settings.dumpvalues = DUMP_VALUE_MONSTER_TREASURE; 00456 settings.dumparg = name; 00457 } 00458 00459 static void set_dumpmon12() 00460 { 00461 settings.dumpvalues = DUMP_VALUE_LEVEL_COLORS; 00462 } 00463 00464 static void set_spell_dump(char *arg) 00465 { 00466 settings.dumpvalues = DUMP_VALUE_SPELLS; 00467 settings.dumparg = arg; 00468 } 00469 00470 static void set_daemon() 00471 { 00472 settings.daemonmode = 1; 00473 } 00474 00475 static void set_watchdog() 00476 { 00477 settings.watchdog = 1; 00478 } 00479 00480 static void set_interactive() 00481 { 00482 settings.interactive = 1; 00483 } 00484 00485 static void set_datadir(char *path) 00486 { 00487 settings.datadir = path; 00488 } 00489 00490 static void set_localdir(char *path) 00491 { 00492 settings.localdir = path; 00493 } 00494 00495 static void set_mapdir(char *path) 00496 { 00497 settings.mapdir = path; 00498 } 00499 00500 static void set_archetypes(char *path) 00501 { 00502 settings.archetypes = path; 00503 } 00504 00505 static void set_treasures(char *path) 00506 { 00507 settings.treasures = path; 00508 } 00509 00510 static void set_uniquedir(char *path) 00511 { 00512 settings.uniquedir = path; 00513 } 00514 00515 static void set_tmpdir(char *path) 00516 { 00517 settings.tmpdir = path; 00518 } 00519 00520 static void showscoresparm(const char *data) 00521 { 00522 hiscore_display(NULL, 9999, data); 00523 exit(0); 00524 } 00525 00526 static void set_csport(const char *val) 00527 { 00528 settings.csport = atoi(val); 00529 00530 #ifndef WIN32 00531 if (settings.csport <= 0 || settings.csport > 32765 || (settings.csport < 1024 && getuid() != 0)) 00532 { 00533 LOG(llevError, "%d is an invalid csport number.\n", settings.csport); 00534 } 00535 #endif 00536 } 00537 00538 static void stat_loss_on_death_true() 00539 { 00540 settings.stat_loss_on_death = 1; 00541 } 00542 00543 static void stat_loss_on_death_false() 00544 { 00545 settings.stat_loss_on_death = 0; 00546 } 00547 00548 static void balanced_stat_loss_true() 00549 { 00550 settings.balanced_stat_loss = 1; 00551 } 00552 00553 static void balanced_stat_loss_false() 00554 { 00555 settings.balanced_stat_loss = 0; 00556 } 00557 00558 static void set_unit_tests() 00559 { 00560 #if defined(HAVE_CHECK) 00561 settings.unit_tests = 1; 00562 #else 00563 LOG(llevInfo, "The server was built without the check unit testing framework.\nIf you want to run unit tests, you must first install this framework.\n"); 00564 exit(0); 00565 #endif 00566 } 00567 00568 static void set_world_maker(const char *data) 00569 { 00570 #if defined(HAVE_WORLD_MAKER) 00571 settings.world_maker = 1; 00572 00573 if (data) 00574 { 00575 strncpy(settings.world_maker_dir, data, sizeof(settings.world_maker_dir) - 1); 00576 settings.world_maker_dir[sizeof(settings.world_maker_dir) - 1] = '\0'; 00577 } 00578 #else 00579 (void) data; 00580 LOG(llevInfo, "The server was built without the world maker module.\n"); 00581 exit(0); 00582 #endif 00583 } 00584 00588 struct Command_Line_Options 00589 { 00591 char *cmd_option; 00592 00594 uint8 num_args; 00595 00597 uint8 pass; 00598 00604 void (*func)(); 00605 }; 00606 00615 struct Command_Line_Options options[] = 00616 { 00617 /* Pass 1 functions - Stuff that can/should be called before we actually 00618 * initialize any data. */ 00619 {"-h", 0, 1, help}, 00620 /* Honor -help also, since it is somewhat common */ 00621 {"-help", 0, 1, help}, 00622 {"-v", 0, 1, call_version}, 00623 {"-d", 0, 1, set_debug}, 00624 {"+d", 0, 1, unset_debug}, 00625 {"-data",1,1, set_datadir}, 00626 {"-local",1,1, set_localdir}, 00627 {"-maps", 1, 1, set_mapdir}, 00628 {"-arch", 1, 1, set_archetypes}, 00629 {"-treasures", 1, 1, set_treasures}, 00630 {"-uniquedir", 1, 1, set_uniquedir}, 00631 {"-tmpdir", 1, 1, set_tmpdir}, 00632 {"-log", 1, 1, set_logfile}, 00633 {"-ts", 0, 1, set_timestamp}, 00634 00635 /* Pass 2 functions. Most of these could probably be in pass 1, 00636 * as they don't require much of anything to bet set up. */ 00637 {"-csport", 1, 2, set_csport}, 00638 {"-detach", 0, 2, set_daemon}, 00639 {"-watchdog", 0, 2, set_watchdog}, 00640 {"-interactive", 0, 2, set_interactive}, 00641 00642 /* Start of pass 3 information. In theory, by pass 3, all data paths 00643 * and defaults should have been set up. */ 00644 {"-o", 0, 3, compile_info}, 00645 00646 {"-m1", 0, 3, set_dumpmon1}, 00647 {"-m2", 0, 3, set_dumpmon2}, 00648 {"-m3", 0, 3, set_dumpmon3}, 00649 {"-m4", 0, 3, set_dumpmon4}, 00650 {"-m5", 0, 3, set_dumpmon5}, 00651 {"-m6", 0, 3, set_dumpmon6}, 00652 {"-m7", 0, 3, set_dumpmon7}, 00653 {"-m8", 0, 3, set_dumpmon8}, 00654 {"-m9", 0, 3, set_dumpmon9}, 00655 {"-m10", 0, 3, set_dumpmon10}, 00656 {"-m11", 1, 3, set_dumpmon11}, 00657 {"-m12", 0, 3, set_dumpmon12}, 00658 {"-spell", 1, 3, set_spell_dump}, 00659 00660 {"-tests", 0, 3, set_unit_tests}, 00661 {"-world_maker", 1, 3, set_world_maker}, 00662 00663 {"-s", 0, 3, showscores}, 00664 {"-score", 1, 3, showscoresparm}, 00665 {"-stat_loss_on_death", 0, 3, stat_loss_on_death_true}, 00666 {"+stat_loss_on_death", 0, 3, stat_loss_on_death_false}, 00667 {"-balanced_stat_loss", 0, 3, balanced_stat_loss_true}, 00668 {"+balanced_stat_loss", 0, 3, balanced_stat_loss_false} 00669 }; 00670 00679 static void parse_args(int argc, char *argv[], int pass) 00680 { 00681 size_t i; 00682 int on_arg = 1; 00683 00684 while (on_arg < argc) 00685 { 00686 for (i = 0; i < sizeof(options) / sizeof(struct Command_Line_Options); i++) 00687 { 00688 if (!strcmp(options[i].cmd_option, argv[on_arg]) || (argv[on_arg][0] == '-' && !strcmp(options[i].cmd_option, argv[on_arg] + 1))) 00689 { 00690 /* Found a matching option, but should not be processed on 00691 * this pass. Just skip over it */ 00692 if (options[i].pass != pass) 00693 { 00694 on_arg += options[i].num_args + 1; 00695 break; 00696 } 00697 00698 if (options[i].num_args) 00699 { 00700 if ((on_arg + options[i].num_args) >= argc) 00701 { 00702 LOG(llevSystem, "command line: %s requires an argument.\n", options[i].cmd_option); 00703 exit(1); 00704 } 00705 else 00706 { 00707 if (options[i].num_args == 1) 00708 { 00709 options[i].func(argv[on_arg + 1]); 00710 } 00711 00712 if (options[i].num_args == 2) 00713 { 00714 options[i].func(argv[on_arg + 1],argv[on_arg + 2]); 00715 } 00716 00717 on_arg += options[i].num_args + 1; 00718 } 00719 } 00720 /* takes no args */ 00721 else 00722 { 00723 options[i].func(); 00724 on_arg++; 00725 } 00726 00727 break; 00728 } 00729 } 00730 00731 if (i == sizeof(options) / sizeof(struct Command_Line_Options)) 00732 { 00733 LOG(llevSystem, "Unknown option: %s\n", argv[on_arg]); 00734 usage(); 00735 exit(1); 00736 } 00737 } 00738 } 00739 00746 static void load_settings() 00747 { 00748 char buf[MAX_BUF], *cp; 00749 int has_val, comp; 00750 FILE *fp; 00751 00752 snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, SETTINGS); 00753 00754 /* We don't require a settings file at current time, but down the road, 00755 * there will probably be so many values that not having a settings file 00756 * will not be a good thing. */ 00757 if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) 00758 { 00759 LOG(llevBug, "No %s file found\n", SETTINGS); 00760 return; 00761 } 00762 00763 while (fgets(buf, MAX_BUF-1, fp) != NULL) 00764 { 00765 if (buf[0] == '#') 00766 { 00767 continue; 00768 } 00769 00770 /* eliminate newline */ 00771 if ((cp = strrchr(buf, '\n')) != NULL) 00772 { 00773 *cp = '\0'; 00774 } 00775 00776 /* Skip over empty lines */ 00777 if (buf[0] == 0) 00778 { 00779 continue; 00780 } 00781 00782 /* Skip all the spaces and set them to nulls. If not space, 00783 * set cp to "" to make strcpy's and the like easier down below. */ 00784 if ((cp = strchr(buf, ' ')) != NULL) 00785 { 00786 while (*cp == ' ') 00787 { 00788 *cp++ = 0; 00789 } 00790 00791 has_val = 1; 00792 } 00793 else 00794 { 00795 cp = ""; 00796 has_val = 0; 00797 } 00798 00799 if (!strcasecmp(buf, "metaserver_notification")) 00800 { 00801 if (!strcasecmp(cp, "on") || !strcasecmp(cp, "true")) 00802 { 00803 settings.meta_on = 1; 00804 } 00805 else if (!strcasecmp(cp, "off") || !strcasecmp(cp, "false")) 00806 { 00807 settings.meta_on = 0; 00808 } 00809 else 00810 { 00811 LOG(llevBug, "load_settings(): Unknown value for metaserver_notification: %s\n", cp); 00812 } 00813 } 00814 else if (!strcasecmp(buf, "metaserver_server")) 00815 { 00816 if (has_val) 00817 { 00818 strcpy(settings.meta_server, cp); 00819 } 00820 else 00821 { 00822 LOG(llevBug, "load_settings(): metaserver_server must have a value.\n"); 00823 } 00824 } 00825 else if (!strcasecmp(buf, "metaserver_host")) 00826 { 00827 if (has_val) 00828 { 00829 strcpy(settings.meta_host, cp); 00830 } 00831 else 00832 { 00833 LOG(llevBug, "load_settings(): metaserver_host must have a value.\n"); 00834 } 00835 } 00836 else if (!strcasecmp(buf, "metaserver_name")) 00837 { 00838 if (has_val) 00839 { 00840 strcpy(settings.meta_name, cp); 00841 } 00842 else 00843 { 00844 LOG(llevBug, "load_settings(): metaserver_name must have a value.\n"); 00845 } 00846 } 00847 else if (!strcasecmp(buf, "metaserver_comment")) 00848 { 00849 strcpy(settings.meta_comment, cp); 00850 } 00851 else if (!strcasecmp(buf, "item_power_factor")) 00852 { 00853 float tmp = atof(cp); 00854 00855 if (tmp < 0) 00856 { 00857 LOG(llevError, "load_settings(): item_power_factor must be a positive number (%f < 0).\n", tmp); 00858 } 00859 else 00860 { 00861 settings.item_power_factor = tmp; 00862 } 00863 } 00864 else if (!strcasecmp(buf, "magic_devices_level")) 00865 { 00866 settings.magic_devices_level = atoi(cp); 00867 } 00868 else if (!strcasecmp(buf, "client_maps")) 00869 { 00870 if (has_val) 00871 { 00872 strcpy(settings.client_maps_url, cp); 00873 } 00874 else 00875 { 00876 LOG(llevBug, "load_settings(): client_maps must have a value.\n"); 00877 } 00878 } 00879 else 00880 { 00881 LOG(llevBug, "Unknown value in %s file: %s\n", SETTINGS, buf); 00882 } 00883 } 00884 00885 close_and_delete(fp, comp); 00886 } 00887 00894 void init(int argc, char **argv) 00895 { 00896 /* We don't want to be affected by players' umask */ 00897 (void) umask(0); 00898 00899 /* Must be done before init_signal() */ 00900 init_done = 0; 00901 logfile = stderr; 00902 00903 /* First arg pass - right now it does 00904 * nothing, but in future specifying the 00905 * LibDir in this pass would be reasonable*/ 00906 parse_args(argc, argv, 1); 00907 00908 /* Must be called early */ 00909 init_library(); 00910 /* Load the settings file */ 00911 load_settings(); 00912 init_world_darkness(); 00913 parse_args(argc, argv, 2); 00914 00915 SRANDOM(time(NULL)); 00916 00917 /* Sets up signal interceptions */ 00918 init_signals(); 00919 /* Sort command tables */ 00920 init_commands(); 00921 /* Load up the old temp map files */ 00922 read_map_log(); 00923 parse_args(argc, argv, 3); 00924 cftimer_init(); 00925 init_regions(); 00926 hiscore_init(); 00927 00928 #ifndef WIN32 00929 if (settings.daemonmode) 00930 { 00931 become_daemon(settings.logfilename[0] == '\0' ? "logfile" : settings.logfilename); 00932 } 00933 #endif 00934 00935 init_beforeplay(); 00936 init_ericserver(); 00937 metaserver_init(); 00938 load_bans_file(); 00939 statistics_init(); 00940 reset_sleep(); 00941 init_done = 1; 00942 } 00943 00946 static void usage() 00947 { 00948 LOG(llevInfo, "Usage: atrinik_server [-h] [-<flags>]...\n"); 00949 } 00950 00953 static void help() 00954 { 00955 LOG(llevInfo, "Flags:\n"); 00956 LOG(llevInfo, " -csport <port> Specifies the port to use for the new client/server code.\n"); 00957 LOG(llevInfo, " -d Turns on some debugging.\n"); 00958 LOG(llevInfo, " +d Turns off debugging (useful if server compiled with debugging\n"); 00959 LOG(llevInfo, " as default).\n"); 00960 LOG(llevInfo, " -detach The server will go in the background, closing all\n"); 00961 LOG(llevInfo, " connections to the tty (UNIX only).\n"); 00962 LOG(llevInfo, " -h, -help Display this information.\n"); 00963 LOG(llevInfo, " -log <file> Specifies which file to send output to.\n"); 00964 LOG(llevInfo, " Only has meaning if -detach is specified.\n"); 00965 LOG(llevInfo, " -o Prints out info on what was defined at compile time.\n"); 00966 LOG(llevInfo, " -s Display the high-score list.\n"); 00967 LOG(llevInfo, " -score <name or class> Displays all high scores with matching name/class.\n"); 00968 LOG(llevInfo, " -stat_loss_on_death - If set, player loses stat when they die.\n"); 00969 LOG(llevInfo, " +stat_loss_on_death - If set, player does not lose a stat when they die.\n"); 00970 LOG(llevInfo, " -balanced_stat_loss - If set, death stat depletion is balanced by level etc.\n"); 00971 LOG(llevInfo, " +balanced_stat_loss - If set, ordinary death stat depletion is used.\n"); 00972 LOG(llevInfo, " -v Print version information.\n"); 00973 LOG(llevInfo, " -data Sets the lib dir (archetypes, treasures, etc.)\n"); 00974 LOG(llevInfo, " -local Read/write local data (hiscore, unique items, etc.)\n"); 00975 LOG(llevInfo, " -maps Sets the directory for maps.\n"); 00976 LOG(llevInfo, " -arch Sets the archetype file to use.\n"); 00977 LOG(llevInfo, " -treasures Sets the treasures file to use.\n"); 00978 LOG(llevInfo, " -uniquedir Sets the unique items/maps directory.\n"); 00979 LOG(llevInfo, " -tmpdir Sets the directory for temporary files (mostly maps.)\n"); 00980 LOG(llevInfo, " -m1 Dumps out object settings for all monsters.\n"); 00981 LOG(llevInfo, " -m2 Dumps out abilities for all monsters.\n"); 00982 LOG(llevInfo, " -m3 Dumps out artifact information.\n"); 00983 LOG(llevInfo, " -m4 Dumps out spell information.\n"); 00984 LOG(llevInfo, " -m5 Dumps out skill information.\n"); 00985 LOG(llevInfo, " -m6 Dumps out race information.\n"); 00986 LOG(llevInfo, " -m7 Dumps out alchemy information.\n"); 00987 LOG(llevInfo, " -m8 Dumps out gods information.\n"); 00988 LOG(llevInfo, " -m9 Dumps out more alchemy information (formula checking).\n"); 00989 LOG(llevInfo, " -m10 Dumps out all arches.\n"); 00990 LOG(llevInfo, " -m11 <arch> Dumps out list of treasures for a monster.\n"); 00991 LOG(llevInfo, " -m12 Dumps out level colors table.\n"); 00992 LOG(llevInfo, " -spell <name> Dumps various information about the specified spell\n"); 00993 LOG(llevInfo, " (if 'all', information about all spells available). This\n"); 00994 LOG(llevInfo, " is useful when debugging/balancing spells.\n"); 00995 00996 #if defined(HAVE_CHECK) 00997 LOG(llevInfo, " -tests Runs unit tests.\n"); 00998 #endif 00999 01000 #if defined(HAVE_WORLD_MAKER) 01001 LOG(llevInfo, " -world_maker <path> Generates region maps and stores them in the specified path.\n"); 01002 #endif 01003 01004 LOG(llevInfo, " -watchdog Enables sending datagrams to an external watchdog program.\n"); 01005 LOG(llevInfo, " -interactive Enables interactive mode. Type 'help' in console for more information.\n"); 01006 LOG(llevInfo, " -ts If enabled, all log entries will be prefixed with UNIX timestamp.\n"); 01007 01008 exit(0); 01009 } 01010 01013 static void init_beforeplay() 01014 { 01015 init_archetypes(); 01016 init_spells(); 01017 race_init(); 01018 init_gods(); 01019 init_readable(); 01020 init_archetype_pointers(); 01021 init_formulae(); 01022 init_new_exp_system(); 01023 01024 if (settings.dumpvalues) 01025 { 01026 switch (settings.dumpvalues) 01027 { 01028 case DUMP_VALUE_MONSTERS: 01029 print_monsters(); 01030 break; 01031 01032 case DUMP_VALUE_ABILITIES: 01033 dump_abilities(); 01034 break; 01035 01036 case DUMP_VALUE_ARTIFACTS: 01037 dump_artifacts(); 01038 break; 01039 01040 case DUMP_VALUE_SPELLS: 01041 dump_spells(); 01042 break; 01043 01044 case DUMP_VALUE_SKILLS: 01045 dump_skills(); 01046 break; 01047 01048 case DUMP_VALUE_RACES: 01049 race_dump(); 01050 break; 01051 01052 case DUMP_VALUE_ALCHEMY: 01053 dump_alchemy(); 01054 break; 01055 01056 case DUMP_VALUE_GODS: 01057 dump_gods(); 01058 break; 01059 01060 case DUMP_VALUE_ALCHEMY_COSTS: 01061 dump_alchemy_costs(); 01062 break; 01063 01064 case DUMP_VALUE_ARCHETYPES: 01065 dump_all_archetypes(); 01066 break; 01067 01068 case DUMP_VALUE_MONSTER_TREASURE: 01069 dump_monster_treasure(settings.dumparg); 01070 break; 01071 01072 case DUMP_VALUE_LEVEL_COLORS: 01073 dump_level_colors_table(); 01074 break; 01075 } 01076 01077 exit(0); 01078 } 01079 } 01080 01086 void compile_info() 01087 { 01088 int i = 0; 01089 01090 LOG(llevInfo, "Setup info:\n"); 01091 LOG(llevInfo, "Non-standard include files:\n"); 01092 #if !defined (__STRICT_ANSI__) || defined (__sun__) 01093 #if !defined (Mips) 01094 LOG(llevInfo, "<stdlib.h>\n"); 01095 i = 1; 01096 #endif 01097 01098 #if !defined (MACH) && !defined (sony) 01099 LOG(llevInfo, "<malloc.h>\n"); 01100 i = 1; 01101 #endif 01102 #endif 01103 01104 #ifndef __STRICT_ANSI__ 01105 #ifndef MACH 01106 LOG(llevInfo, "<memory.h\n"); 01107 i = 1; 01108 #endif 01109 #endif 01110 01111 #ifndef sgi 01112 LOG(llevInfo, "<sys/timeb.h>\n"); 01113 i = 1; 01114 #endif 01115 01116 if (!i) 01117 { 01118 LOG(llevInfo, "(none)\n"); 01119 } 01120 01121 LOG(llevInfo, "Datadir:\t%s\n", settings.datadir); 01122 LOG(llevInfo, "Localdir:\t%s\n", settings.localdir); 01123 01124 LOG(llevInfo, "Save player:\t<true>\n"); 01125 LOG(llevInfo, "Save mode:\t%4.4o\n", SAVE_MODE); 01126 LOG(llevInfo, "Itemsdir:\t%s/%s\n", settings.localdir, settings.uniquedir); 01127 01128 LOG(llevInfo, "Tmpdir:\t\t%s\n", settings.tmpdir); 01129 LOG(llevInfo, "Map timeout:\t%d\n", MAP_MAXTIMEOUT); 01130 01131 LOG(llevInfo, "Objects:\tAllocated: %d, free: %d\n", pool_object->nrof_allocated[0], pool_object->nrof_free[0]); 01132 01133 #ifdef USE_CALLOC 01134 LOG(llevInfo, "Use_calloc:\t<true>\n"); 01135 #else 01136 LOG(llevInfo, "Use_calloc:\t<false>\n"); 01137 #endif 01138 01139 LOG(llevInfo, "Max_time:\t%d\n", MAX_TIME); 01140 01141 LOG(llevInfo, "Logfilename:\t%s (llev:%d)\n", settings.logfilename, settings.debug); 01142 LOG(llevInfo, "ObjectSize:\t%"FMT64U" (living: %"FMT64U")\n", (uint64) sizeof(object), (uint64) sizeof(living)); 01143 LOG(llevInfo, "ObjectlinkSize:\t%"FMT64U"\n", (uint64) sizeof(objectlink)); 01144 LOG(llevInfo, "MapStructSize:\t%"FMT64U"\n", (uint64) sizeof(mapstruct)); 01145 LOG(llevInfo, "MapSpaceSize:\t%"FMT64U"\n", (uint64) sizeof(MapSpace)); 01146 LOG(llevInfo, "PlayerSize:\t%"FMT64U"\n", (uint64) sizeof(player)); 01147 LOG(llevInfo, "SocketSize:\t%"FMT64U"\n", (uint64) sizeof(socket_struct)); 01148 LOG(llevInfo, "PartylistSize:\t%"FMT64U"\n", (uint64) sizeof(party_struct)); 01149 LOG(llevInfo, "KeyValueSize:\t%"FMT64U"\n", (uint64) sizeof(key_value)); 01150 01151 LOG(llevInfo, "Setup info: Done.\n"); 01152 } 01153 01156 static void rec_sigsegv(int i) 01157 { 01158 (void) i; 01159 01160 LOG(llevSystem, "\nSIGSEGV received.\n"); 01161 fatal_signal(1); 01162 } 01163 01164 static void rec_sigint(int i) 01165 { 01166 (void) i; 01167 01168 LOG(llevSystem, "\nSIGINT received.\n"); 01169 fatal_signal(0); 01170 } 01171 01172 static void rec_sighup(int i) 01173 { 01174 (void) i; 01175 01176 LOG(llevSystem, "\nSIGHUP received\n"); 01177 01178 if (init_done) 01179 { 01180 emergency_save(0); 01181 cleanup(); 01182 } 01183 01184 exit(0); 01185 } 01186 01187 static void rec_sigquit(int i) 01188 { 01189 (void) i; 01190 01191 LOG(llevSystem, "\nSIGQUIT received\n"); 01192 fatal_signal(1); 01193 } 01194 01195 static void rec_sigpipe(int i) 01196 { 01197 (void) i; 01198 01199 #ifndef WIN32 01200 LOG(llevSystem, "\nSIGPIPE received, ignoring\n"); 01201 signal(SIGPIPE, rec_sigpipe); 01202 #else 01203 LOG(llevSystem, "\nSIGPIPE received\n"); 01204 fatal_signal(1); 01205 #endif 01206 } 01207 01208 static void rec_sigbus(int i) 01209 { 01210 (void) i; 01211 01212 #ifdef SIGBUS 01213 LOG(llevSystem, "\nSIGBUS received\n"); 01214 fatal_signal(1); 01215 #endif 01216 } 01217 01218 static void rec_sigterm(int i) 01219 { 01220 (void) i; 01221 01222 LOG(llevSystem,"\nSIGTERM received\n"); 01223 fatal_signal(0); 01224 } 01225 01233 static void fatal_signal(int make_core) 01234 { 01235 if (init_done) 01236 { 01237 emergency_save(0); 01238 cleanup(); 01239 } 01240 01241 if (make_core) 01242 { 01243 abort(); 01244 } 01245 01246 exit(0); 01247 } 01248 01251 static void init_signals() 01252 { 01253 #ifndef WIN32 01254 /* init_signals() remove signals */ 01255 signal(SIGHUP, rec_sighup); 01256 signal(SIGINT, rec_sigint); 01257 signal(SIGQUIT, rec_sigquit); 01258 signal(SIGSEGV, rec_sigsegv); 01259 signal(SIGPIPE, rec_sigpipe); 01260 # ifdef SIGBUS 01261 signal(SIGBUS, rec_sigbus); 01262 # endif 01263 signal(SIGTERM, rec_sigterm); 01264 #endif 01265 } 01266 01269 static void dump_level_colors_table() 01270 { 01271 int i, ii, range, tmp; 01272 01273 uint32 vx = 0, vc = 1000000; 01274 float xc = 38; 01275 01276 for (i = 0; i < 100; i++) 01277 { 01278 vc += 100000; 01279 vx += vc; 01280 LOG(-1, "%4.2f, ", (((float) vc) / xc) / 125.0f); 01281 xc += 2; 01282 } 01283 01284 LOG(-1, "\n"); 01285 01286 for (i = 1; i < 201; i++) 01287 { 01288 for (ii = i; ii > 1; ii--) 01289 { 01290 if (!calc_level_difference(i, ii)) 01291 { 01292 break; 01293 } 01294 } 01295 01296 level_color[i].yellow = i - (i / 33); 01297 level_color[i].blue = level_color[i].yellow - 1; 01298 level_color[i].orange = i + (i / 33) + 1; 01299 01300 range = level_color[i].yellow - ii - 1; 01301 01302 if (range < 2) 01303 { 01304 level_color[i].green = level_color[i].blue - 1; 01305 level_color[i].red = level_color[i].orange + 1; 01306 level_color[i].purple = level_color[i].orange + 2; 01307 } 01308 else 01309 { 01310 tmp = (int) ((double) range * 0.4); 01311 01312 if (!tmp) 01313 { 01314 tmp = 1; 01315 } 01316 else if (tmp == range) 01317 { 01318 tmp--; 01319 } 01320 01321 level_color[i].green = level_color[i].blue - (range - tmp); 01322 01323 range = (int) ((double) range * 0.75); 01324 01325 if (!range) 01326 { 01327 range = 0; 01328 } 01329 01330 tmp = (int) ((double) range * 0.7); 01331 01332 if (!tmp) 01333 { 01334 tmp = 1; 01335 } 01336 else if (tmp == range) 01337 { 01338 tmp--; 01339 } 01340 01341 if (tmp == range) 01342 { 01343 range++; 01344 } 01345 01346 level_color[i].red = level_color[i].orange + (range - tmp); 01347 level_color[i].purple = level_color[i].red + tmp; 01348 } 01349 01350 LOG(llevSystem, "{ %d, %d, %d, %d, %d, %d}, lvl %d \n", ii + 1, level_color[i].green + 1, level_color[i].yellow, level_color[i].orange, level_color[i].red, level_color[i].purple, i); 01351 } 01352 }
1.7.4