/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ### File Specific: main-programmer: Patrick Boenzli co-programmer: Christian Meyer co-programmer: Benjamin Grauer: injected ResourceManager/GraphicsEngine/GUI */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ORXONOX #include "orxonox.h" #include "globals.h" #include "gui/qt/qt_gui.h" #include "gui/qt/qt_gui_datadir_fallback.h" #include "parser/ini_parser/ini_parser.h" #include "util/loading/game_loader.h" #include "util/signal_handler.h" //ENGINES #include "graphics_engine.h" #include "sound_engine.h" #include "util/loading/resource_manager.h" #include "cd_engine.h" #include "text_engine.h" #include "event_handler.h" #include "loading/fast_factory.h" #include "benchmark.h" #include "shell_command_class.h" #include "shell_command.h" #include "shell_buffer.h" #include "util/loading/load_param_class_description.h" #include "network_manager.h" #include "shared_network_data.h" #include "state.h" #include "lib/parser/preferences/cmd_line_prefs_reader.h" #include "lib/parser/preferences/ini_file_prefs_reader.h" #include int verbose = 5; SHELL_COMMAND(restart, Orxonox, restart); REGISTER_ARG_FLAG( l, license, "misc", "showLicenseAndExit", "Prints the license and exit", "1" ); REGISTER_ARG_FLAG( c, client, "game", "gameType", "Connect to Server (-H)", "multiplayer_client" ); REGISTER_ARG_FLAG( s, server, "game", "gameType", "Start Orxonox as Game Server", "multiplayer_master_server" ); REGISTER_ARG_FLAG( x, proxy, "game", "gameType", "Start Orxonox as Proxy Server", "multiplayer_proxy_server" ); REGISTER_ARG_ARG( H, host, "game", "host", "Host to connect to", "host"); REGISTER_ARG_ARG( p, port, "game", "port", "Port to use", "port" ); REGISTER_ARG_FLAG( g, gui, "game", "showGui", "starts the orxonox with the configuration GUI", "1"); REGISTER_ARG_FLAG( f, fullscreen, "video", "Fullscreen-mode", "start Orxonox in fullscreen mode", "1"); REGISTER_ARG_FLAG( w, windowed, "video", "Fullscreen-mode", "start Orxonox in windowed mode", "0"); REGISTER_ARG_ARG( r, resolution, "video", "Resolution", "sets resolution / window size", "res"); REGISTER_ARG_FLAG( d, dedicated, "video", "Norender-mode", "the scene is not rendered", "1" ); REGISTER_ARG_FLAG( a, audio, "audio", "Disable-Audio", "Enable audio", "0" ); REGISTER_ARG_FLAG( m, mute , "audio", "Disable-Audio", "Disable audio", "1" ); REGISTER_ARG_ARG( _, audio_channels, "audio", "Audio-Channels", "Sets # audio channels", "num" ); REGISTER_ARG_ARG( _, music_volume, "audio", "Music-Volume", "Sets music volume", "vol" ); REGISTER_ARG_ARG( _, effects_volume, "audio", "Effects-Volume", "Sets effects volume", "vol" ); #ifndef __WIN32__ REGISTER_ARG_FLAG( _, write_bt_to_file, "misc", "bt-to-file", "Write backtrace to file", "1"); #endif REGISTER_ARG_ARG( t, telnetport, "network","telnetport", "Port to use for network debug output", "port" ); REGISTER_ARG_ARG( _, write_dict, "compression", "writedict", "write packets to DATA/dicts/newdict", "numBytes" ); ObjectListDefinition(Orxonox); /** * create a new Orxonox In this funcitons only global values are set. The game will not be started here. */ Orxonox::Orxonox () { this->registerObject(this, Orxonox::_objectList); this->setName("orxonox-main"); this->argc = 0; this->argv = NULL; /* this way, there is no network enabled: */ this->serverName = ""; this->port = -1; this->configFileName = ""; } /** * remove Orxonox from memory */ Orxonox::~Orxonox () { // game-specific delete GameLoader::getInstance(); // class-less services/factories FastFactory::deleteAll(); OrxShell::ShellCommandClass::unregisterAllCommands(); LoadParamClassDescription::deleteAllDescriptions(); // handlers delete ResourceManager::getInstance(); // deletes the Resource Manager // engines delete CDEngine::getInstance(); delete OrxSound::SoundEngine::getInstance(); delete GraphicsEngine::getInstance(); // deleting the Graphics delete EventHandler::getInstance(); // output-buffer delete OrxShell::ShellBuffer::getInstance(); SDL_QuitSubSystem(SDL_INIT_TIMER); ObjectListBase::debugAll(1); Preferences::getInstance()->save(); PRINT(3) ( "===================================================\n" \ "Thanks for playing orxonox.\n" \ "visit: http://www.orxonox.net for new versions.\n" \ "===================================================\n" \ ORXONOX_LICENSE_SHORT ); Orxonox::singletonRef = NULL; } /** * this is a singleton class to prevent duplicates */ Orxonox* Orxonox::singletonRef = NULL; // DANGEROUS void Orxonox::restart() { // int argc = this->argc; // char** argv = this->argv; // // Orxonox *orx = Orxonox::getInstance(); // // delete orx; // // orx = Orxonox::getInstance(); // // if((*orx).init(argc, argv) == -1) // { // PRINTF(1)("! Orxonox initialization failed\n"); // return; // } // // printf("finished inizialisation\n"); // orx->start(); } /** * @brief this finds the config file * @returns the new config-fileName * Since the config file varies from user to user and since one may want to specify different config files * for certain occasions or platforms this function finds the right config file for every occasion and stores * it's path and name into configfilename */ const std::string& Orxonox::getConfigFile () { File orxConfFile("orxonox.conf"); if (orxConfFile.isFile()) { this->configFileName = "orxonox.conf"; } else this->configFileName = File(DEFAULT_CONFIG_FILE).name(); PRINTF(3)("Parsed Config File: '%s'\n", this->configFileName.c_str()); return this->configFileName; } /** * initialize Orxonox with command line */ int Orxonox::init (int argc, char** argv, const std::string & name, int port) { this->argc = argc; this->argv = argv; this->serverName = name; this->port = port; // initialize the Config-file this->getConfigFile(); // windows must not write into stdout.txt and stderr.txt /*#ifdef __WIN32__ freopen( "CON", "w", stdout ); freopen( "CON", "w", stderr ); #endif*/ // initialize everything SDL_Init(0); if( initVideo() == -1) return -1; if( initResources () == -1) return -1; if( initSound() == -1) return -1; if( initInput() == -1) return -1; if( initNetworking () == -1) return -1; if( initMisc () == -1) return -1; return 0; } /** * initializes SDL and OpenGL */ int Orxonox::initVideo() { PRINTF(3)("> Initializing video\n"); GraphicsEngine::getInstance(); GraphicsEngine::getInstance()->initFromPreferences(); std::string iconName = ResourceManager::getFullName("pictures/fighter-top-32x32.bmp"); if (!iconName.empty()) { GraphicsEngine::getInstance()->setWindowName(PACKAGE_NAME " " PACKAGE_VERSION, iconName); } return 0; } /** * initializes the sound engine */ int Orxonox::initSound() { PRINT(3)("> Initializing sound\n"); // SDL_InitSubSystem(SDL_INIT_AUDIO); OrxSound::SoundEngine::getInstance(); OrxSound::SoundEngine::getInstance()->loadSettings(); OrxSound::SoundEngine::getInstance()->initAudio(); return 0; } /** * initializes input functions */ int Orxonox::initInput() { PRINT(3)("> Initializing input\n"); EventHandler::getInstance()->init(); EventHandler::getInstance()->subscribe(GraphicsEngine::getInstance(), ES_ALL, EV_VIDEO_RESIZE); return 0; } /** * initializes network system */ int Orxonox::initNetworking() { PRINT(3)("> Initializing networking\n"); std::string gameType = Preferences::getInstance()->getString( "game", "gameType", "" ); if( gameType == "multiplayer_client") { // we are a client State::setOnline(true); SharedNetworkData::getInstance()->setNodeType(NET_CLIENT); NetworkManager::getInstance()->createClient(this->serverName, port); } else if( gameType == "multiplayer_master_server") { // we are a master server State::setOnline(true); SharedNetworkData::getInstance()->setNodeType(NET_MASTER_SERVER); NetworkManager::getInstance()->createMasterServer(port); } else if( gameType == "multiplayer_proxy_server") { // we are a proxy server State::setOnline(true); SharedNetworkData::getInstance()->setNodeType(NET_PROXY_SERVER_ACTIVE); NetworkManager::getInstance()->createProxyServer(port); } return 0; } //#include "util/loading/dynamic_loader.h" /** * initializes and loads resource files */ int Orxonox::initResources() { PRINTF(3)("> Initializing resources\n"); PRINT(3)("initializing ResourceManager\n"); // init the resource manager std::string dataPath; if ((dataPath = Preferences::getInstance()->getString(CONFIG_SECTION_GENERAL, CONFIG_NAME_DATADIR, ""))!= "") { if (!ResourceManager::getInstance()->setDataDir(dataPath) && !ResourceManager::getInstance()->verifyDataDir(DEFAULT_DATA_DIR_CHECKFILE)) { PRINTF(1)("Data Could not be located in %s\n", dataPath.c_str()); } } while (!ResourceManager::getInstance()->verifyDataDir(DEFAULT_DATA_DIR_CHECKFILE)) { PRINTF(1)("The DataDirectory %s could not be verified\n\nh" \ "!!! Please Change in File %s Section %s Entry %s to a suitable value !!!\n", ResourceManager::getInstance()->getDataDir().c_str(), this->configFileName.c_str(), CONFIG_SECTION_GENERAL, CONFIG_NAME_DATADIR ); OrxGui::Gui* gui = new OrxGui::QtGuiDataDirFallback(argc, argv); gui->startGui(); if (gui->getState() == OrxGui::Gui::Quitting) return(-1); delete gui; ResourceManager::getInstance()->setDataDir(Preferences::getInstance()->getString(CONFIG_SECTION_GENERAL, CONFIG_NAME_DATADIR, "")); } //! @todo this is a hack and should be loadable std::string imageDir = ResourceManager::getInstance()->getFullName("maps"); ResourceManager::getInstance()->addImageDir(imageDir); imageDir = ResourceManager::getInstance()->getFullName("pictures"); ResourceManager::getInstance()->addImageDir(imageDir); // DynamicLoader::loadDyLib("libtest.so"); return 0; } /** * initializes miscelaneous features * @return -1 on failure */ int Orxonox::initMisc() { OrxShell::ShellBuffer::getInstance(); // start the collision detection engine CDEngine::getInstance(); return 0; } /** * starts the orxonox game or menu * here is the central orxonox state manager. There are currently two states * - menu * - game-play * both states manage their states themselfs again. */ void Orxonox::start() { this->gameLoader = GameLoader::getInstance(); if( this->port != -1) this->gameLoader->loadNetworkCampaign("worlds/DefaultNetworkCampaign.oxc"); else this->gameLoader->loadCampaign("worlds/DefaultCampaign.oxc"); /* start orxonox in single player mode */ // this->gameLoader->loadDebugCampaign(DEBUG_CAMPAIGN_0); this->gameLoader->init(); this->gameLoader->start(); } /** * handles sprecial events from localinput * @param event: an event not handled by the CommandNode */ // void Orxonox::graphicsHandler(SDL_Event* event) // { // // Handle special events such as reshape, quit, focus changes // switch (event->type) // { // case SDL_VIDEORESIZE: // GraphicsEngine* tmpGEngine = GraphicsEngine::getInstance(); // tmpGEngine->resolutionChanged(event->resize); // break; // } // } bool showGui = false; /********************************** *** ORXONOX MAIN STARTING POINT *** **********************************/ /** * * main function * * here the journey begins */ int main(int argc, char** argv) { CmdLinePrefsReader prefs; IniFilePrefsReader ini(File(DEFAULT_CONFIG_FILE).name()); Preferences::getInstance()->setUserIni(File(DEFAULT_CONFIG_FILE).name()); prefs.parse(argc, argv); if ( Preferences::getInstance()->getString("misc", "showLicenseAndExit", "") == "1" ) { PRINT(0)(ORXONOX_LICENSE_SHORT); return 0; } if ( Preferences::getInstance()->getString("misc", "bt-to-file", "1") == "1" ) { SignalHandler::getInstance()->doCatch( argv[0], "orxonox.backtrace" ); SignalHandler::getInstance()->registerCallback( EventHandler::releaseMouse, NULL ); } if( Preferences::getInstance()->getString("game", "showGui", "") == "1" ) showGui = true; else if( Preferences::getInstance()->getString( "game", "gameType", "" ) == "multiplayer_master_server" || Preferences::getInstance()->getString( "game", "gameType", "" ) == "multiplayer_proxy_server" || Preferences::getInstance()->getString( "game", "gameType", "" ) == "multiplayer_client" ) return startNetworkOrxonox(argc, argv); return startOrxonox(argc, argv, "", -1); } /** * starts orxonox in network mode * @param argc parameters count given to orxonox * @param argv parameters given to orxonox */ int startNetworkOrxonox(int argc, char** argv) { std::string gameType = Preferences::getInstance()->getString( "game", "gameType", "" ); if ( gameType == "multiplayer_client" ) { int port = Preferences::getInstance()->getInt( "game", "port", DEFAULT_ORXONOX_PORT ); std::string host = Preferences::getInstance()->getString( "game", "host", "" ); if ( host == "" ) { printf("You need to specify a host to connect to ( -H )\n"); return 1; } printf("Starting Orxonox as client: connecting to %s, on port %i\n", host.c_str(), port); startOrxonox(argc, argv, host.c_str(), port); } else if ( gameType == "multiplayer_master_server" ) { int port = Preferences::getInstance()->getInt( "game", "port", DEFAULT_ORXONOX_PORT ); printf("Starting Orxonox as server: listening on port %i\n", port); startOrxonox(argc, argv, "", port); } else if ( gameType == "multiplayer_proxy_server" ) { int port = Preferences::getInstance()->getInt( "game", "port", DEFAULT_ORXONOX_PORT ); printf("Starting Orxonox as proxy server: listening on port %i\n", port); startOrxonox(argc, argv, "", port); } return 1; } /** * starts orxonox * @param argc parameters count given to orxonox * @param argv parameters given to orxonox */ int startOrxonox(int argc, char** argv, const std::string & name, int port) { // checking for existence of the configuration-files, or if the lock file is still used if (showGui || (!File("./orxonox.conf").isFile() && !File(DEFAULT_CONFIG_FILE).isFile()) #if DEBUG_LEVEL <= 3 // developers do not need to see the GUI, when orxonox fails || ResourceManager::isFile(DEFAULT_LOCK_FILE) #endif ) { File lockFile(DEFAULT_LOCK_FILE); if (lockFile.isFile()) lockFile.remove(); // starting the GUI OrxGui::QtGui gui(argc, argv); gui.startGui(); if (gui.getState() & OrxGui::Gui::Quitting) return 0; } PRINT(0)(">>> Starting Orxonox <<<\n"); File(DEFAULT_LOCK_FILE).touch(); Orxonox *orx = Orxonox::getInstance(); if( orx->init(argc, argv, name, port) == -1) { PRINTF(1)("! Orxonox initialization failed\n"); return -1; } printf("finished inizialisation\n"); orx->start(); delete orx; File("~/.orxonox/orxonox.lock").remove(); return 0; }