PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/stk-code-master/src/main.cpp

https://github.com/jeremiejig/paf-autostereoscopie-2014
C++ | 1622 lines | 1233 code | 126 blank | 263 comment | 339 complexity | c82c788ed20692938917acf8736a6cb7 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-4.0, LGPL-2.0, LGPL-3.0, GPL-2.0
  1. //
  2. // SuperTuxKart - a fun racing game with go-kart
  3. // Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
  4. // Copyright (C) 2011-2013 Joerg Henrichs, Marianne Gagnon
  5. //
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 3
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software
  18. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. /**
  20. * \mainpage SuperTuxKart developer documentation
  21. *
  22. * This document contains the developer documentation for SuperTuxKart,
  23. * including the list of modules, the list of classes, the API reference,
  24. * and some pages that describe in more depth some parts of the code/engine.
  25. *
  26. * \section Overview
  27. *
  28. * Here is an overview of the high-level interactions between modules :
  29. \dot
  30. digraph interaction {
  31. race -> modes
  32. race -> tracks
  33. race -> karts
  34. modes -> tracks
  35. modes -> karts
  36. tracks -> graphics
  37. karts -> graphics
  38. tracks -> items
  39. graphics -> irrlicht
  40. guiengine -> irrlicht
  41. states_screens -> guiengine
  42. states_screens -> input
  43. guiengine -> input
  44. karts->physics
  45. tracks->physics
  46. karts -> controller
  47. input->controller
  48. tracks -> animations
  49. physics -> animations
  50. }
  51. \enddot
  52. Note that this graph is only an approximation because the real one would be
  53. much too complicated :)
  54. \section Modules
  55. \li \ref addonsgroup :
  56. Handles add-ons that can be downloaded.
  57. \li \ref animations :
  58. This module manages interpolation-based animation (of position, rotation
  59. and/or scale)
  60. \li \ref audio :
  61. This module handles audio (sound effects and music).
  62. \li \ref challenges :
  63. This module handles the challenge system, which locks features (tracks, karts
  64. modes, etc.) until the user completes some task.
  65. \li \ref config :
  66. This module handles the user configuration, the supertuxkart configuration
  67. file (which contains options usually not edited by the player) and the input
  68. configuration file.
  69. \li \ref graphics :
  70. This module contains the core graphics engine, that is mostly a thin layer
  71. on top of irrlicht providing some additional features we need for STK
  72. (like particles, more scene node types, mesh manipulation tools, material
  73. management, etc...)
  74. \li \ref guiengine :
  75. Contains the generic GUI engine (contains the widgets and the backing logic
  76. for event handling, the skin, screens and dialogs). See module @ref states_screens
  77. for the actual STK GUI screens. Note that all input comes through this module
  78. too.
  79. \li \ref widgetsgroup :
  80. Contains the various types of widgets supported by the GUI engine.
  81. \li \ref input :
  82. Contains classes for input management (keyboard and gamepad)
  83. \li \ref io :
  84. Contains generic utility classes for file I/O (especially XML handling).
  85. \li \ref items :
  86. Defines the various collectibles and weapons of STK.
  87. \li \ref karts :
  88. Contains classes that deal with the properties, models and physics
  89. of karts.
  90. \li \ref controller :
  91. Contains kart controllers, which are either human players or AIs
  92. (this module thus contains the AIs)
  93. \li \ref modes :
  94. Contains the logic for the various game modes (race, follow the leader,
  95. battle, etc.)
  96. \li \ref physics :
  97. Contains various physics utilities.
  98. \li \ref race :
  99. Contains the race information that is conceptually above what you can find
  100. in group Modes. Handles highscores, grands prix, number of karts, which
  101. track was selected, etc.
  102. \li \ref states_screens :
  103. Contains the various screens and dialogs of the STK user interface,
  104. using the facilities of the guiengine module. Also contains the
  105. stack of menus and handles state management (in-game vs menu).
  106. \li \ref tracks :
  107. Contains information about tracks, namely drivelines, checklines and track
  108. objects.
  109. \li \ref tutorial :
  110. Work in progress
  111. */
  112. #ifdef WIN32
  113. # ifdef __CYGWIN__
  114. # include <unistd.h>
  115. # endif
  116. # define _WINSOCKAPI_
  117. # include <windows.h>
  118. # ifdef _MSC_VER
  119. # include <direct.h>
  120. # endif
  121. #else
  122. # include <unistd.h>
  123. #endif
  124. #include <stdexcept>
  125. #include <cstdio>
  126. #include <string>
  127. #include <cstring>
  128. #include <sstream>
  129. #include <algorithm>
  130. #include <IEventReceiver.h>
  131. #include "main_loop.hpp"
  132. #include "addons/addons_manager.hpp"
  133. #include "addons/inetwork_http.hpp"
  134. #include "addons/news_manager.hpp"
  135. #include "audio/music_manager.hpp"
  136. #include "audio/sfx_manager.hpp"
  137. #include "challenges/unlock_manager.hpp"
  138. #include "config/stk_config.hpp"
  139. #include "config/user_config.hpp"
  140. #include "config/player.hpp"
  141. #include "graphics/hardware_skinning.hpp"
  142. #include "graphics/irr_driver.hpp"
  143. #include "graphics/material_manager.hpp"
  144. #include "graphics/particle_kind_manager.hpp"
  145. #include "graphics/referee.hpp"
  146. #include "graphics/view_player.hpp"
  147. #include "guiengine/engine.hpp"
  148. #include "guiengine/event_handler.hpp"
  149. #include "input/input_manager.hpp"
  150. #include "input/device_manager.hpp"
  151. #include "input/wiimote_manager.hpp"
  152. #include "io/file_manager.hpp"
  153. #include "items/attachment_manager.hpp"
  154. #include "items/item_manager.hpp"
  155. #include "items/projectile_manager.hpp"
  156. #include "karts/controller/ai_base_controller.hpp"
  157. #include "karts/kart_properties.hpp"
  158. #include "karts/kart_properties_manager.hpp"
  159. #include "modes/demo_world.hpp"
  160. #include "modes/profile_world.hpp"
  161. #include "network/network_manager.hpp"
  162. #include "race/grand_prix_manager.hpp"
  163. #include "race/highscore_manager.hpp"
  164. #include "race/history.hpp"
  165. #include "race/race_manager.hpp"
  166. #include "replay/replay_play.hpp"
  167. #include "replay/replay_recorder.hpp"
  168. #include "states_screens/story_mode_lobby.hpp"
  169. #include "states_screens/state_manager.hpp"
  170. #include "states_screens/dialogs/message_dialog.hpp"
  171. #include "tracks/track.hpp"
  172. #include "tracks/track_manager.hpp"
  173. #include "utils/constants.hpp"
  174. #include "utils/leak_check.hpp"
  175. #include "utils/log.hpp"
  176. #include "utils/translation.hpp"
  177. static void cleanSuperTuxKart();
  178. // ============================================================================
  179. // gamepad visualisation screen
  180. // ============================================================================
  181. void gamepadVisualisation()
  182. {
  183. core::array<SJoystickInfo> irrlicht_gamepads;
  184. irr_driver->getDevice()->activateJoysticks(irrlicht_gamepads);
  185. struct Gamepad
  186. {
  187. s16 m_axis[SEvent::SJoystickEvent::NUMBER_OF_AXES];
  188. bool m_button_state[SEvent::SJoystickEvent::NUMBER_OF_BUTTONS];
  189. };
  190. #define GAMEPAD_COUNT 8 // const won't work
  191. class EventReceiver : public IEventReceiver
  192. {
  193. public:
  194. Gamepad m_gamepads[GAMEPAD_COUNT];
  195. EventReceiver()
  196. {
  197. for (int n=0; n<GAMEPAD_COUNT; n++)
  198. {
  199. Gamepad& g = m_gamepads[n];
  200. for (int i=0; i<SEvent::SJoystickEvent::NUMBER_OF_AXES; i++)
  201. g.m_axis[i] = 0;
  202. for (int i=0; i<SEvent::SJoystickEvent::NUMBER_OF_BUTTONS; i++)
  203. g.m_button_state[i] = false;
  204. }
  205. }
  206. virtual bool OnEvent (const irr::SEvent &event)
  207. {
  208. switch (event.EventType)
  209. {
  210. case EET_JOYSTICK_INPUT_EVENT :
  211. {
  212. const SEvent::SJoystickEvent& evt = event.JoystickEvent;
  213. if (evt.Joystick >= GAMEPAD_COUNT) return true;
  214. Gamepad& g = m_gamepads[evt.Joystick];
  215. for (int i=0; i<SEvent::SJoystickEvent::NUMBER_OF_AXES;i++)
  216. {
  217. g.m_axis[i] = evt.Axis[i];
  218. }
  219. for (int i=0; i<SEvent::SJoystickEvent::NUMBER_OF_BUTTONS;
  220. i++)
  221. {
  222. g.m_button_state[i] = evt.IsButtonPressed(i);
  223. }
  224. break;
  225. }
  226. case EET_KEY_INPUT_EVENT:
  227. {
  228. const SEvent::SKeyInput& evt = event.KeyInput;
  229. if (evt.PressedDown)
  230. {
  231. if (evt.Key == KEY_RETURN || evt.Key == KEY_ESCAPE ||
  232. evt.Key == KEY_SPACE)
  233. {
  234. exit(0);
  235. }
  236. }
  237. }
  238. default:
  239. // don't care about others
  240. break;
  241. }
  242. return true;
  243. }
  244. };
  245. EventReceiver* events = new EventReceiver();
  246. irr_driver->getDevice()->setEventReceiver(events);
  247. while (true)
  248. {
  249. if (!irr_driver->getDevice()->run()) break;
  250. video::IVideoDriver* driver = irr_driver->getVideoDriver();
  251. const core::dimension2du size = driver ->getCurrentRenderTargetSize();
  252. driver->beginScene(true, true, video::SColor(255,0,0,0));
  253. for (int n=0; n<GAMEPAD_COUNT; n++)
  254. {
  255. Gamepad& g = events->m_gamepads[n];
  256. const int MARGIN = 10;
  257. const int x = (n & 1 ? size.Width/2 + MARGIN : MARGIN );
  258. const int w = size.Width/2 - MARGIN*2;
  259. const int h = size.Height/(GAMEPAD_COUNT/2) - MARGIN*2;
  260. const int y = size.Height/(GAMEPAD_COUNT/2)*(n/2) + MARGIN;
  261. driver->draw2DRectangleOutline( core::recti(x, y, x+w, y+h) );
  262. const int btn_y = y + 5;
  263. const int btn_x = x + 5;
  264. const int BTN_SIZE =
  265. (w - 10)/SEvent::SJoystickEvent::NUMBER_OF_BUTTONS;
  266. for (int b=0; b<SEvent::SJoystickEvent::NUMBER_OF_BUTTONS; b++)
  267. {
  268. core::position2di pos(btn_x + b*BTN_SIZE, btn_y);
  269. core::dimension2di size(BTN_SIZE, BTN_SIZE);
  270. if (g.m_button_state[b])
  271. {
  272. driver->draw2DRectangle (video::SColor(255,255,0,0),
  273. core::recti(pos, size));
  274. }
  275. driver->draw2DRectangleOutline( core::recti(pos, size) );
  276. }
  277. const int axis_y = btn_y + BTN_SIZE + 5;
  278. const int axis_x = btn_x;
  279. const int axis_w = w - 10;
  280. const int axis_h = (h - BTN_SIZE - 15)
  281. / SEvent::SJoystickEvent::NUMBER_OF_AXES;
  282. for (int a=0; a<SEvent::SJoystickEvent::NUMBER_OF_AXES; a++)
  283. {
  284. const float rate = g.m_axis[a] / 32767.0f;
  285. core::position2di pos(axis_x, axis_y + a*axis_h);
  286. core::dimension2di size(axis_w, axis_h);
  287. const bool deadzone = (abs(g.m_axis[a]) < DEADZONE_JOYSTICK);
  288. core::recti fillbar(core::position2di(axis_x + axis_w/2,
  289. axis_y + a*axis_h),
  290. core::dimension2di( (int)(axis_w/2*rate),
  291. axis_h) );
  292. fillbar.repair(); // dimension may be negative
  293. driver->draw2DRectangle (deadzone ? video::SColor(255,255,0,0)
  294. : video::SColor(255,0,255,0),
  295. fillbar);
  296. driver->draw2DRectangleOutline( core::recti(pos, size) );
  297. }
  298. }
  299. driver->endScene();
  300. }
  301. } // gamepadVisualisation
  302. // ============================================================================
  303. /** Sets the Christmas flag (m_xmas_enabled), depending on currently set
  304. * Christ mode (m_xmas_mode)
  305. */
  306. void handleXmasMode()
  307. {
  308. bool xmas = false;
  309. switch(UserConfigParams::m_xmas_mode)
  310. {
  311. case 0:
  312. {
  313. int day, month;
  314. StkTime::getDate(&day, &month);
  315. // Christmat hats are shown between 17. of December
  316. // and 5th of January
  317. xmas = (month == 12 && day>=17) || (month == 1 && day <=5);
  318. break;
  319. }
  320. case 1: xmas = true; break;
  321. default: xmas = false; break;
  322. } // switch m_xmas_mode
  323. if(xmas)
  324. kart_properties_manager->setHatMeshName("christmas_hat.b3d");
  325. } // handleXmasMode
  326. // ----------------------------------------------------------------------------
  327. /** Prints help for command line options to stdout.
  328. */
  329. void cmdLineHelp(char* invocation)
  330. {
  331. Log::info("main",
  332. "Usage: %s [OPTIONS]\n\n"
  333. "Run SuperTuxKart, a racing game with go-kart that features"
  334. " the Tux and friends.\n\n"
  335. "Options:\n"
  336. " -N, --no-start-screen Immediately start race without showing a "
  337. "menu.\n"
  338. " -R, --race-now Same as -N but also skip the ready-set-go phase"
  339. " and the music.\n"
  340. " -t, --track NAME Start at track NAME (see --list-tracks).\n"
  341. " --gp NAME Start the specified Grand Prix.\n"
  342. " --stk-config FILE use ./data/FILE instead of "
  343. "./data/stk_config.xml\n"
  344. " -l, --list-tracks Show available tracks.\n"
  345. " -k, --numkarts NUM Number of karts on the racetrack.\n"
  346. " --kart NAME Use kart number NAME (see --list-karts).\n"
  347. " --ai=a,b,... Use the karts a, b, ... for the AI.\n"
  348. " --list-karts Show available karts.\n"
  349. " --laps N Define number of laps to N.\n"
  350. " --mode N N=1 novice, N=2 driver, N=3 racer.\n"
  351. " --type N N=0 Normal, N=1 Time trial, N=2 FTL\n"
  352. " --reverse Play track in reverse (if allowed)\n"
  353. // TODO: add back "--players" switch
  354. // " --players n Define number of players to between 1 and 4.\n"
  355. " -f, --fullscreen Select fullscreen display.\n"
  356. " -w, --windowed Windowed display (default).\n"
  357. " -s, --screensize WxH Set the screen size (e.g. 320x200).\n"
  358. " -v, --version Show version of SuperTuxKart.\n"
  359. " --trackdir DIR A directory from which additional tracks are "
  360. "loaded.\n"
  361. " --animations=n Play karts' animations (All: 2, Humans only: 1,"
  362. " Nobody: 0).\n"
  363. " --gfx=n Play other graphical effects like impact stars "
  364. "dance,\n"
  365. " water animations or explosions (Enable: 1, "
  366. "Disable: 0).\n"
  367. " --weather=n Show weather effects like rain or snow (0 or 1 "
  368. "as --gfx).\n"
  369. " --camera-style=n Flexible (0) or hard like v0.6 (1) kart-camera "
  370. "link.\n"
  371. " --profile-laps=n Enable automatic driven profile mode for n "
  372. "laps.\n"
  373. " --profile-time=n Enable automatic driven profile mode for n "
  374. "seconds.\n"
  375. " --no-graphics Do not display the actual race.\n"
  376. " --demo-mode t Enables demo mode after t seconds idle time in "
  377. "main menu.\n"
  378. " --demo-tracks t1,t2 List of tracks to be used in demo mode. No\n"
  379. " spaces are allowed in the track names.\n"
  380. " --demo-laps n Number of laps in a demo.\n"
  381. " --demo-karts n Number of karts to use in a demo.\n"
  382. " --demo-startrace Skip the ready-set-go phase (everywhere).\n"
  383. " --ghost Replay ghost data together with one player kart.\n"
  384. " --nbviews n Number of views of the display (PAF).\n"
  385. " --shader Will render via shader (soft by default).\n"
  386. " --angle n Distance between two camera (soft rendering).\n"
  387. // " --history Replay history file 'history.dat'.\n"
  388. // " --history=n Replay history file 'history.dat' using:\n"
  389. // " n=1: recorded positions\n"
  390. // " n=2: recorded key strokes\n"
  391. //" --server[=port] This is the server (running on the specified "
  392. // "port).\n"
  393. //" --client=ip This is a client, connect to the specified ip"
  394. // " address.\n"
  395. //" --port=n Port number to use.\n"
  396. //" --numclients=n Number of clients to wait for (server "
  397. // "only).\n"
  398. " --no-console Does not write messages in the console but to\n"
  399. " stdout.log.\n"
  400. " --console Write messages in the console and files\n"
  401. " -h, --help Show this help.\n"
  402. "\n"
  403. "You can visit SuperTuxKart's homepage at "
  404. "http://supertuxkart.sourceforge.net\n\n", invocation
  405. );
  406. } // cmdLineHelp
  407. //=============================================================================
  408. /** For base options that don't need much to be inited (and, in some cases,
  409. * that need to be read before initing stuff) - it only assumes that
  410. * user config is loaded (necessary to check for blacklisted screen
  411. * resolutions), but nothing else (esp. not kart_properties_manager and
  412. * track_manager, since their search path might be extended by command
  413. * line options).
  414. */
  415. int handleCmdLinePreliminary(int argc, char **argv)
  416. {
  417. int n;
  418. for(int i=1; i<argc; i++)
  419. {
  420. if(argv[i][0] != '-') continue;
  421. if (!strcmp(argv[i], "--help" ) ||
  422. !strcmp(argv[i], "-help" ) ||
  423. !strcmp(argv[i], "-h" ) )
  424. {
  425. cmdLineHelp(argv[0]);
  426. exit(0);
  427. }
  428. else if(!strcmp(argv[i], "--gamepad-visualisation") ||
  429. !strcmp(argv[i], "--gamepad-visualization") )
  430. {
  431. UserConfigParams::m_gamepad_visualisation=true;
  432. }
  433. else if ( !strcmp(argv[i], "--debug=memory") )
  434. {
  435. UserConfigParams::m_verbosity |= UserConfigParams::LOG_MEMORY;
  436. }
  437. else if ( !strcmp(argv[i], "--debug=addons") )
  438. {
  439. UserConfigParams::m_verbosity |= UserConfigParams::LOG_ADDONS;
  440. }
  441. else if ( !strcmp(argv[i], "--debug=gui") )
  442. {
  443. UserConfigParams::m_verbosity |= UserConfigParams::LOG_GUI;
  444. }
  445. else if ( !strcmp(argv[i], "--debug=flyable") )
  446. {
  447. UserConfigParams::m_verbosity |= UserConfigParams::LOG_FLYABLE;
  448. }
  449. else if ( !strcmp(argv[i], "--debug=misc") )
  450. {
  451. UserConfigParams::m_verbosity |= UserConfigParams::LOG_MISC;
  452. }
  453. else if ( sscanf(argv[i], "--xmas=%d", &n) )
  454. {
  455. UserConfigParams::m_xmas_mode = n;
  456. }
  457. else if( !strcmp(argv[i], "--no-console"))
  458. {
  459. UserConfigParams::m_log_errors_to_console=false;
  460. }
  461. else if( !strcmp(argv[i], "--console"))
  462. {
  463. UserConfigParams::m_log_errors_to_console=true;
  464. }
  465. else if( !strcmp(argv[i], "--log=nocolor"))
  466. {
  467. Log::disableColor();
  468. Log::verbose("main", "Colours disabled.\n");
  469. }
  470. else if(sscanf(argv[i], "--log=%d",&n)==1)
  471. {
  472. Log::setLogLevel(n);
  473. }
  474. else if ( !strcmp(argv[i], "--debug=all") )
  475. {
  476. UserConfigParams::m_verbosity |= UserConfigParams::LOG_ALL;
  477. }
  478. else if( (!strcmp(argv[i], "--stk-config")) && i+1<argc )
  479. {
  480. stk_config->load(file_manager->getDataFile(argv[i+1]));
  481. Log::info("main", "STK config will be read from %s.\n",argv[i+1] );
  482. i++;
  483. }
  484. else if( !strcmp(argv[i], "--trackdir") && i+1<argc )
  485. {
  486. TrackManager::addTrackSearchDir(argv[i+1]);
  487. i++;
  488. }
  489. else if( !strcmp(argv[i], "--kartdir") && i+1<argc )
  490. {
  491. KartPropertiesManager::addKartSearchDir(argv[i+1]);
  492. i++;
  493. }
  494. else if( !strcmp(argv[i], "--nbviews") && i+1<argc)
  495. {
  496. int nb;
  497. StringUtils::fromString(argv[i+1], nb);
  498. UserConfigParams::m_nbviews = nb;
  499. i++;
  500. }
  501. else if( !strcmp(argv[i], "--angle") && i+1<argc)
  502. {
  503. float nb;
  504. StringUtils::fromString(argv[i+1], nb);
  505. UserConfigParams::m_interocularDistance = nb;
  506. i++;
  507. }
  508. else if( !strcmp(argv[i], "--no-graphics") || !strncmp(argv[i], "--list-", 7) ||
  509. !strcmp(argv[i], "-l" ))
  510. {
  511. ProfileWorld::disableGraphics();
  512. UserConfigParams::m_log_errors_to_console=true;
  513. }
  514. #if !defined(WIN32) && !defined(__CYGWIN)
  515. else if ( !strcmp(argv[i], "--fullscreen") || !strcmp(argv[i], "-f"))
  516. {
  517. // Check that current res is not blacklisted
  518. std::ostringstream o;
  519. o << UserConfigParams::m_width << "x"
  520. << UserConfigParams::m_height;
  521. std::string res = o.str();
  522. if (std::find(UserConfigParams::m_blacklist_res.begin(),
  523. UserConfigParams::m_blacklist_res.end(),res)
  524. == UserConfigParams::m_blacklist_res.end())
  525. UserConfigParams::m_fullscreen = true;
  526. else
  527. Log::warn("main", "Resolution %s has been blacklisted, so it "
  528. "is not available!\n", res.c_str());
  529. }
  530. else if ( !strcmp(argv[i], "--windowed") || !strcmp(argv[i], "-w"))
  531. {
  532. UserConfigParams::m_fullscreen = false;
  533. }
  534. #endif
  535. else if ( (!strcmp(argv[i], "--screensize") || !strcmp(argv[i], "-s") )
  536. && i+1<argc)
  537. {
  538. //Check if fullscreen and new res is blacklisted
  539. int width, height;
  540. if (sscanf(argv[i+1], "%dx%d", &width, &height) == 2)
  541. {
  542. std::ostringstream o;
  543. o << width << "x" << height;
  544. std::string res = o.str();
  545. if (!UserConfigParams::m_fullscreen ||
  546. std::find(UserConfigParams::m_blacklist_res.begin(),
  547. UserConfigParams::m_blacklist_res.end(),res) ==
  548. UserConfigParams::m_blacklist_res.end())
  549. {
  550. UserConfigParams::m_prev_width =
  551. UserConfigParams::m_width = width;
  552. UserConfigParams::m_prev_height =
  553. UserConfigParams::m_height = height;
  554. Log::verbose("main", "You choose to use %dx%d.\n",
  555. (int)UserConfigParams::m_width,
  556. (int)UserConfigParams::m_height );
  557. }
  558. else
  559. Log::warn("main", "Resolution %s has been blacklisted, so "
  560. "it is not available!\n", res.c_str());
  561. i++;
  562. }
  563. else
  564. {
  565. Log::fatal("main", "Error: --screensize argument must be "
  566. "given as WIDTHxHEIGHT");
  567. }
  568. }
  569. else if (strcmp(argv[i], "--version") == 0 ||
  570. strcmp(argv[i], "-v" ) == 0 )
  571. {
  572. Log::info("main", "==============================");
  573. Log::info("main", "SuperTuxKart, %s.", STK_VERSION ) ;
  574. #ifdef SVNVERSION
  575. Log::info("main", "SuperTuxKart, SVN revision number '%s'.",
  576. SVNVERSION ) ;
  577. #endif
  578. // IRRLICHT_VERSION_SVN
  579. Log::info("main", "Irrlicht version %i.%i.%i (%s)",
  580. IRRLICHT_VERSION_MAJOR , IRRLICHT_VERSION_MINOR,
  581. IRRLICHT_VERSION_REVISION, IRRLICHT_SDK_VERSION );
  582. Log::info("main", "==============================");
  583. } // --verbose or -v
  584. }
  585. return 0;
  586. } // handleCmdLinePreliminary
  587. // ============================================================================
  588. /** Handles command line options.
  589. * \param argc Number of command line options
  590. * \param argv Command line options.
  591. */
  592. int handleCmdLine(int argc, char **argv)
  593. {
  594. int n;
  595. char s[1024];
  596. for(int i=1; i<argc; i++)
  597. {
  598. if(!strcmp(argv[i], "--gamepad-debug"))
  599. {
  600. UserConfigParams::m_gamepad_debug=true;
  601. }
  602. else if (!strcmp(argv[i], "--wiimote-debug"))
  603. {
  604. UserConfigParams::m_wiimote_debug = true;
  605. }
  606. else if (!strcmp(argv[i], "--tutorial-debug"))
  607. {
  608. UserConfigParams::m_tutorial_debug = true;
  609. }
  610. else if(sscanf(argv[i], "--track-debug=%d",&n)==1)
  611. {
  612. UserConfigParams::m_track_debug=n;
  613. }
  614. else if(!strcmp(argv[i], "--track-debug"))
  615. {
  616. UserConfigParams::m_track_debug=1;
  617. }
  618. else if(!strcmp(argv[i], "--material-debug"))
  619. {
  620. UserConfigParams::m_material_debug = true;
  621. }
  622. else if(!strcmp(argv[i], "--ftl-debug"))
  623. {
  624. UserConfigParams::m_ftl_debug = true;
  625. }
  626. else if(UserConfigParams::m_artist_debug_mode &&
  627. !strcmp(argv[i], "--camera-wheel-debug"))
  628. {
  629. UserConfigParams::m_camera_debug=2;
  630. }
  631. else if(UserConfigParams::m_artist_debug_mode &&
  632. !strcmp(argv[i], "--camera-debug"))
  633. {
  634. UserConfigParams::m_camera_debug=1;
  635. }
  636. else if(UserConfigParams::m_artist_debug_mode &&
  637. !strcmp(argv[i], "--physics-debug"))
  638. {
  639. UserConfigParams::m_physics_debug=1;
  640. }
  641. else if(!strcmp(argv[i], "--kartsize-debug"))
  642. {
  643. for(unsigned int i=0;
  644. i<kart_properties_manager->getNumberOfKarts(); i++)
  645. {
  646. const KartProperties *km =
  647. kart_properties_manager->getKartById(i);
  648. Log::info("main", "%s:\t%swidth: %f length: %f height: %f "
  649. "mesh-buffer count %d",
  650. km->getIdent().c_str(),
  651. (km->getIdent().size()<7) ? "\t" : "",
  652. km->getMasterKartModel().getWidth(),
  653. km->getMasterKartModel().getLength(),
  654. km->getMasterKartModel().getHeight(),
  655. km->getMasterKartModel().getModel()
  656. ->getMeshBufferCount());
  657. }
  658. }
  659. else if(UserConfigParams::m_artist_debug_mode &&
  660. !strcmp(argv[i], "--check-debug"))
  661. {
  662. UserConfigParams::m_check_debug=true;
  663. }
  664. else if(!strcmp(argv[i], "--slipstream-debug"))
  665. {
  666. UserConfigParams::m_slipstream_debug=true;
  667. }
  668. else if(!strcmp(argv[i], "--rendering-debug"))
  669. {
  670. UserConfigParams::m_rendering_debug=true;
  671. }
  672. else if(!strcmp(argv[i], "--ai-debug"))
  673. {
  674. AIBaseController::enableDebug();
  675. }
  676. else if(sscanf(argv[i], "--server=%d",&n)==1)
  677. {
  678. network_manager->setMode(NetworkManager::NW_SERVER);
  679. UserConfigParams::m_server_port = n;
  680. }
  681. else if( !strcmp(argv[i], "--server") )
  682. {
  683. network_manager->setMode(NetworkManager::NW_SERVER);
  684. }
  685. else if( sscanf(argv[i], "--port=%d", &n) )
  686. {
  687. UserConfigParams::m_server_port=n;
  688. }
  689. else if( sscanf(argv[i], "--client=%1023s", s) )
  690. {
  691. network_manager->setMode(NetworkManager::NW_CLIENT);
  692. UserConfigParams::m_server_address=s;
  693. }
  694. else if ( sscanf(argv[i], "--gfx=%d", &n) )
  695. {
  696. if (n)
  697. {
  698. UserConfigParams::m_graphical_effects = true;
  699. }
  700. else
  701. {
  702. UserConfigParams::m_graphical_effects = false;
  703. }
  704. }
  705. else if ( sscanf(argv[i], "--weather=%d", &n) )
  706. {
  707. if (n)
  708. {
  709. UserConfigParams::m_weather_effects = true;
  710. }
  711. else
  712. {
  713. UserConfigParams::m_weather_effects = false;
  714. }
  715. }
  716. else if ( sscanf(argv[i], "--animations=%d", &n) )
  717. {
  718. UserConfigParams::m_show_steering_animations = n;
  719. }
  720. else if ( sscanf(argv[i], "--camera-style=%d", &n) )
  721. {
  722. UserConfigParams::m_camera_style = n;
  723. }
  724. else if( (!strcmp(argv[i], "--kart") && i+1<argc ))
  725. {
  726. unlock_manager->setCurrentSlot(UserConfigParams::m_all_players[0]
  727. .getUniqueID() );
  728. if (!unlock_manager->getCurrentSlot()->isLocked(argv[i+1]))
  729. {
  730. const KartProperties *prop =
  731. kart_properties_manager->getKart(argv[i+1]);
  732. if(prop)
  733. {
  734. UserConfigParams::m_default_kart = argv[i+1];
  735. // if a player was added with -N, change its kart.
  736. // Otherwise, nothing to do, kart choice will be picked
  737. // up upon player creation.
  738. if (StateManager::get()->activePlayerCount() > 0)
  739. {
  740. race_manager->setLocalKartInfo(0, argv[i+1]);
  741. }
  742. Log::verbose("main", "You chose to use kart '%s'.",
  743. argv[i+1] ) ;
  744. i++;
  745. }
  746. else
  747. {
  748. Log::warn("main", "Kart '%s' not found, ignored.",
  749. argv[i+1]);
  750. i++; // ignore the next parameter, otherwise STK will abort
  751. }
  752. }
  753. else // kart locked
  754. {
  755. Log::warn("main", "Kart '%s' has not been unlocked yet.",
  756. argv[i+1]);
  757. Log::warn("main",
  758. "Use --list-karts to list available karts.");
  759. return 0;
  760. } // if kart locked
  761. }
  762. else if( sscanf(argv[i], "--ai=%1023s", s)==1)
  763. {
  764. const std::vector<std::string> l=
  765. StringUtils::split(std::string(s),',');
  766. race_manager->setDefaultAIKartList(l);
  767. // Add 1 for the player kart
  768. race_manager->setNumKarts(l.size()+1);
  769. }
  770. else if( (!strcmp(argv[i], "--mode") && i+1<argc ))
  771. {
  772. int n = atoi(argv[i+1]);
  773. if(n<0 || n>RaceManager::DIFFICULTY_LAST)
  774. Log::warn("main", "Invalid difficulty '%s' - ignored.\n",
  775. argv[i+1]);
  776. else
  777. race_manager->setDifficulty(RaceManager::Difficulty(n));
  778. i++;
  779. }
  780. else if( (!strcmp(argv[i], "--type") && i+1<argc ))
  781. {
  782. switch (atoi(argv[i+1]))
  783. {
  784. case 0: race_manager
  785. ->setMinorMode(RaceManager::MINOR_MODE_NORMAL_RACE);
  786. break;
  787. case 1: race_manager
  788. ->setMinorMode(RaceManager::MINOR_MODE_TIME_TRIAL);
  789. break;
  790. case 2: race_manager
  791. ->setMinorMode(RaceManager::MINOR_MODE_FOLLOW_LEADER);
  792. break;
  793. default:
  794. Log::warn("main", "Invalid race type '%d' - ignored.",
  795. atoi(argv[i+1]));
  796. }
  797. i++;
  798. }
  799. else if( !strcmp(argv[i], "--reverse"))
  800. {
  801. race_manager->setReverseTrack(true);
  802. }
  803. else if( (!strcmp(argv[i], "--track") || !strcmp(argv[i], "-t"))
  804. && i+1<argc )
  805. {
  806. unlock_manager->setCurrentSlot(UserConfigParams::m_all_players[0]
  807. .getUniqueID() );
  808. if (!unlock_manager->getCurrentSlot()->isLocked(argv[i+1]))
  809. {
  810. race_manager->setTrack(argv[i+1]);
  811. Log::verbose("main", "You choose to start in track '%s'.",
  812. argv[i+1] );
  813. Track* t = track_manager->getTrack(argv[i+1]);
  814. if (t == NULL)
  815. {
  816. Log::warn("main", "Can't find track named '%s'.",
  817. argv[i+1]);
  818. }
  819. else if (t->isArena())
  820. {
  821. //if it's arena, don't create ai karts
  822. const std::vector<std::string> l;
  823. race_manager->setDefaultAIKartList(l);
  824. // Add 1 for the player kart
  825. race_manager->setNumKarts(1);
  826. race_manager->setMinorMode(RaceManager::MINOR_MODE_3_STRIKES);
  827. }
  828. else if(t->isSoccer())
  829. {
  830. //if it's soccer, don't create ai karts
  831. const std::vector<std::string> l;
  832. race_manager->setDefaultAIKartList(l);
  833. // Add 1 for the player kart
  834. race_manager->setNumKarts(1);
  835. race_manager->setMinorMode(RaceManager::MINOR_MODE_SOCCER);
  836. }
  837. }
  838. else
  839. {
  840. Log::warn("main", "Track '%s' has not been unlocked yet.",
  841. argv[i+1]);
  842. Log::warn("main", "Use --list-tracks to list available "
  843. "tracks.");
  844. return 0;
  845. }
  846. i++;
  847. }
  848. else if( (!strcmp(argv[i], "--gp")) && i+1<argc)
  849. {
  850. race_manager->setMajorMode(RaceManager::MAJOR_MODE_GRAND_PRIX);
  851. const GrandPrixData *gp =
  852. grand_prix_manager->getGrandPrix(argv[i+1]);
  853. if (gp == NULL)
  854. {
  855. Log::warn("main", "There is no GP named '%s'.", argv[i+1]);
  856. return 0;
  857. }
  858. race_manager->setGrandPrix(*gp);
  859. i++;
  860. }
  861. else if( (!strcmp(argv[i], "--numkarts") || !strcmp(argv[i], "-k")) &&
  862. i+1<argc )
  863. {
  864. UserConfigParams::m_num_karts = atoi(argv[i+1]);
  865. if(UserConfigParams::m_num_karts > stk_config->m_max_karts)
  866. {
  867. Log::warn("main",
  868. "Number of karts reset to maximum number %d.",
  869. stk_config->m_max_karts);
  870. UserConfigParams::m_num_karts = stk_config->m_max_karts;
  871. }
  872. race_manager->setNumKarts( UserConfigParams::m_num_karts );
  873. Log::verbose("main", "%d karts will be used.",
  874. (int)UserConfigParams::m_num_karts);
  875. i++;
  876. }
  877. else if( !strcmp(argv[i], "--list-tracks") || !strcmp(argv[i], "-l") )
  878. {
  879. Log::info("main", " Available tracks:" );
  880. unlock_manager->setCurrentSlot(UserConfigParams::m_all_players[0]
  881. .getUniqueID() );
  882. for (size_t i = 0; i != track_manager->getNumberOfTracks(); i++)
  883. {
  884. const Track *track = track_manager->getTrack(i);
  885. const char * locked = "";
  886. if ( unlock_manager->getCurrentSlot()
  887. ->isLocked(track->getIdent()) )
  888. {
  889. locked = " (locked)";
  890. }
  891. Log::info("main", "%-18s: %ls %s",
  892. track->getIdent().c_str(),
  893. track->getName(), locked);
  894. //}
  895. }
  896. Log::info("main", "Use --track N to choose track.");
  897. exit(0);
  898. }
  899. else if( !strcmp(argv[i], "--list-karts") )
  900. {
  901. Log::info("main", " Available karts:");
  902. for (unsigned int i = 0;
  903. i < kart_properties_manager->getNumberOfKarts(); i++)
  904. {
  905. const KartProperties* KP =
  906. kart_properties_manager->getKartById(i);
  907. unlock_manager->setCurrentSlot(UserConfigParams::m_all_players[0]
  908. .getUniqueID() );
  909. const char * locked = "";
  910. if (unlock_manager->getCurrentSlot()->isLocked(KP->getIdent()))
  911. locked = "(locked)";
  912. Log::info("main", " %-10s: %ls %s", KP->getIdent().c_str(),
  913. KP->getName(), locked);
  914. }
  915. exit(0);
  916. }
  917. else if ( !strcmp(argv[i], "--no-start-screen")
  918. || !strcmp(argv[i], "-N") )
  919. {
  920. UserConfigParams::m_no_start_screen = true;
  921. }
  922. else if ( !strcmp(argv[i], "--race-now")
  923. || !strcmp(argv[i], "-R") )
  924. {
  925. UserConfigParams::m_no_start_screen = true;
  926. UserConfigParams::m_race_now = true;
  927. }
  928. else if ( !strcmp(argv[i], "--laps") && i+1<argc )
  929. {
  930. int laps = atoi(argv[i+1]);
  931. if (laps < 0)
  932. {
  933. Log::error("main", "Invalid number of laps: %s.\n", argv[i+1] );
  934. return 0;
  935. }
  936. else
  937. {
  938. Log::verbose("main", "You choose to have %d laps.", laps);
  939. race_manager->setNumLaps(laps);
  940. i++;
  941. }
  942. }
  943. else if( sscanf(argv[i], "--profile-laps=%d", &n)==1)
  944. {
  945. if (n < 0)
  946. {
  947. Log::error("main", "Invalid number of profile-laps: %i.\n", n );
  948. return 0;
  949. }
  950. else
  951. {
  952. Log::verbose("main", "Profiling %d laps.",n);
  953. UserConfigParams::m_no_start_screen = true;
  954. ProfileWorld::setProfileModeLaps(n);
  955. race_manager->setNumLaps(n);
  956. }
  957. }
  958. else if( sscanf(argv[i], "--profile-time=%d", &n)==1)
  959. {
  960. Log::verbose("main", "Profiling: %d seconds.", n);
  961. UserConfigParams::m_no_start_screen = true;
  962. ProfileWorld::setProfileModeTime((float)n);
  963. race_manager->setNumLaps(999999); // profile end depends on time
  964. }
  965. else if( !strcmp(argv[i], "--no-graphics") )
  966. {
  967. // Set default profile mode of 1 lap if we haven't already set one
  968. if (!ProfileWorld::isProfileMode()) {
  969. UserConfigParams::m_no_start_screen = true;
  970. ProfileWorld::setProfileModeLaps(1);
  971. race_manager->setNumLaps(1);
  972. }
  973. }
  974. else if( !strcmp(argv[i], "--ghost"))
  975. {
  976. ReplayPlay::create();
  977. }
  978. else if( sscanf(argv[i], "--history=%d", &n)==1)
  979. {
  980. history->doReplayHistory( (History::HistoryReplayMode)n);
  981. // Force the no-start screen flag, since this initialises
  982. // the player structures correctly.
  983. UserConfigParams::m_no_start_screen = true;
  984. }
  985. else if( !strcmp(argv[i], "--history") )
  986. {
  987. history->doReplayHistory(History::HISTORY_POSITION);
  988. // Force the no-start screen flag, since this initialises
  989. // the player structures correctly.
  990. UserConfigParams::m_no_start_screen = true;
  991. }
  992. else if( !strcmp(argv[i], "--demo-mode") && i+1<argc)
  993. {
  994. unlock_manager->setCurrentSlot(UserConfigParams::m_all_players[0]
  995. .getUniqueID() );
  996. float t;
  997. StringUtils::fromString(argv[i+1], t);
  998. DemoWorld::enableDemoMode(t);
  999. // The default number of laps is taken from ProfileWorld and
  1000. // is 0. So set a more useful default for demo mode.
  1001. DemoWorld::setNumLaps(2);
  1002. i++;
  1003. }
  1004. else if( !strcmp(argv[i], "--demo-laps") && i+1<argc)
  1005. {
  1006. // Note that we use a separate setting for demo mode to avoid the
  1007. // problem that someone plays a game, and in further demos then
  1008. // the wrong (i.e. last selected) number of laps would be used
  1009. DemoWorld::setNumLaps(atoi(argv[i+1]));
  1010. i++;
  1011. }
  1012. else if( !strcmp(argv[i], "--demo-karts") && i+1<argc)
  1013. {
  1014. // Note that we use a separate setting for demo mode to avoid the
  1015. // problem that someone plays a game, and in further demos then
  1016. // the wrong (i.e. last selected) number of karts would be used
  1017. DemoWorld::setNumKarts(atoi(argv[i+1]));
  1018. i++;
  1019. }
  1020. else if( !strcmp(argv[i], "--demo-tracks") && i+1<argc)
  1021. {
  1022. DemoWorld::setTracks(StringUtils::split(std::string(argv[i+1]),
  1023. ','));
  1024. i++;
  1025. }
  1026. else if ( !strcmp(argv[i], "--demo-startrace") )
  1027. {
  1028. UserConfigParams::m_race_now = true;
  1029. }
  1030. else if( !strcmp(argv[i], "--shader"))
  1031. {
  1032. ViewPlayer::switchSVAlg();
  1033. }
  1034. #ifdef ENABLE_WIIUSE
  1035. else if( !strcmp(argv[i], "--wii"))
  1036. {
  1037. WiimoteManager::enable();
  1038. }
  1039. #endif
  1040. // these commands are already processed in handleCmdLinePreliminary,
  1041. // but repeat this just so that we don't get error messages about
  1042. // unknown commands
  1043. else if( !strcmp(argv[i], "--stk-config")&& i+1<argc ) { i++; }
  1044. else if( !strcmp(argv[i], "--trackdir") && i+1<argc ) { i++; }
  1045. else if( !strcmp(argv[i], "--kartdir") && i+1<argc ) { i++; }
  1046. else if( !strcmp(argv[i], "--debug=memory" ) ) {}
  1047. else if( !strcmp(argv[i], "--debug=addons" ) ) {}
  1048. else if( !strcmp(argv[i], "--debug=gui" ) ) {}
  1049. else if( !strcmp(argv[i], "--debug=flyable") ) {}
  1050. else if( !strcmp(argv[i], "--debug=misc" ) ) {}
  1051. else if( !strcmp(argv[i], "--debug=all" ) ) {}
  1052. else if ( sscanf(argv[i], "--xmas=%d", &n) ) {}
  1053. else if( !strcmp(argv[i], "--log=nocolor" ) ) {}
  1054. else if( sscanf(argv[i], "--log=%d",&n )==1 ) {}
  1055. else if( !strcmp(argv[i], "--no-console" ) ) {}
  1056. else if( !strcmp(argv[i], "--console" ) ) {}
  1057. else if( !strcmp(argv[i], "--screensize") ||
  1058. !strcmp(argv[i], "-s") ) {i++;}
  1059. else if( !strcmp(argv[i], "--fullscreen") || !strcmp(argv[i], "-f")) {}
  1060. else if( !strcmp(argv[i], "--windowed") || !strcmp(argv[i], "-w")) {}
  1061. else if( !strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) {}
  1062. else if( !strcmp(argv[i], "--nbviews") && i+1<argc) { i++; }
  1063. else if( !strcmp(argv[i], "--angle") && i+1<argc) { i++; }
  1064. #ifdef __APPLE__
  1065. // on OS X, sometimes the Finder will pass a -psn* something parameter
  1066. // to the application
  1067. else if( strncmp(argv[i], "-psn", 3) == 0) {}
  1068. #endif
  1069. else
  1070. {
  1071. // invalid param needs to go to console
  1072. UserConfigParams::m_log_errors_to_console = true;
  1073. Log::error("main", "Invalid parameter: %s.\n", argv[i] );
  1074. cmdLineHelp(argv[0]);
  1075. cleanSuperTuxKart();
  1076. return 0;
  1077. }
  1078. } // for i <argc
  1079. if(UserConfigParams::m_no_start_screen)
  1080. unlock_manager->setCurrentSlot(UserConfigParams::m_all_players[0]
  1081. .getUniqueID() );
  1082. if(ProfileWorld::isProfileMode())
  1083. {
  1084. UserConfigParams::m_sfx = false; // Disable sound effects
  1085. UserConfigParams::m_music = false;// and music when profiling
  1086. }
  1087. return 1;
  1088. } // handleCmdLine
  1089. //=============================================================================
  1090. /** Initialises the minimum number of managers to get access to user_config.
  1091. */
  1092. void initUserConfig(char *argv[])
  1093. {
  1094. irr_driver = new IrrDriver();
  1095. file_manager = new FileManager(argv);
  1096. user_config = new UserConfig(); // needs file_manager
  1097. const bool config_ok = user_config->loadConfig();
  1098. if (UserConfigParams::m_language.toString() != "system")
  1099. {
  1100. #ifdef WIN32
  1101. std::string s=std::string("LANGUAGE=")
  1102. +UserConfigParams::m_language.c_str();
  1103. _putenv(s.c_str());
  1104. #else
  1105. setenv("LANGUAGE", UserConfigParams::m_language.c_str(), 1);
  1106. #endif
  1107. }
  1108. translations = new Translations(); // needs file_manager
  1109. stk_config = new STKConfig(); // in case of --stk-config
  1110. // command line parameters
  1111. user_config->postLoadInit();
  1112. if (!config_ok || UserConfigParams::m_all_players.size() == 0)
  1113. {
  1114. user_config->addDefaultPlayer();
  1115. user_config->saveConfig();
  1116. }
  1117. } // initUserConfig
  1118. //=============================================================================
  1119. void initRest()
  1120. {
  1121. stk_config->load(file_manager->getDataFile("stk_config.xml"));
  1122. // Now create the actual non-null device in the irrlicht driver
  1123. irr_driver->initDevice();
  1124. // Init GUI
  1125. IrrlichtDevice* device = irr_driver->getDevice();
  1126. video::IVideoDriver* driver = device->getVideoDriver();
  1127. if (UserConfigParams::m_gamepad_visualisation)
  1128. {
  1129. gamepadVisualisation();
  1130. exit(0);
  1131. }
  1132. GUIEngine::init(device, driver, StateManager::get());
  1133. // This only initialises the non-network part of the addons manager. The
  1134. // online section of the addons manager will be initialised from a
  1135. // separate thread running in network http.
  1136. news_manager = new NewsManager();
  1137. addons_manager = new AddonsManager();
  1138. INetworkHttp::create();
  1139. // Note that the network thread must be started after the assignment
  1140. // to network_http (since the thread might use network_http, otherwise
  1141. // a race condition can be introduced resulting in a crash).
  1142. INetworkHttp::get()->startNetworkThread();
  1143. music_manager = new MusicManager();
  1144. sfx_manager = new SFXManager();
  1145. // The order here can be important, e.g. KartPropertiesManager needs
  1146. // defaultKartProperties, which are defined in stk_config.
  1147. history = new History ();
  1148. ReplayRecorder::create();
  1149. material_manager = new MaterialManager ();
  1150. track_manager = new TrackManager ();
  1151. kart_properties_manager = new KartPropertiesManager();
  1152. projectile_manager = new ProjectileManager ();
  1153. powerup_manager = new PowerupManager ();
  1154. attachment_manager = new AttachmentManager ();
  1155. highscore_manager = new HighscoreManager ();
  1156. network_manager = new NetworkManager ();
  1157. KartPropertiesManager::addKartSearchDir(
  1158. file_manager->getAddonsFile("karts/"));
  1159. track_manager->addTrackSearchDir(
  1160. file_manager->getAddonsFile("tracks/"));
  1161. track_manager->loadTrackList();
  1162. music_manager->addMusicToTracks();
  1163. GUIEngine::addLoadingIcon(
  1164. irr_driver->getTexture(file_manager->getTextureFile("notes.png")) );
  1165. grand_prix_manager = new GrandPrixManager ();
  1166. // Consistency check for challenges, and enable all challenges
  1167. // that have all prerequisites fulfilled
  1168. grand_prix_manager->checkConsistency();
  1169. std::string file = file_manager->getTextureFile("cup_gold.png");
  1170. if(file.size()==0)
  1171. Log::fatal("main", "Can not find cup_gold.png, aborting.");
  1172. GUIEngine::addLoadingIcon( irr_driver->getTexture(file) );
  1173. race_manager = new RaceManager ();
  1174. // default settings for Quickstart
  1175. race_manager->setNumLocalPlayers(1);
  1176. race_manager->setNumLaps (3);
  1177. race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE);
  1178. race_manager->setMinorMode (RaceManager::MINOR_MODE_NORMAL_RACE);
  1179. race_manager->setDifficulty(
  1180. (RaceManager::Difficulty)(int)UserConfigParams::m_difficulty);
  1181. } // initRest
  1182. //=============================================================================
  1183. /** Frees all manager and their associated memory.
  1184. */
  1185. static void cleanSuperTuxKart()
  1186. {
  1187. delete main_loop;
  1188. irr_driver->updateConfigIfRelevant();
  1189. if(INetworkHttp::get())
  1190. INetworkHttp::get()->stopNetworkThread();
  1191. //delete in reverse order of what they were created in.
  1192. //see InitTuxkart()
  1193. Referee::cleanup();
  1194. if(ReplayPlay::get()) ReplayPlay::destroy();
  1195. if(race_manager) delete race_manager;
  1196. INetworkHttp::destroy();
  1197. if(news_manager) delete news_manager;
  1198. if(addons_manager) delete addons_manager;
  1199. if(network_manager) delete network_manager;
  1200. if(grand_prix_manager) delete grand_prix_manager;
  1201. if(highscore_manager) delete highscore_manager;
  1202. if(attachment_manager) delete attachment_manager;
  1203. ItemManager::removeTextures();
  1204. if(powerup_manager) delete powerup_manager;
  1205. if(projectile_manager) delete projectile_manager;
  1206. if(kart_properties_manager) delete kart_properties_manager;
  1207. if(track_manager) delete track_manager;
  1208. if(material_manager) delete material_manager;
  1209. if(history) delete history;
  1210. ReplayRecorder::destroy();
  1211. if(sfx_manager) delete sfx_manager;
  1212. if(music_manager) delete music_manager;
  1213. delete ParticleKindManager::get();
  1214. if(stk_config) delete stk_config;
  1215. if(user_config) delete user_config;
  1216. if(unlock_manager) delete unlock_manager;
  1217. if(translations) delete translations;
  1218. if(file_manager) delete file_manager;
  1219. if(irr_driver) delete irr_driver;
  1220. StateManager::deallocate();
  1221. GUIEngine::EventHandler::deallocate();
  1222. } // cleanSuperTuxKart
  1223. //=============================================================================
  1224. #ifdef BREAKPAD
  1225. bool ShowDumpResults(const wchar_t* dump_path,
  1226. const wchar_t* minidump_id,
  1227. void* context,
  1228. EXCEPTION_POINTERS* exinfo,
  1229. MDRawAssertionInfo* assertion,
  1230. bool succeeded)
  1231. {
  1232. wprintf(L"Path: %s id %s.\n", dump_path, minidump_id);
  1233. return succeeded;
  1234. }
  1235. #endif
  1236. #if defined(DEBUG) && defined(WIN32) && !defined(__CYGWIN__)
  1237. #pragma comment(linker, "/SUBSYSTEM:console")
  1238. #endif
  1239. int main(int argc, char *argv[] )
  1240. {
  1241. #ifdef BREAKPAD
  1242. google_breakpad::ExceptionHandler eh(L"C:\\Temp", NULL, ShowDumpResults,
  1243. NULL, google_breakpad::ExceptionHandler::HANDLER_ALL);
  1244. #endif
  1245. srand(( unsigned ) time( 0 ));
  1246. try {
  1247. // Init the minimum managers so that user config exists, then
  1248. // handle all command line options that do not need (or must
  1249. // not have) other managers initialised:
  1250. initUserConfig(argv); // argv passed so config file can be
  1251. // found more reliably
  1252. handleCmdLinePreliminary(argc, argv);
  1253. initRest();
  1254. // Windows 32 always redirects output
  1255. #ifndef WIN32
  1256. file_manager->redirectOutput();
  1257. #endif
  1258. input_manager = new InputManager ();
  1259. #ifdef ENABLE_WIIUSE
  1260. wiimote_manager = new WiimoteManager();
  1261. #endif
  1262. // Get into menu mode initially.
  1263. input_manager->setMode(InputManager::MENU);
  1264. main_loop = new MainLoop();
  1265. material_manager -> loadMaterial ();
  1266. GUIEngine::addLoadingIcon( irr_driver->getTexture(
  1267. file_manager->getGUIDir() + "options_video.png") );
  1268. kart_properties_manager -> loadAllKarts ();
  1269. handleXmasMode();
  1270. unlock_manager = new UnlockManager();
  1271. std::string file = file_manager->getTextureFile("gui_lock.png");
  1272. if(file.size()==0)
  1273. Log::fatal("main", "Can not find gui_lock.png, aborting.");
  1274. GUIEngine::addLoadingIcon( irr_driver->getTexture(file));
  1275. projectile_manager -> loadData ();
  1276. // Both item_manager and powerup_manager load models and therefore
  1277. // textures from the model directory. To avoid reading the
  1278. // materials.xml twice, we do this here once for both:
  1279. file_manager->pushTextureSearchPath(file_manager->getModelFile(""));
  1280. const std::string materials_file =
  1281. file_manager->getModelFile("materials.xml");
  1282. if(materials_file!="")
  1283. {
  1284. // Some of the materials might be needed later, so just add
  1285. // them all permanently (i.e. as shared). Adding them temporary
  1286. // will actually not be possible: powerup_manager adds some
  1287. // permanent icon materials, which would (with the current
  1288. // implementation) make the temporary materials permanent anyway.
  1289. material_manager->addSharedMaterial(materials_file);
  1290. }
  1291. Referee::init();
  1292. powerup_manager -> loadAllPowerups ();
  1293. ItemManager::loadDefaultItemMeshes();
  1294. GUIEngine::addLoadingIcon( irr_driver->getTexture(
  1295. file_manager->getGUIDir() + "gift.png") );
  1296. file_manager->popTextureSearchPath();
  1297. attachment_manager -> loadModels ();
  1298. GUIEngine::addLoadingIcon( irr_driver->getTexture(
  1299. file_manager->getGUIDir() + "banana.png") );
  1300. //handleCmdLine() needs InitTuxkart() so it can't be called first
  1301. if(!handleCmdLine(argc, argv)) exit(0);
  1302. addons_manager->checkInstalledAddons();
  1303. // Load addons.xml to get info about addons even when not
  1304. // allowed to access the internet
  1305. if (UserConfigParams::m_internet_status != INetworkHttp::IPERM_ALLOWED) {
  1306. std::string xml_file = file_manager->getAddonsFile("addons.xml");
  1307. if (file_manager->fileExists(xml_file)) {
  1308. const XMLNode *xml = new XMLNode (xml_file);
  1309. addons_manager->initOnline(xml);
  1310. }
  1311. }
  1312. if(!UserConfigParams::m_no_start_screen)
  1313. {
  1314. StateManager::get()->pushScreen(StoryModeLobbyScreen::getInstance());
  1315. #ifdef ENABLE_WIIUSE
  1316. // Show a dialog to allow connection of wiimotes. */
  1317. if(WiimoteManager::isEnabled())
  1318. {
  1319. wiimote_manager->askUserToConnectWiimotes();
  1320. }
  1321. #endif
  1322. if(UserConfigParams::m_internet_status ==
  1323. INetworkHttp::IPERM_NOT_ASKED)
  1324. {
  1325. class ConfirmServer :
  1326. public MessageDialog::IConfirmDialogListener
  1327. {
  1328. public:
  1329. virtual void onConfirm()
  1330. {
  1331. INetworkHttp::destroy();
  1332. UserConfigParams::m_internet_status =
  1333. INetworkHttp::IPERM_ALLOWED;
  1334. GUIEngine::ModalDialog::dismiss();
  1335. INetworkHttp::create();
  1336. // Note that the network thread must be started after
  1337. // the assignment to network_http (since the thread
  1338. // might use network_http, otherwise a race condition
  1339. // can be introduced resulting in a crash).
  1340. INetworkHttp::get()->startNetworkThread();
  1341. } // onConfirm
  1342. // --------------------------------------------------------
  1343. virtual void onCancel()
  1344. {
  1345. INetworkHttp::destroy();
  1346. UserConfigParams::m_internet_status =
  1347. INetworkHttp::IPERM_NOT_ALLOWED;
  1348. GUIEngine::ModalDialog::dismiss();
  1349. INetworkHttp::create();
  1350. INetworkHttp::get()->startNetworkThread();
  1351. } // onCancel
  1352. }; // ConfirmServer
  1353. new MessageDialog(_("SuperTuxKart may connect to a server "
  1354. "to download add-ons and notify you of updates. Would you "
  1355. "like this feature to be enabled? (To change this setting "
  1356. "at a later time, go to options, select tab "
  1357. "'User Interface', and edit \"Allow STK to connect to the "
  1358. "Internet\")."),
  1359. MessageDialog::MESSAGE_DIALOG_CONFIRM,
  1360. new ConfirmServer(), true);
  1361. }
  1362. }
  1363. else
  1364. {
  1365. InputDevice *device;
  1366. // Use keyboard 0 by default in --no-start-screen
  1367. device = input_manager->getDeviceList()->getKeyboard(0);
  1368. // Create player and associate player with keyboard
  1369. StateManager::get()->createActivePlayer(
  1370. UserConfigParams::m_all_players.get(0), device );
  1371. if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL)
  1372. {
  1373. Log::warn("main", "Kart '%s' is unknown so will use the "
  1374. "default kart.",
  1375. UserConfigParams::m_default_kart.c_str());
  1376. race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart.getDefaultValue());
  1377. }
  1378. else
  1379. {
  1380. // Set up race manager appropriately
  1381. race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart);
  1382. }
  1383. // ASSIGN should make sure that only input from assigned devices
  1384. // is read.
  1385. input_manager->getDeviceList()->setAssignMode(ASSIGN);
  1386. // Go straight to the race
  1387. StateManager::get()->enterGameState();
  1388. }
  1389. // If an important news message exists it is shown in a popup dialog.
  1390. const core::stringw important_message =
  1391. news_manager->getImportantMessage();
  1392. if(important_message!="")
  1393. {
  1394. new MessageDialog(important_message,
  1395. MessageDialog::MESSAGE_DIALOG_OK,
  1396. NULL, true);
  1397. } // if important_message
  1398. // Replay a race
  1399. // =============
  1400. if(history->replayHistory())
  1401. {
  1402. // This will setup the race manager etc.
  1403. history->Load();
  1404. network_manager->setupPlayerKartInfo();
  1405. race_manager->startNew(false);
  1406. main_loop->run();
  1407. // well, actually run() will never return, since
  1408. // it exits after replaying history (see history::GetNextDT()).
  1409. // So the next line is just to make this obvious here!
  1410. exit(-3);
  1411. }
  1412. // Initialise connection in case that a command line option was set
  1413. // configuring a client or server. Otherwise this function does nothing
  1414. // here (and will be called again from the network gui).
  1415. if(!network_manager->initialiseConnections())
  1416. {
  1417. Log::error("main", "Problems initialising network connections,\n"
  1418. "Running in non-network mode.");
  1419. }
  1420. // On the server start with the network information page for now
  1421. if(network_manager->getMode()==NetworkManager::NW_SERVER)
  1422. {
  1423. // TODO - network menu
  1424. //menu_manager->pushMenu(MENUID_NETWORK_GUI);
  1425. }
  1426. // Not replaying
  1427. // =============
  1428. if(!ProfileWorld::isProfileMode())
  1429. {
  1430. if(UserConfigParams::m_no_start_screen)
  1431. {
  1432. // Quickstart (-N)
  1433. // ===============
  1434. // all defaults are set in InitTuxkart()
  1435. network_manager->setupPlayerKartInfo();
  1436. race_manager->startNew(false);
  1437. }
  1438. }
  1439. else // profile
  1440. {
  1441. // Profiling
  1442. // =========
  1443. race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE);
  1444. race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
  1445. network_manager->setupPlayerKartInfo();
  1446. race_manager->startNew(false);
  1447. }
  1448. main_loop->run();
  1449. } // try
  1450. catch (std::exception &e)
  1451. {
  1452. Log::error("main", "Exception caught : %s.",e.what());
  1453. Log::error("main", "Aborting SuperTuxKart.");
  1454. }
  1455. /* Program closing...*/
  1456. if(user_config)
  1457. {
  1458. // In case that abort is triggered before user_config exists
  1459. if (UserConfigParams::m_crashed) UserConfigParams::m_crashed = false;
  1460. user_config->saveConfig();
  1461. }
  1462. #ifdef ENABLE_WIIUSE
  1463. if(wiimote_manager)
  1464. delete wiimote_manager;
  1465. #endif
  1466. // If the window was closed in the middle of a race, remove players,
  1467. // so we don't crash later when StateManager tries to access input devices.
  1468. StateManager::get()->resetActivePlayers();
  1469. if(input_manager) delete input_manager; // if early crash avoid delete NULL
  1470. cleanSuperTuxKart();
  1471. #ifdef DEBUG
  1472. MemoryLeaks::checkForLeaks();
  1473. #endif
  1474. #ifndef WIN32
  1475. if (user_config) //close logfiles
  1476. {
  1477. Log::closeOutputFiles();
  1478. #endif
  1479. fclose(stderr);
  1480. fclose(stdout);
  1481. #ifndef WIN32
  1482. }
  1483. #endif
  1484. return 0 ;
  1485. } // main
  1486. #ifdef WIN32
  1487. //routine for running under windows
  1488. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
  1489. {
  1490. return main(__argc, __argv);
  1491. }
  1492. #endif