00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "gStuff.h"
00029 #include "tSysTime.h"
00030 #include "tDirectories.h"
00031 #include "tLocale.h"
00032 #include "rViewport.h"
00033 #include "rConsole.h"
00034 #include "gGame.h"
00035 #include "gLogo.h"
00036 #include "gCommandLineJumpStart.h"
00037
00038 #include "eSoundMixer.h"
00039
00040 #include "rScreen.h"
00041 #include "rSysdep.h"
00042 #include "uInputQueue.h"
00043
00044 #include "rTexture.h"
00045 #include "tConfiguration.h"
00046 #include "tRecorder.h"
00047 #include "tCommandLine.h"
00048 #include "eAdvWall.h"
00049 #include "eGameObject.h"
00050 #include "uMenu.h"
00051 #include "ePlayer.h"
00052 #include "gLanguageMenu.h"
00053 #include "gAICharacter.h"
00054 #include "gCycle.h"
00055
00056 #include <stdio.h>
00057 #include <stdlib.h>
00058 #include <fstream>
00059
00060 #include "nServerInfo.h"
00061 #include "nSocket.h"
00062 #include "tRuby.h"
00063 #ifndef DEDICATED
00064 #include "rRender.h"
00065 #include "rSDL.h"
00066 #include <SDL_syswm.h>
00067
00068 static gCommandLineJumpStartAnalyzer sg_jumpStartAnalyzer;
00069 #endif
00070
00071 #ifndef DEDICATED
00072 #ifdef MACOSX
00073 #include "AAURLHandler.h"
00074 #include "version.h"
00075 #endif
00076 #endif
00077
00078
00079 class gMainCommandLineAnalyzer: public tCommandLineAnalyzer
00080 {
00081 public:
00082 bool daemon_;
00083 bool fullscreen_;
00084 bool windowed_;
00085 bool use_directx_;
00086 bool dont_use_directx_;
00087
00088 gMainCommandLineAnalyzer()
00089 {
00090 daemon_ = false;
00091 windowed_ = false;
00092 fullscreen_ = false;
00093 use_directx_ = false;
00094 dont_use_directx_ = false;
00095 }
00096
00097
00098 private:
00099 virtual bool DoAnalyze( tCommandLineParser & parser )
00100 {
00101 if ( parser.GetSwitch( "--daemon","-d") )
00102 {
00103 daemon_ = true;
00104 }
00105 else if ( parser.GetSwitch( "-fullscreen", "-f" ) )
00106 {
00107 fullscreen_=true;
00108 }
00109 else if ( parser.GetSwitch( "-window", "-w" ) || parser.GetSwitch( "-windowed") )
00110 {
00111 windowed_=true;
00112 }
00113
00114 #ifdef WIN32
00115 else if ( parser.GetSwitch( "+directx") )
00116 {
00117 use_directx_=true;
00118 }
00119 else if ( parser.GetSwitch( "-directx") )
00120 {
00121 dont_use_directx_=true;
00122 }
00123 #endif
00124 else
00125 {
00126 return false;
00127 }
00128
00129 return true;
00130 }
00131
00132 virtual void DoHelp( std::ostream & s )
00133 {
00134 #ifndef DEDICATED
00135 s << "-f, --fullscreen : start in fullscreen mode\n";
00136 s << "-w, --window, --windowed : start in windowed mode\n\n";
00137 #ifdef WIN32
00138 s << "+directx, -directx : enable/disable usage of DirectX for screen\n"
00139 << " initialisation under MS Windows\n\n";
00140 s << "\n\nYes, I know this looks ugly. Sorry about that.\n";
00141 #endif
00142 #else
00143 #ifndef WIN32
00144 s << "-d, --daemon : allow the dedicated server to run as a daemon\n"
00145 << " (will not poll for input on stdin)\n";
00146 #endif
00147 #endif
00148 }
00149 };
00150
00151 static gMainCommandLineAnalyzer commandLineAnalyzer;
00152
00153 static bool use_directx=true;
00154 #ifdef WIN32
00155 static tConfItem<bool> udx("USE_DIRECTX","makes use of the DirectX input "
00156 "fuctions; causes some graphic cards to fail to work (VooDoo 3,...)",
00157 use_directx);
00158 #endif
00159
00160 extern void exit_game_objects(eGrid *grid);
00161
00162 #ifndef DEDICATED
00163 static void welcome(){
00164 bool textOutBack = sr_textOut;
00165 sr_textOut = false;
00166
00167 #ifdef DEBUG_XXXX
00168 {
00169 for (int i = 20; i>=0; i--)
00170 {
00171 sr_ClearGL();
00172 {
00173 rTextField c(-.8,.6, .1, .1);
00174 tString s;
00175 s << ColorString(1,1,1);
00176 s << "Test";
00177 s << ColorString(1,0,0);
00178 s << "bla bla blubb blaa blaa blubbb blaaa blaaa blubbbb blaaaa blaaaa blubbbbb blaaaaa blaaaaa blubbbbbb blaaaaaa\n";
00179 c << s;
00180 }
00181 sr_SwapGL();
00182 }
00183 }
00184 #endif
00185
00186 REAL timeout = tSysTimeFloat() + .2;
00187 SDL_Event tEvent;
00188
00189 if (st_FirstUse)
00190 {
00191 st_FirstUse=false;
00192 sr_LoadDefaultConfig();
00193 textOutBack = sr_textOut;
00194 sr_textOut = false;
00195 gLogo::SetBig(false);
00196 gLogo::SetSpinning(true);
00197 }
00198 else
00199 {
00200 bool showSplash = true;
00201 #ifdef DEBUG
00202 showSplash = false;
00203 #endif
00204
00205
00206 eSoundMixer* mixer;
00207 mixer = eSoundMixer::GetMixer();
00208 mixer->SetMode(TITLE_TRACK);
00209 mixer->Update();
00210
00211
00212 static const char * splashSection = "SPLASH";
00213 if ( tRecorder::IsRunning() )
00214 {
00215 showSplash = false;
00216
00217
00218 if ( !tRecorder::Playback( splashSection, showSplash ) )
00219 showSplash = tRecorder::IsPlayingBack();
00220 }
00221
00222 #ifndef DEDICATED
00223 if ( sg_jumpStartAnalyzer.ShouldConnect() )
00224 {
00225 showSplash = false;
00226 gLogo::SetDisplayed(false);
00227 sg_jumpStartAnalyzer.Connect();
00228 }
00229 #endif
00230
00231 #ifdef MACOSX
00232 StartAAURLHandler();
00233 #endif
00234 tRecorder::Record( splashSection, showSplash );
00235
00236 if ( showSplash )
00237 {
00238 timeout = tSysTimeFloat() + 6;
00239
00240 uInputProcessGuard inputProcessGuard;
00241 while((!su_GetSDLInput(tEvent) || tEvent.type!=SDL_KEYDOWN) &&
00242 tSysTimeFloat() < timeout)
00243 {
00244 if ( sr_glOut )
00245 {
00246 sr_ResetRenderState(true);
00247 rViewport::s_viewportFullscreen.Select();
00248
00249 rSysDep::ClearGL();
00250
00251 uMenu::GenericBackground();
00252
00253 rSysDep::SwapGL();
00254 }
00255
00256 tAdvanceFrame();
00257 }
00258 }
00259
00260
00261 {
00262 uInputProcessGuard inputProcessGuard;
00263 while (su_GetSDLInput(tEvent));
00264 }
00265
00266 sr_textOut = textOutBack;
00267 return;
00268 }
00269
00270 if ( sr_glOut )
00271 {
00272 rSysDep::ClearGL();
00273
00274
00275 gLogo::Display();
00276 rSysDep::ClearGL();
00277 }
00278 rSysDep::SwapGL();
00279
00280 sg_LanguageMenu();
00281
00282
00283 {
00284 uInputProcessGuard inputProcessGuard;
00285 while (su_GetSDLInput(tEvent));
00286 }
00287
00288 timeout = tSysTimeFloat() + 10;
00289
00290 sr_UnlockSDL();
00291 uInputProcessGuard inputProcessGuard;
00292 while((!su_GetSDLInput(tEvent) || tEvent.type!=SDL_KEYDOWN) &&
00293 tSysTimeFloat() < timeout){
00294
00295 sr_ResetRenderState(true);
00296 rViewport::s_viewportFullscreen.Select();
00297
00298 if ( sr_glOut )
00299 {
00300 rSysDep::ClearGL();
00301
00302 uMenu::GenericBackground();
00303
00304 REAL w=16*2/640.0;
00305 REAL h=32*2/480.0;
00306
00307
00308
00309
00310 Color(1,1,1);
00311 DisplayText(0,.8,h,tOutput("$welcome_message_heading"), sr_fontError);
00312
00313 w/=2;
00314 h/=2;
00315
00316 rTextField c(-.8,.6, h, sr_fontError);
00317
00318
00319 c << tOutput("$welcome_message_intro");
00320
00321 c.SetIndent(12);
00322
00323 c << tOutput("$welcome_message_vendor") << gl_vendor << '\n';
00324 c << tOutput("$welcome_message_renderer") << gl_renderer << '\n';
00325 c << tOutput("$welcome_message_version") << gl_version << '\n';
00326
00327 c.SetIndent(0);
00328
00329 c << tOutput("$welcome_message_finish");
00330
00331 rSysDep::SwapGL();
00332 }
00333
00334 tAdvanceFrame();
00335 }
00336 sr_LockSDL();
00337
00338 sr_textOut = textOutBack;
00339 }
00340 #endif
00341
00342 void cleanup(eGrid *grid){
00343 static bool reentry=true;
00344 if (reentry){
00345 reentry=false;
00346 su_contInput=false;
00347
00348 exit_game_objects(grid);
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 #ifdef POWERPAK_DEB
00372 if (pp_out){
00373 PD_Quit();
00374 PP_Quit();
00375 }
00376 #endif
00377 nNetObject::ClearAll();
00378
00379 if (sr_glOut){
00380 rITexture::UnloadAll();
00381 }
00382
00383 sr_glOut=false;
00384 sr_ExitDisplay();
00385
00386 #ifndef DEDICATED
00387 sr_RendererCleanup();
00388 #endif
00389
00390 }
00391 }
00392
00393 #ifndef DEDICATED
00394 int filter(const SDL_Event *tEvent){
00395
00396 static bool recursion = false;
00397 if ( !recursion )
00398 {
00399 class RecursionGuard
00400 {
00401 public:
00402 RecursionGuard( bool& recursion )
00403 :recursion_( recursion )
00404 {
00405 recursion = true;
00406 }
00407
00408 ~RecursionGuard()
00409 {
00410 recursion_ = false;
00411 }
00412
00413 private:
00414 bool& recursion_;
00415 };
00416
00417 RecursionGuard guard( recursion );
00418
00419
00420 if ((tEvent->type==SDL_KEYDOWN && tEvent->key.keysym.sym==27 &&
00421 tEvent->key.keysym.mod & KMOD_SHIFT) ||
00422 (tEvent->type==SDL_KEYDOWN && tEvent->key.keysym.sym==113 &&
00423 tEvent->key.keysym.mod & KMOD_META) ||
00424 (tEvent->type==SDL_QUIT)){
00425
00426
00427
00428
00429 tRecorder::Record("END");
00430
00431 st_SaveConfig();
00432 uMenu::quickexit=true;
00433 return false;
00434 }
00435
00436 if(tEvent->type==SDL_MOUSEMOTION)
00437 if(tEvent->motion.x==sr_screenWidth/2 && tEvent->motion.y==sr_screenHeight/2)
00438 return 0;
00439 if (su_mouseGrab &&
00440 tEvent->type!=SDL_MOUSEBUTTONDOWN &&
00441 tEvent->type!=SDL_MOUSEBUTTONUP &&
00442 ((tEvent->motion.x>=sr_screenWidth-10 || tEvent->motion.x<=10) ||
00443 (tEvent->motion.y>=sr_screenHeight-10 || tEvent->motion.y<=10)))
00444 SDL_WarpMouse(sr_screenWidth/2,sr_screenHeight/2);
00445
00446
00447
00448 if (tEvent->type==SDL_ACTIVEEVENT)
00449 {
00450
00451 #ifdef MACOSX
00452 if(currentScreensetting.fullscreen ^ lastSuccess.fullscreen) return false;
00453 #endif
00454 int flags = SDL_APPINPUTFOCUS;
00455 if ( tEvent->active.gain && tEvent->active.state & flags )
00456 Activate(true);
00457 if ( !tEvent->active.gain && tEvent->active.state & flags )
00458 Activate(false);
00459 return false;
00460 }
00461
00462 if (su_prefetchInput){
00463 return su_StoreSDLEvent(*tEvent);
00464 }
00465
00466 }
00467
00468 return 1;
00469 }
00470 #endif
00471
00472
00473 void Update_netPlayer();
00474
00475 void sg_SetIcon()
00476 {
00477 #ifndef DEDICATED
00478 #ifndef MACOSX
00479 #ifdef WIN32
00480 SDL_SysWMinfo info;
00481 HICON icon;
00482
00483 SDL_VERSION( &info.version );
00484 if( SDL_GetWMInfo( &info ) )
00485 {
00486 icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( 1 ) );
00487 SetClassLong( info.window, GCL_HICON, (LONG) icon );
00488 }
00489 #else
00490 rSurface tex( "desktop/icons/medium/armagetronad.png" );
00491
00492
00493 if (tex.GetSurface())
00494 SDL_WM_SetIcon(tex.GetSurface(),NULL);
00495 #endif
00496 #endif
00497 #endif
00498 }
00499
00500 class gAutoStringArray
00501 {
00502 public:
00503 ~gAutoStringArray()
00504 {
00505 for ( std::vector< char * >::iterator i = strings.begin(); i != strings.end(); ++i )
00506 {
00507 free( *i );
00508 }
00509 }
00510
00511 char * Store( char const * s )
00512 {
00513 char * ret = strdup( s );
00514 strings.push_back( ret );
00515 return ret;
00516 }
00517 private:
00518 std::vector< char * > strings;
00519 };
00520
00521
00522
00523 void sg_PutEnv( char const * s )
00524 {
00525 static gAutoStringArray store;
00526 putenv( store.Store( s ) );
00527 }
00528
00529 int main(int argc,char **argv){
00530
00531
00532
00533 bool dedicatedServer = false;
00534
00535
00536
00537
00538
00539 try
00540 {
00541 tCommandLineData commandLine;
00542 commandLine.programVersion_ = &sn_programVersion;
00543
00544
00545
00546 if ( ! commandLine.Analyse(argc, argv) )
00547 return 0;
00548
00549
00550 {
00551
00552 const char * versionSection = "VERSION";
00553 tString version( sn_programVersion );
00554 tRecorder::Playback( versionSection, version );
00555 tRecorder::Record( versionSection, version );
00556 }
00557
00558 {
00559
00560 const char * dedicatedSection = "DEDICATED";
00561 if ( !tRecorder::PlaybackStrict( dedicatedSection, dedicatedServer ) )
00562 {
00563 #ifdef DEDICATED
00564 dedicatedServer = true;
00565 #endif
00566 }
00567 tRecorder::Record( dedicatedSection, dedicatedServer );
00568 }
00569
00570
00571
00572 #ifdef linux
00573
00574
00575
00576
00577
00578
00579
00580
00581 #endif
00582
00583 #ifdef WIN32
00584
00585 if (!use_directx && !getenv("SDL_VIDEODRIVER") ) {
00586 sg_PutEnv("SDL_VIDEODRIVER=windib");
00587 }
00588 #endif
00589
00590
00591
00592 #ifndef WIN32
00593 #ifdef DEBUG
00594 #define NOSOUND
00595 #endif
00596 #endif
00597
00598 #ifndef DEDICATED
00599 Uint32 flags = SDL_INIT_VIDEO;
00600 #ifdef DEBUG
00601 flags |= SDL_INIT_NOPARACHUTE;
00602 #endif // DEBUG
00603 if (SDL_Init(flags) < 0) {
00604 tERR_ERROR("Couldn't initialize SDL: " << SDL_GetError());
00605 }
00606 atexit(SDL_Quit);
00607
00608
00609 su_KeyInit();
00610
00611 #ifndef NOJOYSTICK
00612 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK))
00613 std::cout << "Error initializing joystick subsystem\n";
00614 else
00615 {
00616 #ifdef DEBUG
00617
00618 #endif // DEBUG
00619 su_JoystickInit();
00620 }
00621 #endif // NOJOYSTICK
00622 #endif // DEDICATED
00623
00624
00625 ePlayer::Init();
00626
00627 #ifdef HAVE_LIBRUBY
00628 tRuby::InitializeInterpreter();
00629 try {
00630 tRuby::Load(tDirectories::Data(), "scripts/initialize.rb");
00631 }
00632 catch (std::runtime_error & e) {
00633 std::cerr << e.what() << '\n';
00634 }
00635 #endif
00636
00637
00638 tLocale::Load("languages.txt");
00639
00640 st_LoadConfig();
00641
00642
00643 tRecorderSyncBase::GetDebugLevelPlayback();
00644
00645 if ( commandLineAnalyzer.fullscreen_ )
00646 currentScreensetting.fullscreen = true;
00647 if ( commandLineAnalyzer.windowed_ )
00648 currentScreensetting.fullscreen = false;
00649 if ( commandLineAnalyzer.use_directx_ )
00650 use_directx = true;
00651 if ( commandLineAnalyzer.dont_use_directx_ )
00652 use_directx = false;
00653
00654
00655 gAICharacter::LoadAll( aiPlayersConfig );
00656
00657 sg_LanguageInit();
00658 atexit(tLocale::Clear);
00659
00660 if ( commandLine.Execute() )
00661 {
00662 gCycle::PrivateSettings();
00663
00664 {
00665 std::ifstream t;
00666
00667 if ( !tDirectories::Config().Open( t, "settings.cfg" ) )
00668 {
00669
00670
00671
00672 tERR_ERROR( "Configuration files not found. Check your installation." );
00673
00674 }
00675 }
00676
00677 {
00678 std::ofstream s;
00679 if (! tDirectories::Var().Open( s, "scorelog.txt", std::ios::app ) )
00680 {
00681 char const * error = "var directory not writable or does not exist. It should reside inside your user data directory and should have been created automatically on first start, but something must have gone wrong."
00682 #ifdef WIN32
00683 " You can access your user data directory over one of the start menu entries we installed."
00684 #else
00685 " Your user data directory is subdirectory named .armagetronad in your home directory."
00686 #endif
00687 ;
00688
00689 tERR_ERROR( error );
00690 }
00691 }
00692
00693 {
00694 std::ifstream t;
00695
00696 if ( tDirectories::Data().Open( t, "moviepack/settings.cfg" ) )
00697 {
00698 sg_moviepackInstalled=true;
00699 }
00700 }
00701
00702 #ifndef DEDICATED
00703 sr_glOut=1;
00704
00705
00706 sr_glRendererInit();
00707
00708 SDL_SetEventFilter(&filter);
00709
00710
00711
00712 sg_SetIcon();
00713
00714 tConsole::RegisterMessageCallback(&uMenu::Message);
00715 tConsole::RegisterIdleCallback(&uMenu::IdleInput);
00716
00717 if (sr_InitDisplay()){
00718
00719 try
00720 {
00721 #ifdef HAVE_GLEW
00722
00723 {
00724 GLenum err = glewInit();
00725 if (GLEW_OK != err)
00726 {
00727
00728 throw tGenericException( (const char *)glewGetErrorString(err), "GLEW Error" );
00729 }
00730 con << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << "\n";
00731 }
00732 #endif // HAVE_GLEW
00733
00734
00735
00736
00737
00738 welcome();
00739
00740
00741
00742 sr_con.autoDisplayAtSwap=false;
00743
00744
00745
00746 gLogo::SetBig(false);
00747 gLogo::SetSpinning(true);
00748
00749 sn_bigBrotherString = renderer_identification + "VER=" + sn_programVersion + "\n\n";
00750
00751 #ifdef HAVE_LIBRUBY
00752 try {
00753
00754 tRuby::Load(tDirectories::Data(), "scripts/ai.rb");
00755 }
00756 catch (std::runtime_error & e) {
00757 std::cerr << e.what() << '\n';
00758 }
00759 #endif
00760
00761 MainMenu();
00762
00763
00764 for ( int i = se_PlayerNetIDs.Len()-1; i>=0; --i )
00765 se_PlayerNetIDs(i)->RemoveFromGame();
00766
00767 nNetObject::ClearAll();
00768
00769 rITexture::UnloadAll();
00770 sr_RendererCleanup();
00771 }
00772 catch (tException const & e)
00773 {
00774 gLogo::SetDisplayed(true);
00775 uMenu::SetIdle(NULL);
00776 sr_con.autoDisplayAtSwap=false;
00777
00778
00779 tConsole::Message( e.GetName(), e.GetDescription(), 20 );
00780 }
00781
00782 sr_ExitDisplay();
00783
00784
00785
00786 st_SaveConfig();
00787
00788
00789
00790
00791 SDL_QuitSubSystem(SDL_INIT_VIDEO);
00792 }
00793
00794 eSoundMixer::ShutDown();
00795
00796 SDL_Quit();
00797 #else // DEDICATED
00798 if (!commandLineAnalyzer.daemon_)
00799 sr_Unblock_stdin();
00800
00801 sr_glOut=0;
00802
00803
00804
00805 while (!uMenu::quickexit)
00806 sg_HostGame();
00807 #endif // DEDICATED
00808 nNetObject::ClearAll();
00809 nServerInfo::DeleteAll();
00810 }
00811
00812 ePlayer::Exit();
00813
00814 #ifdef HAVE_LIBRUBY
00815 tRuby::CleanupInterpreter();
00816 #endif
00817
00818
00819 }
00820 catch( tException const & e )
00821 {
00822 try
00823 {
00824 st_PresentError( e.GetName(), e.GetDescription() );
00825 }
00826 catch(...)
00827 {
00828 }
00829
00830 return 1;
00831 }
00832 catch ( std::exception & e )
00833 {
00834 try
00835 {
00836 st_PresentError("", e.what());
00837 }
00838 catch(...)
00839 {
00840 }
00841 }
00842 #ifdef _MSC_VER
00843 #pragma warning ( disable : 4286 )
00844
00845
00846 catch( tGenericException const & e )
00847 {
00848 try
00849 {
00850 st_PresentError( e.GetName(), e.GetDescription() );
00851 }
00852 catch(...)
00853 {
00854 }
00855
00856 return 1;
00857 }
00858 #endif
00859 catch(...)
00860 {
00861 return 1;
00862 }
00863
00864 return 0;
00865 }
00866
00867 #ifdef DEDICATED
00868
00869 static void st_Dummy(std::istream &s){tString rest; rest.ReadLine(s);}
00870 static tConfItemFunc st_Dummy10("MASTER_QUERY_INTERVAL", &st_Dummy);
00871 static tConfItemFunc st_Dummy11("MASTER_SAVE_INTERVAL", &st_Dummy);
00872 static tConfItemFunc st_Dummy12("MASTER_IDLE", &st_Dummy);
00873 static tConfItemFunc st_Dummy13("MASTER_PORT", &st_Dummy);
00874 #endif
00875
00876
00877