2007-06-06 22:29:40 +03:00
// CMT.cpp : Defines the entry point for the console application.
//
2009-05-20 13:08:56 +03:00
# include "../stdafx.h"
2007-06-06 22:29:40 +03:00
# include <cmath>
2007-06-20 15:00:18 +03:00
# include <string>
2007-06-06 22:29:40 +03:00
# include <vector>
2008-07-27 20:07:37 +03:00
# include <queue>
2007-06-06 22:29:40 +03:00
# include <cmath>
2008-09-17 13:18:22 +03:00
# include <boost/algorithm/string.hpp>
2009-05-20 13:08:56 +03:00
# include <boost/filesystem/operations.hpp>
2008-07-25 20:28:28 +03:00
# include <boost/thread.hpp>
2008-12-21 21:17:35 +02:00
# include <SDL_mixer.h>
2008-07-25 20:28:28 +03:00
# include "SDL_Extensions.h"
2008-08-04 18:56:36 +03:00
# include "SDL_framerate.h"
# include "CGameInfo.h"
2010-04-06 11:59:24 +03:00
# include "mapHandler.h"
2009-05-20 13:08:56 +03:00
# include "../global.h"
2008-08-04 18:56:36 +03:00
# include "CPreGame.h"
2008-09-17 13:18:22 +03:00
# include "CCastleInterface.h"
2009-05-20 13:08:56 +03:00
# include "../CConsoleHandler.h"
2007-08-21 16:48:18 +03:00
# include "CCursorHandler.h"
2009-05-20 13:08:56 +03:00
# include "../lib/CGameState.h"
# include "../CCallback.h"
2007-11-19 00:58:28 +02:00
# include "CPlayerInterface.h"
2007-12-06 20:55:58 +02:00
# include "CAdvmapInterface.h"
2009-05-20 13:08:56 +03:00
# include "../hch/CBuildingHandler.h"
# include "../hch/CVideoHandler.h"
# include "../hch/CHeroHandler.h"
# include "../hch/CCreatureHandler.h"
# include "../hch/CSpellHandler.h"
# include "../hch/CMusicHandler.h"
2009-06-20 04:40:52 +03:00
# include "../hch/CVideoHandler.h"
2009-05-20 13:08:56 +03:00
# include "../hch/CLodHandler.h"
# include "../hch/CDefHandler.h"
# include "../hch/CGeneralTextHandler.h"
# include "Graphics.h"
# include "Client.h"
# include "CConfigHandler.h"
# include "../lib/Connection.h"
# include "../lib/VCMI_Lib.h"
2009-10-10 08:47:59 +03:00
# include "../lib/VCMIDirs.h"
2008-12-21 21:17:35 +02:00
# include <cstdlib>
2009-05-20 13:08:56 +03:00
# include "../lib/NetPacks.h"
2010-02-08 16:38:06 +02:00
# include "CMessage.h"
2010-05-31 23:38:14 +03:00
# include "../hch/CObjectHandler.h"
2009-12-03 06:01:14 +02:00
# ifdef _WIN32
2009-11-28 19:21:54 +02:00
# include "SDL_syswm.h"
2009-12-03 06:01:14 +02:00
# endif
2010-07-12 13:20:25 +03:00
# include <boost/foreach.hpp>
2010-08-01 17:04:48 +03:00
# include "../hch/CDefObjInfoHandler.h"
2008-12-21 21:17:35 +02:00
2009-02-08 17:39:26 +02:00
# if __MINGW32__
# undef main
# endif
2009-04-15 17:03:31 +03:00
/*
* CMT . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2009-07-31 23:10:22 +03:00
std : : string NAME_AFFIX = " client " ;
std : : string NAME = NAME_VER + std : : string ( " ( " ) + NAME_AFFIX + ' ) ' ; //application name
2009-08-07 01:36:51 +03:00
CGuiHandler GH ;
2009-11-01 03:15:16 +02:00
static CClient * client ;
2009-05-25 02:21:55 +03:00
SDL_Surface * screen = NULL , //main screen surface
* screen2 = NULL , //and hlp surface (used to store not-active interfaces layer)
* screenBuf = screen ; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
2009-12-28 06:08:24 +02:00
static boost : : thread * mainGUIThread ;
2009-04-11 04:32:50 +03:00
2009-07-18 06:13:13 +03:00
SystemOptions GDefaultOptions ;
2009-10-10 08:47:59 +03:00
VCMIDirs GVCMIDirs ;
2009-03-12 20:50:36 +02:00
std : : queue < SDL_Event * > events ;
2008-08-04 18:56:36 +03:00
boost : : mutex eventsM ;
2009-04-11 04:32:50 +03:00
2009-08-08 02:17:12 +03:00
static bool gOnlyAI = false ;
2010-03-21 00:17:19 +02:00
static bool setResolution = false ; //set by event handling thread after resolution is adjusted
2009-04-11 04:32:50 +03:00
2009-08-17 11:50:31 +03:00
void processCommand ( const std : : string & message ) ;
2009-05-17 07:14:30 +03:00
static void setScreenRes ( int w , int h , int bpp , bool fullscreen ) ;
2009-06-23 11:14:49 +03:00
void dispose ( ) ;
2009-06-24 09:56:36 +03:00
void playIntro ( ) ;
2009-11-01 03:15:16 +02:00
static void listenForEvents ( ) ;
2010-07-14 04:08:27 +03:00
void requestChangingResolution ( ) ;
2009-06-24 09:56:36 +03:00
2010-04-04 01:06:50 +03:00
# ifndef _WIN32
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# include <getopt.h>
# endif
2009-06-24 09:56:36 +03:00
void init ( )
{
timeHandler tmh , pomtime ;
# if SDL_BYTEORDER == SDL_BIG_ENDIAN
int rmask = 0xff000000 ; int gmask = 0x00ff0000 ; int bmask = 0x0000ff00 ; int amask = 0x000000ff ;
# else
int rmask = 0x000000ff ; int gmask = 0x0000ff00 ; int bmask = 0x00ff0000 ; int amask = 0xff000000 ;
# endif
CSDL_Ext : : std32bppSurface = SDL_CreateRGBSurface ( SDL_SWSURFACE , 1 , 1 , 32 , rmask , gmask , bmask , amask ) ;
tlog0 < < " \t Initializing minors: " < < pomtime . getDif ( ) < < std : : endl ;
2009-07-18 06:13:13 +03:00
{
//read system options
2010-02-24 15:03:36 +02:00
CLoadFile settings ( GVCMIDirs . UserPath + " /config/sysopts.bin " , false ) ;
2009-07-18 06:13:13 +03:00
if ( settings . sfile )
{
settings > > GDefaultOptions ;
}
else //file not found (probably, may be also some kind of access problem
{
tlog2 < < " Warning: Cannot read system options, default settings will be used. \n " ;
//Try to create file
tlog2 < < " VCMI will try to save default system options... \n " ;
GDefaultOptions . settingsChanged ( ) ;
}
}
THC tlog0 < < " \t Loading default system settings: " < < pomtime . getDif ( ) < < std : : endl ;
2009-06-24 09:56:36 +03:00
//initializing audio
// Note: because of interface button range, volume can only be a
// multiple of 11, from 0 to 99.
CGI - > soundh = new CSoundHandler ;
CGI - > soundh - > init ( ) ;
2009-07-18 06:13:13 +03:00
CGI - > soundh - > setVolume ( GDefaultOptions . soundVolume ) ;
2009-06-24 09:56:36 +03:00
CGI - > musich = new CMusicHandler ;
2009-08-22 16:59:15 +03:00
//CGI->musich->init();
//CGI->musich->setVolume(GDefaultOptions.musicVolume);
2009-06-24 09:56:36 +03:00
tlog0 < < " \t Initializing sound: " < < pomtime . getDif ( ) < < std : : endl ;
2010-02-04 17:50:59 +02:00
tlog0 < < " Initializing screen and sound handling: " < < tmh . getDif ( ) < < std : : endl ;
2009-06-24 09:56:36 +03:00
initDLL ( : : console , logfile ) ;
CGI - > setFromLib ( ) ;
CGI - > soundh - > initCreaturesSounds ( CGI - > creh - > creatures ) ;
CGI - > soundh - > initSpellsSounds ( CGI - > spellh - > spells ) ;
tlog0 < < " Initializing VCMI_Lib: " < < tmh . getDif ( ) < < std : : endl ;
pomtime . getDif ( ) ;
CGI - > curh = new CCursorHandler ;
CGI - > curh - > initCursor ( ) ;
CGI - > curh - > show ( ) ;
tlog0 < < " Screen handler: " < < pomtime . getDif ( ) < < std : : endl ;
pomtime . getDif ( ) ;
graphics = new Graphics ( ) ;
2009-07-06 22:41:27 +03:00
graphics - > loadHeroAnims ( ) ;
2009-06-24 09:56:36 +03:00
tlog0 < < " \t Main graphics: " < < tmh . getDif ( ) < < std : : endl ;
tlog0 < < " Initializing game graphics: " < < tmh . getDif ( ) < < std : : endl ;
CMessage : : init ( ) ;
tlog0 < < " Message handler: " < < tmh . getDif ( ) < < std : : endl ;
2009-08-17 11:50:31 +03:00
//CPG = new CPreGame(); //main menu and submenus
//tlog0<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
2009-06-24 09:56:36 +03:00
}
2009-04-14 15:47:09 +03:00
2010-04-04 01:06:50 +03:00
# ifndef _WIN32
static void prog_version ( void )
{
printf ( " %s \n " , NAME_VER ) ;
printf ( " data directory: %s \n " , DATA_DIR ) ;
printf ( " library directory: %s \n " , LIB_DIR ) ;
printf ( " binary directory: %s \n " , BIN_DIR ) ;
}
static void prog_help ( const char * progname )
{
printf ( " %s - A Heroes of Might and Magic 3 clone \n " , NAME_VER ) ;
printf ( " Copyright (C) 2007-2010 VCMI dev team - see AUTHORS file \n " ) ;
printf ( " This is free software; see the source for copying conditions. There is NO \n " ) ;
printf ( " warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \n " ) ;
printf ( " \n " ) ;
printf ( " Usage: \n " ) ;
printf ( " -h, --help display this help and exit \n " ) ;
printf ( " -v, --version display version information and exit \n " ) ;
}
# endif
# ifdef _WIN32
2008-06-30 03:06:41 +03:00
int _tmain ( int argc , _TCHAR * argv [ ] )
2008-08-04 18:56:36 +03:00
# else
2008-09-10 00:10:24 +03:00
int main ( int argc , char * * argv )
2008-08-04 18:56:36 +03:00
# endif
2009-02-08 17:39:26 +02:00
{
2010-04-04 01:06:50 +03:00
# ifndef _WIN32
struct option long_options [ ] = {
{ " help " , 0 , NULL , ' h ' } ,
{ " version " , 0 , NULL , ' v ' } ,
{ NULL , 0 , NULL , 0 }
} ;
while ( 1 ) {
int c ;
int option_index ;
c = getopt_long ( argc , argv , " hv " ,
long_options , & option_index ) ;
if ( c = = EOF )
break ;
else if ( c = = ' ? ' )
return - 1 ;
switch ( c ) {
case ' h ' :
prog_help ( argv [ 0 ] ) ;
return 0 ;
break ;
case ' v ' :
prog_version ( ) ;
return 0 ;
break ;
}
}
if ( optind < argc ) {
printf ( " Extra arguments: %s \n " , argv [ optind + + ] ) ;
return 1 ;
}
# endif
2010-01-29 22:52:45 +02:00
//Set environment vars to make window centered. Sometimes work, sometimes not. :/
2009-09-07 05:29:44 +03:00
putenv ( " SDL_VIDEO_WINDOW_POS " ) ;
putenv ( " SDL_VIDEO_CENTERED=1 " ) ;
2008-11-09 00:29:19 +02:00
tlog0 < < " Starting... " < < std : : endl ;
2009-06-24 09:56:36 +03:00
timeHandler total , pomtime ;
2008-11-15 15:44:32 +02:00
std : : cout . flags ( std : : ios : : unitbuf ) ;
2008-11-09 00:29:19 +02:00
logfile = new std : : ofstream ( " VCMI_Client_log.txt " ) ;
2009-06-23 11:14:49 +03:00
console = new CConsoleHandler ;
2009-08-17 11:50:31 +03:00
* console - > cb = boost : : bind ( & processCommand , _1 ) ;
2009-06-23 11:14:49 +03:00
console - > start ( ) ;
atexit ( dispose ) ;
2008-11-09 00:29:19 +02:00
tlog0 < < " Creating console and logfile: " < < pomtime . getDif ( ) < < std : : endl ;
conf . init ( ) ;
tlog0 < < " Loading settings: " < < pomtime . getDif ( ) < < std : : endl ;
2008-09-19 11:16:19 +03:00
tlog0 < < NAME < < std : : endl ;
2008-11-09 00:29:19 +02:00
2008-06-16 13:51:14 +03:00
srand ( time ( NULL ) ) ;
2009-08-17 11:50:31 +03:00
//CPG=NULL;
2009-06-24 09:56:36 +03:00
CGI = new CGameInfo ; //contains all global informations about game (texts, lodHandlers, map handler itp.)
2010-08-16 12:54:09 +03:00
2009-08-17 11:50:31 +03:00
if ( SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO ) )
2007-06-06 22:29:40 +03:00
{
2009-08-17 11:50:31 +03:00
tlog1 < < " Something was wrong: " < < SDL_GetError ( ) < < std : : endl ;
exit ( - 1 ) ;
2007-06-06 22:29:40 +03:00
}
2009-10-26 07:39:30 +02:00
atexit ( SDL_Quit ) ;
2009-08-17 11:50:31 +03:00
setScreenRes ( 800 , 600 , conf . cc . bpp , conf . cc . fullscreen ) ;
tlog0 < < " \t Initializing screen: " < < pomtime . getDif ( ) < < std : : endl ;
// Initialize video
CGI - > videoh = new CVideoPlayer ;
tlog0 < < " \t Initializing video: " < < pomtime . getDif ( ) < < std : : endl ;
//we can properly play intro only in the main thread, so we have to move loading to the separate thread
boost : : thread loading ( init ) ;
playIntro ( ) ;
SDL_FillRect ( screen , NULL , 0 ) ;
SDL_Flip ( screen ) ;
loading . join ( ) ;
tlog0 < < " Initialization of VCMI (together): " < < total . getDif ( ) < < std : : endl ;
CGI - > musich - > playMusic ( musicBase : : mainMenu , - 1 ) ;
2009-11-01 03:15:16 +02:00
2009-12-28 06:08:24 +02:00
GH . curInt = new CGPreGame ; //will set CGP pointer to itself
mainGUIThread = new boost : : thread ( & CGuiHandler : : run , boost : : ref ( GH ) ) ;
2009-08-17 11:50:31 +03:00
listenForEvents ( ) ;
2009-10-26 07:39:30 +02:00
return 0 ;
2007-06-07 20:45:56 +03:00
}
2008-09-17 13:18:22 +03:00
2009-08-17 11:50:31 +03:00
void processCommand ( const std : : string & message )
2008-09-17 13:18:22 +03:00
{
std : : istringstream readed ;
readed . str ( message ) ;
std : : string cn ; //command name
readed > > cn ;
int3 src , dst ;
2008-12-21 21:17:35 +02:00
// int heronum;//TODO use me
2008-09-17 13:18:22 +03:00
int3 dest ;
2009-04-04 22:26:41 +03:00
if ( LOCPLINT & & LOCPLINT - > cingconsole )
LOCPLINT - > cingconsole - > print ( message ) ;
2008-09-17 13:18:22 +03:00
if ( message = = std : : string ( " die, fool " ) )
2008-12-21 21:17:35 +02:00
exit ( EXIT_SUCCESS ) ;
2008-09-17 13:18:22 +03:00
else if ( cn = = std : : string ( " activate " ) )
{
int what ;
readed > > what ;
switch ( what )
{
case 0 :
2009-08-07 01:36:51 +03:00
GH . topInt ( ) - > activate ( ) ;
2008-09-17 13:18:22 +03:00
break ;
case 1 :
2010-02-20 15:24:38 +02:00
adventureInt - > activate ( ) ;
2008-09-17 13:18:22 +03:00
break ;
case 2 :
LOCPLINT - > castleInt - > activate ( ) ;
break ;
}
}
2009-08-22 16:59:15 +03:00
else if ( cn = = " redraw " )
{
GH . totalRedraw ( ) ;
}
2009-08-17 11:50:31 +03:00
else if ( cn = = " screen " )
{
tlog0 < < " Screenbuf points to " ;
if ( screenBuf = = screen )
tlog1 < < " screen " ;
else if ( screenBuf = = screen2 )
tlog1 < < " screen2 " ;
else
tlog1 < < " ?!? " ;
tlog1 < < std : : endl ;
SDL_SaveBMP ( screen , " Screen_c.bmp " ) ;
SDL_SaveBMP ( screen2 , " Screen2_c.bmp " ) ;
}
2008-11-16 03:06:15 +02:00
else if ( cn = = " save " )
{
std : : string fname ;
readed > > fname ;
client - > save ( fname ) ;
}
2009-08-17 11:50:31 +03:00
//else if(cn=="list")
//{
// if(CPG)
// for(int i = 0; i < CPG->ourScenSel->mapsel.ourGames.size(); i++)
// tlog0 << i << ".\t" << CPG->ourScenSel->mapsel.ourGames[i]->filename << std::endl;
//}
2009-01-11 00:08:18 +02:00
else if ( cn = = " load " )
{
2009-11-01 03:15:16 +02:00
// TODO: this code should end the running game and manage to call startGame instead
2009-01-11 00:08:18 +02:00
std : : string fname ;
readed > > fname ;
2009-11-01 03:15:16 +02:00
client - > loadGame ( fname ) ;
2009-01-11 00:08:18 +02:00
}
2009-08-17 11:50:31 +03:00
//else if(cn=="ln")
//{
// int num;
// readed >> num;
// std::string &name = CPG->ourScenSel->mapsel.ourGames[num]->filename;
// client->load(name.substr(0, name.size()-6));
//}
2009-08-27 11:04:32 +03:00
else if ( cn = = " resolution " | | cn = = " r " )
2009-02-01 22:31:41 +02:00
{
2009-08-01 22:25:12 +03:00
if ( LOCPLINT )
{
tlog1 < < " Resolution can be set only before starting the game. \n " ;
return ;
}
2009-02-01 22:31:41 +02:00
std : : map < std : : pair < int , int > , config : : GUIOptions > : : iterator j ;
int i = 1 , hlp = 1 ;
tlog4 < < " Available screen resolutions: \n " ;
for ( j = conf . guiOptions . begin ( ) ; j ! = conf . guiOptions . end ( ) ; j + + )
tlog4 < < i + + < < " . " < < j - > first . first < < " x " < < j - > first . second < < std : : endl ;
tlog4 < < " Type number from 1 to " < < i - 1 < < " to set appropriate resolution or 0 to cancel. \n " ;
std : : cin > > i ;
2009-06-02 01:31:11 +03:00
if ( i < 0 | | i > conf . guiOptions . size ( ) | | std : : cin . bad ( ) | | std : : cin . fail ( ) )
2009-02-09 18:18:48 +02:00
{
2009-06-02 01:31:11 +03:00
std : : cin . clear ( ) ;
2009-02-09 18:18:48 +02:00
tlog1 < < " Invalid resolution ID! Not a number between 0 and " < < conf . guiOptions . size ( ) < < " . No settings changed. \n " ;
}
2009-06-02 01:31:11 +03:00
else if ( ! i )
{
return ;
}
2009-02-01 22:31:41 +02:00
else
{
2009-02-09 18:18:48 +02:00
for ( j = conf . guiOptions . begin ( ) ; j ! = conf . guiOptions . end ( ) & & hlp + + < i ; j + + ) ; //move j to the i-th resolution info
2009-02-01 22:31:41 +02:00
conf . cc . resx = j - > first . first ;
conf . cc . resy = j - > first . second ;
tlog0 < < " Screen resolution set to " < < conf . cc . resx < < " x " < < conf . cc . resy < < " . It will be aplied when the game starts. \n " ;
}
}
2008-09-17 13:18:22 +03:00
else if ( message = = " get txt " )
{
boost : : filesystem : : create_directory ( " Extracted_txts " ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " Command accepted. Opening .lod file... \t " ;
2008-09-17 13:18:22 +03:00
CLodHandler * txth = new CLodHandler ;
2009-10-04 05:02:45 +03:00
txth - > init ( std : : string ( DATA_DIR " /Data/H3bitmap.lod " ) , " " ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " done. \n Scanning .lod file \n " ;
2008-09-17 13:18:22 +03:00
int curp = 0 ;
2008-10-18 14:41:24 +03:00
std : : string pattern = " .TXT " , pom ;
2008-09-17 13:18:22 +03:00
for ( int i = 0 ; i < txth - > entries . size ( ) ; i + + )
{
2008-10-18 14:41:24 +03:00
pom = txth - > entries [ i ] . nameStr ;
2008-09-17 13:18:22 +03:00
if ( boost : : algorithm : : find_last ( pom , pattern ) )
{
2009-10-04 05:02:45 +03:00
txth - > extractFile ( std : : string ( DATA_DIR " /Extracted_txts/ " ) + pom , pom ) ;
2008-09-17 13:18:22 +03:00
}
if ( i % 8 ) continue ;
int p2 = ( ( float ) i / ( float ) txth - > entries . size ( ) ) * ( float ) 100 ;
if ( p2 ! = curp )
{
curp = p2 ;
2008-09-19 11:16:19 +03:00
tlog0 < < " \r " < < curp < < " % " ;
2008-09-17 13:18:22 +03:00
}
}
2008-09-19 11:16:19 +03:00
tlog0 < < " \r Extracting done :) \n " ;
2008-09-17 13:18:22 +03:00
}
2009-07-31 23:10:22 +03:00
else if ( cn = = " crash " )
{
int * ptr = NULL ;
* ptr = 666 ;
//disaster!
}
2009-08-08 02:17:12 +03:00
else if ( cn = = " onlyai " )
{
gOnlyAI = true ;
}
2010-05-31 23:38:14 +03:00
else if ( cn = = " mp " & & adventureInt )
{
if ( const CGHeroInstance * h = dynamic_cast < const CGHeroInstance * > ( adventureInt - > selection ) )
tlog0 < < h - > movement < < " ; max: " < < h - > maxMovePoints ( true ) < < " / " < < h - > maxMovePoints ( false ) < < std : : endl ;
}
2010-07-12 13:20:25 +03:00
else if ( cn = = " bonuses " )
{
tlog0 < < " Bonuses of " < < adventureInt - > selection - > getHoverText ( ) < < std : : endl
< < adventureInt - > selection - > bonuses < < std : : endl ;
tlog0 < < " \n Inherited bonuses: \n " ;
TCNodes parents ;
adventureInt - > selection - > getParents ( parents ) ;
BOOST_FOREACH ( const CBonusSystemNode * parent , parents )
{
tlog0 < < " \n Bonuses from " < < typeid ( * parent ) . name ( ) < < std : : endl < < parent - > bonuses < < std : : endl ;
}
}
2010-07-24 14:46:04 +03:00
else if ( cn = = " not dialog " )
{
LOCPLINT - > showingDialog - > setn ( false ) ;
}
2008-10-19 02:20:48 +03:00
else if ( client & & client - > serv & & client - > serv - > connected ) //send to server
{
2009-04-04 22:26:41 +03:00
PlayerMessage pm ( LOCPLINT - > playerID , message ) ;
* client - > serv < < & pm ;
2008-10-19 02:20:48 +03:00
}
2009-04-14 15:47:09 +03:00
}
2009-06-24 09:56:36 +03:00
//plays intro, ends when intro is over or button has been pressed (handles events)
void playIntro ( )
{
if ( CGI - > videoh - > openAndPlayVideo ( " 3DOLOGO.SMK " , 60 , 40 , screen , true ) )
{
CGI - > videoh - > openAndPlayVideo ( " AZVS.SMK " , 60 , 80 , screen , true ) ;
}
}
2009-06-23 11:14:49 +03:00
void dispose ( )
{
delete logfile ;
2009-10-26 07:39:30 +02:00
if ( console )
delete console ;
2009-06-23 11:14:49 +03:00
}
2009-05-17 07:14:30 +03:00
static void setScreenRes ( int w , int h , int bpp , bool fullscreen )
2009-08-11 19:05:33 +03:00
{
2010-08-05 14:02:18 +03:00
// VCMI will only work with 2, 3 or 4 bytes per pixel
amax ( bpp , 16 ) ;
amin ( bpp , 32 ) ;
2009-05-17 07:14:30 +03:00
// Try to use the best screen depth for the display
2009-07-16 02:58:47 +03:00
int suggestedBpp = SDL_VideoModeOK ( w , h , bpp , SDL_SWSURFACE | ( fullscreen ? SDL_FULLSCREEN : 0 ) ) ;
if ( suggestedBpp = = 0 )
{
2009-08-11 19:05:33 +03:00
tlog1 < < " Error: SDL says that " < < w < < " x " < < h < < " resolution is not available! \n " ;
return ;
2009-07-16 02:58:47 +03:00
}
2009-08-22 16:59:15 +03:00
bool bufOnScreen = ( screenBuf = = screen ) ;
2009-08-11 19:05:33 +03:00
if ( suggestedBpp ! = bpp )
2009-07-16 02:58:47 +03:00
{
tlog2 < < " Warning: SDL says that " < < bpp < < " bpp is wrong and suggests " < < suggestedBpp < < std : : endl ;
}
2009-08-11 19:05:33 +03:00
if ( screen ) //screen has been already initialized
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
SDL_InitSubSystem ( SDL_INIT_VIDEO ) ;
2009-07-16 02:58:47 +03:00
if ( ( screen = SDL_SetVideoMode ( w , h , suggestedBpp , SDL_SWSURFACE | ( fullscreen ? SDL_FULLSCREEN : 0 ) ) ) = = NULL )
{
tlog1 < < " Requested screen resolution is not available ( " < < w < < " x " < < h < < " x " < < suggestedBpp < < " bpp) \n " ;
2009-05-17 07:14:30 +03:00
throw " Requested screen resolution is not available \n " ;
}
2009-08-22 16:59:15 +03:00
tlog0 < < " New screen flags: " < < screen - > flags < < std : : endl ;
2009-04-14 15:47:09 +03:00
if ( screen2 )
SDL_FreeSurface ( screen2 ) ;
screen2 = CSDL_Ext : : copySurface ( screen ) ;
SDL_EnableUNICODE ( 1 ) ;
SDL_WM_SetCaption ( NAME . c_str ( ) , " " ) ; //set window title
SDL_ShowCursor ( SDL_DISABLE ) ;
2010-02-20 15:24:38 +02:00
SDL_EnableKeyRepeat ( SDL_DEFAULT_REPEAT_DELAY , SDL_DEFAULT_REPEAT_INTERVAL ) ;
2009-08-22 16:59:15 +03:00
2009-11-28 19:21:54 +02:00
# ifdef _WIN32
SDL_SysWMinfo wm ;
SDL_VERSION ( & wm . version ) ;
int getwm = SDL_GetWMInfo ( & wm ) ;
if ( getwm = = 1 )
{
int sw = GetSystemMetrics ( SM_CXSCREEN ) ,
sh = GetSystemMetrics ( SM_CYSCREEN ) ;
RECT curpos ;
GetWindowRect ( wm . window , & curpos ) ;
int ourw = curpos . right - curpos . left ,
ourh = curpos . bottom - curpos . top ;
SetWindowPos ( wm . window , 0 , ( sw - ourw ) / 2 , ( sh - ourh ) / 2 , 0 , 0 , SWP_NOZORDER | SWP_NOSIZE ) ;
}
else
{
tlog3 < < " Something went wrong, getwm= " < < getwm < < std : : endl ;
tlog3 < < " SDL says: " < < SDL_GetError ( ) < < std : : endl ;
tlog3 < < " Window won't be centered. \n " ;
}
# endif
//TODO: centering game window on other platforms (or does the environment do their job correctly there?)
2009-08-22 16:59:15 +03:00
screenBuf = bufOnScreen ? screen : screen2 ;
2010-07-14 04:08:27 +03:00
setResolution = true ;
2009-05-06 05:32:36 +03:00
}
2009-08-17 11:50:31 +03:00
2009-11-01 03:15:16 +02:00
static void listenForEvents ( )
2009-08-17 13:47:08 +03:00
{
while ( 1 ) //main SDL events loop
{
2009-11-01 03:15:16 +02:00
SDL_Event * ev = new SDL_Event ( ) ;
2009-08-17 13:47:08 +03:00
2009-08-22 16:59:15 +03:00
//tlog0 << "Waiting... ";
2009-08-17 13:47:08 +03:00
int ret = SDL_WaitEvent ( ev ) ;
2009-08-22 16:59:15 +03:00
//tlog0 << "got " << (int)ev->type;
2009-11-01 03:15:16 +02:00
if ( ret = = 0 | | ( ev - > type = = SDL_QUIT ) | |
( ev - > type = = SDL_KEYDOWN & & ev - > key . keysym . sym = = SDLK_F4 & & ( ev - > key . keysym . mod & KMOD_ALT ) ) )
2009-08-17 13:47:08 +03:00
{
2009-10-26 07:39:30 +02:00
if ( client )
2009-11-01 03:15:16 +02:00
client - > stop ( ) ;
2009-12-28 06:08:24 +02:00
if ( mainGUIThread )
{
GH . terminate = true ;
mainGUIThread - > join ( ) ;
delete mainGUIThread ;
mainGUIThread = NULL ;
2009-10-26 07:39:30 +02:00
}
delete console ;
console = NULL ;
2009-08-17 13:47:08 +03:00
SDL_Delay ( 750 ) ;
2009-10-26 07:39:30 +02:00
SDL_Quit ( ) ;
2009-08-17 13:47:08 +03:00
tlog0 < < " Ending... \n " ;
2009-10-26 07:39:30 +02:00
break ;
2009-08-17 13:47:08 +03:00
}
2009-08-22 16:59:15 +03:00
else if ( LOCPLINT & & ev - > type = = SDL_KEYDOWN & & ev - > key . keysym . sym = = SDLK_F4 )
2009-08-17 13:47:08 +03:00
{
boost : : unique_lock < boost : : recursive_mutex > lock ( * LOCPLINT - > pim ) ;
bool full = ! ( screen - > flags & SDL_FULLSCREEN ) ;
setScreenRes ( conf . cc . resx , conf . cc . resy , conf . cc . bpp , full ) ;
GH . totalRedraw ( ) ;
2009-11-01 03:15:16 +02:00
delete ev ;
continue ;
2009-08-17 13:47:08 +03:00
}
2009-08-22 16:59:15 +03:00
else if ( ev - > type = = SDL_USEREVENT & & ev - > user . code = = 1 )
{
2010-07-14 04:08:27 +03:00
tlog0 < < " Changing resolution has been requested \n " ;
2009-08-22 16:59:15 +03:00
setScreenRes ( conf . cc . resx , conf . cc . resy , conf . cc . bpp , conf . cc . fullscreen ) ;
delete ev ;
continue ;
}
2010-01-29 18:19:12 +02:00
else if ( ev - > type = = SDL_USEREVENT & & ev - > user . code = = 2 ) //something want to quit to main menu
2009-12-28 06:08:24 +02:00
{
2009-11-01 03:15:16 +02:00
client - > stop ( ) ;
2010-01-29 22:52:45 +02:00
delete client ;
client = NULL ;
2009-11-01 03:15:16 +02:00
delete ev ;
2009-12-28 06:08:24 +02:00
2010-08-01 17:04:48 +03:00
delete CGI - > dobjinfo ;
CGI - > dobjinfo = new CDefObjInfoHandler ;
CGI - > dobjinfo - > load ( ) ;
2009-12-28 06:08:24 +02:00
GH . curInt = CGP ;
2010-03-06 00:51:09 +02:00
GH . defActionsDef = 63 ;
2009-11-01 03:15:16 +02:00
continue ;
}
2009-08-22 16:59:15 +03:00
//tlog0 << " pushing ";
2009-08-17 13:47:08 +03:00
eventsM . lock ( ) ;
events . push ( ev ) ;
eventsM . unlock ( ) ;
2009-08-22 16:59:15 +03:00
//tlog0 << " done\n";
2009-08-17 13:47:08 +03:00
}
}
void startGame ( StartInfo * options )
{
2009-12-28 06:08:24 +02:00
GH . curInt = NULL ;
2009-08-17 13:47:08 +03:00
if ( gOnlyAI )
{
2010-08-03 14:36:52 +03:00
for ( std : : map < int , PlayerSettings > : : iterator it = options - > playerInfos . begin ( ) ;
it ! = options - > playerInfos . end ( ) ; + + it )
2009-08-17 13:47:08 +03:00
{
2010-08-03 14:36:52 +03:00
it - > second . human = false ;
2009-08-17 13:47:08 +03:00
}
}
if ( screen - > w ! = conf . cc . resx | | screen - > h ! = conf . cc . resy )
{
2010-07-14 04:08:27 +03:00
requestChangingResolution ( ) ;
//allow event handling thread change resolution
eventsM . unlock ( ) ;
while ( ! setResolution ) boost : : this_thread : : sleep ( boost : : posix_time : : milliseconds ( 50 ) ) ;
eventsM . lock ( ) ;
2009-08-17 13:47:08 +03:00
}
2010-04-02 05:07:40 +03:00
else
setResolution = true ;
2009-08-17 13:47:08 +03:00
2010-07-14 04:08:27 +03:00
2009-12-28 06:08:24 +02:00
client = new CClient ;
2010-08-01 17:46:19 +03:00
CPlayerInterface : : howManyPeople = 0 ;
2010-05-08 21:56:38 +03:00
switch ( options - > mode ) //new game
2009-08-17 13:47:08 +03:00
{
2010-08-18 12:50:25 +03:00
case StartInfo : : NEW_GAME :
case StartInfo : : CAMPAIGN :
2009-12-28 06:08:24 +02:00
client - > newGame ( NULL , options ) ;
2010-05-08 21:56:38 +03:00
break ;
2010-08-18 12:50:25 +03:00
case StartInfo : : LOAD_GAME :
2009-08-17 13:47:08 +03:00
std : : string fname = options - > mapname ;
boost : : algorithm : : erase_last ( fname , " .vlgm1 " ) ;
2009-12-28 06:08:24 +02:00
client - > loadGame ( fname ) ;
2010-05-08 21:56:38 +03:00
break ;
2009-08-17 13:47:08 +03:00
}
2009-11-01 03:15:16 +02:00
CGI - > musich - > stopMusic ( ) ;
2009-12-28 06:08:24 +02:00
client - > connectionHandler = new boost : : thread ( & CClient : : run , client ) ;
2009-10-04 05:02:45 +03:00
}
2010-07-14 04:08:27 +03:00
void requestChangingResolution ( )
{
//mark that we are going to change resolution
setResolution = false ;
//push special event to order event reading thread to change resolution
SDL_Event ev ;
ev . type = SDL_USEREVENT ;
ev . user . code = 1 ;
SDL_PushEvent ( & ev ) ;
}