/* vi: set ts=2: * * * Eressea PB(E)M host Copyright (C) 1998-2003 * Christian Schlittchen (corwin@amber.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de) * Henning Peters (faroul@beyond.kn-bremen.de) * Enno Rehling (enno@eressea.de) * Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) * * based on: * * Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace * Atlantis v1.7 Copyright 1996 by Alex Schröder * * This program may not be used, modified or distributed without * prior permission by the authors of Eressea. * This program may not be sold or used commercially without prior written * permission from the authors. */ /* config includes */ #include #include #include "console.h" #include "gmtool.h" /* initialization - TODO: init in separate module */ #include #include #include #include #include #include /* modules includes */ #include #include #include #if MUSEUM_MODULE #include #endif #include #if ARENA_MODULE #include #endif #if DUNGEON_MODULE #include #endif /* gamecode includes */ #include #include #include #include #include #include #include /* kernel includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* util includes */ #include #include #include #include #include #include #ifdef MSPACES # include #endif /* external iniparser */ #include /* lua includes */ #include "lua/bindings.h" #include "lua/script.h" #include #ifdef _MSC_VER #pragma warning (push) #pragma warning (disable: 4127) #endif #include #include #ifdef _MSC_VER #pragma warning (pop) #endif #include /* stdc++ includes */ #include #include #include /* libc includes */ #include #include #include #include #include #include #if defined(_MSC_VER) # include #endif /** ** global variables we are importing from other modules **/ extern "C" { extern const char * g_reportdir; extern const char * g_datadir; extern const char * g_basedir; extern const char * g_resourcedir; extern boolean nobattle; extern boolean nomonsters; extern boolean battledebug; extern int loadplane; extern boolean opt_cr_absolute_coords; } /** ** global variables that we are exporting **/ static char * orders = NULL; static int nowrite = 0; static boolean g_writemap = false; static boolean g_ignore_errors = false; static boolean opt_reportonly = false; static const char * luafile = NULL; static const char * script_path = "scripts"; static int memdebug = 0; #if defined(HAVE_SIGACTION) && defined(HAVE_EXECINFO) #include #include static void report_segfault(int signo, siginfo_t * sinf, void * arg) { void * btrace[50]; size_t size; int fd = fileno(stderr); fflush(stdout); fputs("\n\nProgram received SIGSEGV, backtrace follows.\n", stderr); size = backtrace(btrace, 50); backtrace_symbols_fd(btrace, size, fd); abort(); } static int setup_signal_handler(void) { struct sigaction act; act.sa_flags = SA_ONESHOT | SA_SIGINFO; act.sa_sigaction = report_segfault; sigfillset(&act.sa_mask); return sigaction(SIGSEGV, &act, NULL); } #else static int setup_signal_handler(void) { return 0; } #endif static void game_init(void) { init_triggers(); init_xmas(); reports_init(); report_init(); creport_init(); xmlreport_init(); debug_language("locales.log"); register_races(); register_names(); register_resources(); register_buildings(); register_ships(); register_itemfunctions(); register_spells(); register_gcspells(); #if DUNGEON_MODULE register_dungeon(); #endif #if MUSEUM_MODULE register_museum(); #endif #if ARENA_MODULE register_arena(); #endif register_wormholes(); register_itemtypes(); register_xmlreader(); register_archetypes(); enable_xml_gamecode(); init_data(xmlfile); init_locales(); init_archetypes(); init_attributes(); init_itemtypes(); init_rawmaterials(); init_gmcmd(); #if INFOCMD_MODULE init_info(); #endif } static const struct { const char * name; int (*func)(lua_State *); } lualibs[] = { {"", luaopen_base}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, #if LUA_VERSION_NUM>=501 {LUA_OSLIBNAME, luaopen_os}, #endif { NULL, NULL } }; static void openlibs(lua_State * L) { int i; for (i=0;lualibs[i].func;++i) { lua_pushcfunction(L, lualibs[i].func); lua_pushstring(L, lualibs[i].name); lua_call(L, 1, 0); } } static lua_State * lua_init(void) { lua_State * L = lua_open(); openlibs(L); luabind::open(L); bind_objects(L); bind_eressea(L); bind_script(L); bind_spell(L); bind_alliance(L); bind_region(L); bind_item(L); bind_faction(L); bind_unit(L); bind_ship(L); bind_building(L); bind_event(L); bind_message(L); bind_gamecode(L); bind_gmtool(L); bind_test(L); return L; } static void lua_done(lua_State * luaState) { reset_scripts(); lua_close(luaState); } static void game_done(void) { #ifdef CLEANUP_CODE /* Diese Routine enfernt allen allokierten Speicher wieder. Das ist nur * zum Debugging interessant, wenn man Leak Detection hat, und nach * nicht freigegebenem Speicher sucht, der nicht bis zum Ende benötigt * wird (temporäre Hilsstrukturen) */ free_game(); creport_cleanup(); #ifdef REPORT_FORMAT_NR report_cleanup(); #endif calendar_cleanup(); #endif } #define CRTDBG #ifdef CRTDBG void init_crtdbg(void) { #if (defined(_MSC_VER)) int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); if (memdebug==1) { flags |= _CRTDBG_CHECK_ALWAYS_DF; /* expensive */ } else if (memdebug==2) { flags = (flags&0x0000FFFF) | _CRTDBG_CHECK_EVERY_16_DF; } else if (memdebug==3) { flags = (flags&0x0000FFFF) | _CRTDBG_CHECK_EVERY_128_DF; } else if (memdebug==4) { flags = (flags&0x0000FFFF) | _CRTDBG_CHECK_EVERY_1024_DF; } _CrtSetDbgFlag(flags); #endif } #endif static int usage(const char * prog, const char * arg) { if (arg) { fprintf(stderr, "unknown argument: %s\n\n", arg); } fprintf(stderr, "Usage: %s [options]\n" "-v befehlsdatei : verarbeitet automatisch die angegebene Befehlsdatei\n" "-q : be less verbose\n" "-d datadir : gibt das datenverzeichnis an\n" "-b basedir : gibt das basisverzeichnis an\n" "-r resdir : gibt das resourceverzeichnis an\n" "-t turn : read this datafile, not the most current one\n" "-o reportdir : gibt das reportverzeichnis an\n" "-l path : specify the base script directory\n" "-C : run in interactive mode\n" "-e script : main lua script\n" "-R : erstellt nur die Reports neu\n" "--lomem : keine Messages (RAM sparen)\n" "--nobattle : keine Kämpfe\n" "--ignore-errors : ignore errors in scripts (please don\'t)\n" "--nomonsters : keine monster KI\n" "--nodebug : keine Logfiles für Kämpfe\n" "--noreports : absolut keine Reporte schreiben\n" "--debug : schreibt Debug-Ausgaben in die Datei debug\n" "--color : force curses to use colors even when not detected\n" "--nocr : keine CRs\n" "--nonr : keine Reports\n" "--crabsolute : absolute Koordinaten im CR\n" "--help : help\n", prog); return -1; } static void setLuaString(lua_State * luaState, const char * name, const char * value) { #if LUABIND_BETA<7 || (LUABIND_BETA==7 && LUABIND_DEVEL<2) luabind::object g = luabind::get_globals(luaState); #else luabind::object g = luabind::globals(luaState); #endif g[name] = value; } static void setLuaNumber(lua_State * luaState, const char * name, double value) { #if LUABIND_BETA<7 || (LUABIND_BETA==7 && LUABIND_DEVEL<2) luabind::object g = luabind::get_globals(luaState); #else luabind::object g = luabind::globals(luaState); #endif g[name] = value; } static int read_args(int argc, char **argv, lua_State * luaState) { int i; char * c; for (i=1;i!=argc;++i) { if (argv[i][0]!='-') { return usage(argv[0], argv[i]); } else if (argv[i][1]=='-') { /* long format */ if (strcmp(argv[i]+2, "nocr")==0) nocr = true; else if (strcmp(argv[i]+2, "nosave")==0) nowrite = true; else if (strcmp(argv[i]+2, "noreports")==0) { noreports = true; nocr = true; nocr = true; } else if (strcmp(argv[i]+2, "xml")==0) xmlfile = argv[++i]; else if (strcmp(argv[i]+2, "ignore-errors")==0) g_ignore_errors = true; else if (strcmp(argv[i]+2, "nonr")==0) nonr = true; else if (strcmp(argv[i]+2, "lomem")==0) lomem = true; else if (strcmp(argv[i]+2, "nobattle")==0) nobattle = true; else if (strcmp(argv[i]+2, "nomonsters")==0) nomonsters = true; else if (strcmp(argv[i]+2, "nodebug")==0) battledebug = false; else if (strcmp(argv[i]+2, "console")==0) luafile=NULL; else if (strcmp(argv[i]+2, "crabsolute")==0) opt_cr_absolute_coords = true; else if (strcmp(argv[i]+2, "color")==0) { /* force the editor to have colors */ force_color = 1; } else if (strcmp(argv[i]+2, "current")==0) { turn = -1; } else if (strcmp(argv[i]+2, "help")==0) return usage(argv[0], NULL); else return usage(argv[0], argv[i]); } else switch(argv[i][1]) { case 'C': luafile=NULL; break; case 'o': g_reportdir = argv[++i]; break; case 'e': luafile = argv[++i]; break; case 'd': g_datadir = argv[++i]; break; case 'r': g_resourcedir = argv[++i]; break; case 'b': g_basedir = argv[++i]; break; case 'i': xmlfile = argv[++i]; break; case 't': turn = atoi(argv[++i]); break; case 'q': quiet = 1; break; case 'v': if (i(luaState, "dofile", buf); #ifndef LUABIND_NO_EXCEPTIONS } catch (std::runtime_error& rte) { log_error(("%s.\n", rte.what())); } catch (luabind::error& e) { lua_State* L = e.state(); my_lua_error(L); } #endif } #ifdef MSPACES malloc_stats(); #endif game_done(); kernel_done(); lua_done(luaState); log_close(); setlocale(LC_CTYPE, lc_ctype); setlocale(LC_NUMERIC, lc_numeric); free(lc_ctype); free(lc_numeric); if (inifile) iniparser_free(inifile); return 0; }