/* Minetest-c55 Copyright (C) 2010 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* =============================== NOTES ============================== */ #ifndef SERVER #ifdef _WIN32 #pragma error ("For a server build, SERVER must be defined globally") #else #error "For a server build, SERVER must be defined globally" #endif #endif #ifdef NDEBUG #ifdef _WIN32 #pragma message ("Disabling unit tests") #else #warning "Disabling unit tests" #endif // Disable unit tests #define ENABLE_TESTS 0 #else // Enable unit tests #define ENABLE_TESTS 1 #endif #ifdef _MSC_VER #pragma comment(lib, "jthread.lib") #pragma comment(lib, "zlibwapi.lib") #endif #include #include #include #include #include #include "common_irrlicht.h" #include "debug.h" #include "map.h" #include "player.h" #include "main.h" #include "test.h" #include "environment.h" #include "server.h" #include "serialization.h" #include "constants.h" #include "strfnd.h" #include "porting.h" #include "config.h" #include "filesys.h" #include "defaultsettings.h" #include "settings.h" #include "profiler.h" #include "log.h" #include "nodedef.h" // For init_contentfeatures #include "content_mapnode.h" // For content_mapnode_init #include "mods.h" /* Settings. These are loaded from the config file. */ Settings main_settings; Settings *g_settings = &main_settings; // Global profiler Profiler main_profiler; Profiler *g_profiler = &main_profiler; /* Debug streams */ // Connection std::ostream *dout_con_ptr = &dummyout; std::ostream *derr_con_ptr = &verbosestream; // Server std::ostream *dout_server_ptr = &infostream; std::ostream *derr_server_ptr = &errorstream; // Client std::ostream *dout_client_ptr = &infostream; std::ostream *derr_client_ptr = &errorstream; /* gettime.h implementation */ u32 getTimeMs() { /* Use imprecise system calls directly (from porting.h) */ return porting::getTimeMs(); } class StderrLogOutput: public ILogOutput { public: /* line: Full line with timestamp, level and thread */ void printLog(const std::string &line) { std::cerr< allowed_options; allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG, "Show allowed options")); allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, "Load configuration from specified file")); allowed_options.insert("port", ValueSpec(VALUETYPE_STRING, "Set network port (UDP) to use")); allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG, "Disable unit tests")); allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG, "Enable unit tests")); allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING, "Map directory (where everything in the world is stored)")); allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG, "Print debug information to console")); Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help")) { dstream<<"Allowed options:"<::Iterator i = allowed_options.getIterator(); i.atEnd() == false; i++) { dstream<<" --"<getKey(); if(i.getNode()->getValue().type == VALUETYPE_FLAG) { } else { dstream<<" "; } dstream<getValue().help != NULL) { dstream<<" "<getValue().help <readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" < filenames; filenames.push_back(porting::path_user + DIR_DELIM + "minetest.conf"); #ifdef RUN_IN_PLACE // Try also from a lower level (to aid having the same configuration // for many RUN_IN_PLACE installs) filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; ireadConfigFile(filenames[i].c_str()); if(r) { configpath = filenames[i]; break; } } } // Initialize random seed srand(time(0)); mysrand(time(0)); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } /* Check parameters */ std::cout<__| \\___ >____ > |__| "<exists("port") && g_settings->getU16("port") != 0) port = g_settings->getU16("port"); // Map directory std::string map_dir = porting::path_user + DIR_DELIM + "server" + DIR_DELIM + "worlds" + DIR_DELIM + "world"; if(cmd_args.exists("map-dir")) map_dir = cmd_args.get("map-dir"); else if(g_settings->exists("map-dir")) map_dir = g_settings->get("map-dir"); else{ // No map-dir option was specified. // Check if the world is found from the default directory, and if // not, see if the legacy world directory exists. std::string legacy_map_dir = porting::path_user+DIR_DELIM+".."+DIR_DELIM+"world"; if(!fs::PathExists(map_dir) && fs::PathExists(legacy_map_dir)){ errorstream<<"Warning: Using legacy world directory \"" <