2007-06-06 22:29:40 +03:00
// CMT.cpp : Defines the entry point for the console application.
//
2008-08-04 18:56:36 +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>
# 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_ttf.h>
# 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"
2007-07-07 19:04:15 +03:00
# include "mapHandler.h"
# 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"
2007-08-15 18:13:11 +03:00
# include "CConsoleHandler.h"
2007-08-21 16:48:18 +03:00
# include "CCursorHandler.h"
2007-08-29 15:18:31 +03:00
# include "CPathfinder.h"
# include "CGameState.h"
2007-09-14 16:11:10 +03:00
# 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"
2008-07-25 20:28:28 +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"
# include "hch/CLodHandler.h"
# include "hch/CDefHandler.h"
# include "hch/CAmbarCendamo.h"
# include "hch/CGeneralTextHandler.h"
2008-07-01 11:01:02 +03:00
# include "client/Graphics.h"
2008-08-04 12:05:52 +03:00
# include "client/Client.h"
2008-11-09 00:29:19 +02:00
# include "client/CConfigHandler.h"
2008-07-03 18:03:32 +03:00
# include "lib/Connection.h"
2008-07-25 20:28:28 +03:00
# include "lib/VCMI_Lib.h"
2008-12-21 21:17:35 +02:00
# include <cstdlib>
2009-03-09 12:37:49 +02:00
# include "lib/NetPacks.h"
2008-12-21 21:17:35 +02:00
2009-02-08 17:39:26 +02:00
# if __MINGW32__
# undef main
# endif
2008-06-30 03:06:41 +03:00
std : : string NAME = NAME_VER + std : : string ( " (client) " ) ;
2008-04-25 12:25:59 +03:00
SDL_Surface * screen , * screen2 ;
2009-03-12 20:50:36 +02:00
std : : queue < SDL_Event * > events ;
2008-08-04 18:56:36 +03:00
boost : : mutex eventsM ;
TTF_Font * TNRB16 , * TNR , * GEOR13 , * GEORXX , * GEORM , * GEOR16 ;
2008-10-19 02:20:48 +03:00
void processCommand ( const std : : string & message , CClient * & client ) ;
2008-08-04 12:05:52 +03:00
# ifndef __GNUC__
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
{
2008-11-09 00:29:19 +02:00
tlog0 < < " Starting... " < < std : : endl ;
THC timeHandler tmh , total , pomtime ;
2008-10-19 02:20:48 +03:00
CClient * client = NULL ;
2008-09-17 13:18:22 +03:00
boost : : thread * console = NULL ;
2008-11-09 00:29:19 +02:00
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 " ) ;
: : console = new CConsoleHandler ;
* : : console - > cb = boost : : bind ( processCommand , _1 , boost : : ref ( client ) ) ;
console = new boost : : thread ( boost : : bind ( & CConsoleHandler : : run , : : console ) ) ;
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 ) ) ;
CPG = NULL ;
atexit ( SDL_Quit ) ;
CGameInfo * cgi = CGI = new CGameInfo ; //contains all global informations about game (texts, lodHandlers, map handler itp.)
2008-09-17 13:18:22 +03:00
if ( SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO ) = = 0 )
2007-06-06 22:29:40 +03:00
{
2009-02-01 22:31:41 +02:00
screen = SDL_SetVideoMode ( 800 , 600 , conf . cc . bpp , SDL_SWSURFACE | SDL_DOUBLEBUF | ( conf . cc . fullscreen ? SDL_FULLSCREEN : 0 ) ) ; //initializing important global surface
2008-09-19 11:16:19 +03:00
tlog0 < < " \t Initializing screen: " < < pomtime . getDif ( ) ;
tlog0 < < std : : endl ;
2008-06-30 03:06:41 +03:00
SDL_WM_SetCaption ( NAME . c_str ( ) , " " ) ; //set window title
2008-06-16 13:51:14 +03:00
# 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 ;
2008-08-04 18:56:36 +03:00
# endif
2008-02-06 15:50:40 +02:00
CSDL_Ext : : std32bppSurface = SDL_CreateRGBSurface ( SDL_SWSURFACE , 1 , 1 , 32 , rmask , gmask , bmask , amask ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " \t Initializing minors: " < < pomtime . getDif ( ) < < std : : endl ;
2007-06-12 12:33:20 +03:00
TTF_Init ( ) ;
2008-08-17 22:15:31 +03:00
TNRB16 = TTF_OpenFont ( " Fonts " PATHSEPARATOR " tnrb.ttf " , 16 ) ;
GEOR13 = TTF_OpenFont ( " Fonts " PATHSEPARATOR " georgia.ttf " , 13 ) ;
GEOR16 = TTF_OpenFont ( " Fonts " PATHSEPARATOR " georgia.ttf " , 16 ) ;
GEORXX = TTF_OpenFont ( " Fonts " PATHSEPARATOR " tnrb.ttf " , 22 ) ;
GEORM = TTF_OpenFont ( " Fonts " PATHSEPARATOR " georgia.ttf " , 10 ) ;
2009-02-14 17:00:29 +02:00
if ( ! ( TNRB16 & & GEOR16 & & GEORXX & & GEORM ) )
{
tlog1 < < " One of the fonts couldn't be loaded! \n " ;
throw " One of the fonts couldn't be loaded! \n " ;
}
2008-06-16 13:51:14 +03:00
atexit ( TTF_Quit ) ;
2008-09-19 11:16:19 +03:00
THC tlog0 < < " \t Initializing fonts: " < < pomtime . getDif ( ) < < std : : endl ;
2007-09-18 16:30:26 +03:00
CMusicHandler * mush = new CMusicHandler ; //initializing audio
2007-06-20 15:00:18 +03:00
mush - > initMusics ( ) ;
2009-01-07 21:40:19 +02:00
//audio initialized
2007-07-09 08:57:30 +03:00
cgi - > mush = mush ;
2008-11-09 00:29:19 +02:00
tlog0 < < " \t Initializing sound: " < < pomtime . getDif ( ) < < std : : endl ;
tlog0 < < " Initializing screen, fonts and sound handling: " < < tmh . getDif ( ) < < std : : endl ;
2008-06-14 13:20:18 +03:00
CDefHandler : : Spriteh = cgi - > spriteh = new CLodHandler ( ) ;
2008-08-17 22:15:31 +03:00
cgi - > spriteh - > init ( " Data " PATHSEPARATOR " H3sprite.lod " , " Sprites " ) ;
2008-06-12 09:45:51 +03:00
BitmapHandler : : bitmaph = cgi - > bitmaph = new CLodHandler ;
2008-08-17 22:15:31 +03:00
cgi - > bitmaph - > init ( " Data " PATHSEPARATOR " H3bitmap.lod " , " Data " ) ;
2008-11-09 00:29:19 +02:00
tlog0 < < " Loading .lod files: " < < tmh . getDif ( ) < < std : : endl ;
2008-09-17 13:18:22 +03:00
initDLL ( cgi - > bitmaph , : : console , logfile ) ;
2009-01-11 00:08:18 +02:00
CGI - > setFromLib ( ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " Initializing VCMI_Lib: " < < tmh . getDif ( ) < < std : : endl ;
2008-06-14 13:20:18 +03:00
pomtime . getDif ( ) ;
2009-02-08 17:39:26 +02:00
cgi - > curh = new CCursorHandler ;
2008-08-01 21:13:33 +03:00
cgi - > curh - > initCursor ( ) ;
2008-11-28 03:36:34 +02:00
cgi - > curh - > show ( ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " \t Screen handler: " < < pomtime . getDif ( ) < < std : : endl ;
2009-01-11 00:08:18 +02:00
cgi - > pathf = new CPathfinder ( ) ;
tlog0 < < " \t Pathfinder: " < < pomtime . getDif ( ) < < std : : endl ;
2008-09-19 11:16:19 +03:00
tlog0 < < " Preparing first handlers: " < < tmh . getDif ( ) < < std : : endl ;
2008-06-16 13:51:14 +03:00
pomtime . getDif ( ) ;
2008-06-14 13:20:18 +03:00
graphics = new Graphics ( ) ;
2009-01-11 00:08:18 +02:00
graphics - > loadHeroAnim ( ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " \t Main graphics: " < < tmh . getDif ( ) < < std : : endl ;
tlog0 < < " Initializing game graphics: " < < tmh . getDif ( ) < < std : : endl ;
2007-10-13 23:31:50 +03:00
CMessage : : init ( ) ;
2008-11-28 03:36:34 +02:00
tlog0 < < " Message handler: " < < tmh . getDif ( ) < < std : : endl ;
2007-07-09 14:40:39 +03:00
CPreGame * cpg = new CPreGame ( ) ; //main menu and submenus
2008-09-19 11:16:19 +03:00
tlog0 < < " Initialization CPreGame (together): " < < tmh . getDif ( ) < < std : : endl ;
2009-01-07 21:40:19 +02:00
tlog0 < < " Initialization of VCMI (together): " < < total . getDif ( ) < < std : : endl ;
2007-06-20 15:00:18 +03:00
cpg - > mush = mush ;
2008-09-12 11:51:46 +03:00
2008-06-30 03:06:41 +03:00
StartInfo * options = new StartInfo ( cpg - > runLoop ( ) ) ;
2008-08-09 02:02:32 +03:00
2009-02-01 22:31:41 +02:00
if ( screen - > w ! = conf . cc . resx | | screen - > h ! = conf . cc . resy )
{
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
SDL_InitSubSystem ( SDL_INIT_VIDEO ) ;
screen = SDL_SetVideoMode ( conf . cc . resx , conf . cc . resy , conf . cc . bpp , SDL_SWSURFACE | SDL_DOUBLEBUF | ( conf . cc . fullscreen ? SDL_FULLSCREEN : 0 ) ) ; //initializing important global surface
SDL_WM_SetCaption ( NAME . c_str ( ) , " " ) ; //set window title
SDL_ShowCursor ( SDL_DISABLE ) ;
}
2009-01-11 00:08:18 +02:00
CClient cl ;
if ( options - > mode = = 0 ) //new game
2008-09-12 11:51:46 +03:00
{
2009-01-11 00:08:18 +02:00
tmh . getDif ( ) ;
2009-02-08 17:39:26 +02:00
char portc [ 10 ] ;
2009-01-11 00:08:18 +02:00
SDL_itoa ( conf . cc . port , portc , 10 ) ;
CClient : : runServer ( portc ) ;
tlog0 < < " Preparing shared memory and starting server: " < < tmh . getDif ( ) < < std : : endl ;
tmh . getDif ( ) ; pomtime . getDif ( ) ; //reset timers
CConnection * c = NULL ;
//wait until server is ready
tlog0 < < " Waiting for server... " ;
2009-01-30 23:28:02 +02:00
cl . waitForServer ( ) ;
2009-01-11 00:08:18 +02:00
tlog0 < < tmh . getDif ( ) < < std : : endl ;
while ( ! c )
2008-09-12 11:51:46 +03:00
{
2009-01-11 00:08:18 +02:00
try
{
tlog0 < < " Establishing connection... \n " ;
c = new CConnection ( conf . cc . server , portc , NAME ) ;
}
catch ( . . . )
{
tlog1 < < " \n Cannot establish connection! Retrying within 2 seconds " < < std : : endl ;
SDL_Delay ( 2000 ) ;
}
2008-09-12 11:51:46 +03:00
}
2009-01-11 00:08:18 +02:00
THC tlog0 < < " \t Connecting to the server: " < < tmh . getDif ( ) < < std : : endl ;
cl . newGame ( c , options ) ;
client = & cl ;
boost : : thread t ( boost : : bind ( & CClient : : run , & cl ) ) ;
2008-09-12 11:51:46 +03:00
}
2009-01-11 00:08:18 +02:00
else //load game
2008-08-09 02:02:32 +03:00
{
2009-01-11 00:08:18 +02:00
std : : string fname = options - > mapname ;
boost : : algorithm : : erase_last ( fname , " .vlgm1 " ) ;
cl . load ( fname ) ;
client = & cl ;
boost : : thread t ( boost : : bind ( & CClient : : run , & cl ) ) ;
2008-08-09 02:02:32 +03:00
}
2009-01-11 00:08:18 +02:00
2009-03-12 20:50:36 +02:00
SDL_Event * ev = NULL ;
2008-07-27 20:07:37 +03:00
while ( 1 ) //main SDL events loop
{
2009-03-12 20:50:36 +02:00
ev = new SDL_Event ( ) ;
SDL_WaitEvent ( ev ) ;
if ( ( ev - > type = = SDL_QUIT ) | | ( ev - > type = = SDL_KEYDOWN & & ev - > key . keysym . sym = = SDLK_F4 & & ( ev - > key . keysym . mod & KMOD_ALT ) ) )
2008-07-27 20:07:37 +03:00
{
2008-08-25 13:25:16 +03:00
cl . close ( ) ;
2008-09-18 23:24:53 +03:00
# ifndef __unix__
2008-09-17 13:18:22 +03:00
: : console - > killConsole ( console - > native_handle ( ) ) ;
2008-09-18 23:24:53 +03:00
# endif
2008-10-26 22:58:34 +02:00
LOCPLINT - > pim - > lock ( ) ;
2008-08-25 13:25:16 +03:00
SDL_Delay ( 750 ) ;
2008-09-19 11:16:19 +03:00
tlog0 < < " Ending... \n " ;
2008-12-21 21:17:35 +02:00
exit ( EXIT_SUCCESS ) ;
2008-07-27 20:07:37 +03:00
}
2009-03-12 20:50:36 +02:00
else if ( ev - > type = = SDL_KEYDOWN & & ev - > key . keysym . sym = = SDLK_F4 )
2009-01-07 21:40:19 +02:00
{
LOCPLINT - > pim - > lock ( ) ;
2009-01-25 18:19:34 +02:00
bool full = ! ( screen - > flags & SDL_FULLSCREEN ) ;
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
SDL_InitSubSystem ( SDL_INIT_VIDEO ) ;
screen = SDL_SetVideoMode ( conf . cc . resx , conf . cc . resy , conf . cc . bpp , SDL_SWSURFACE | SDL_DOUBLEBUF | ( full ? SDL_FULLSCREEN : 0 ) ) ; //initializing important global surface
SDL_WM_SetCaption ( NAME . c_str ( ) , " " ) ; //set window title
SDL_ShowCursor ( SDL_DISABLE ) ;
2009-01-07 21:40:19 +02:00
LOCPLINT - > curint - > show ( ) ;
if ( LOCPLINT - > curint ! = LOCPLINT - > adventureInt )
LOCPLINT - > adventureInt - > show ( ) ;
if ( LOCPLINT - > curint = = LOCPLINT - > castleInt )
LOCPLINT - > castleInt - > showAll ( 0 , true ) ;
if ( LOCPLINT - > curint - > subInt )
LOCPLINT - > curint - > subInt - > show ( ) ;
LOCPLINT - > pim - > unlock ( ) ;
}
2008-07-27 20:07:37 +03:00
eventsM . lock ( ) ;
events . push ( ev ) ;
eventsM . unlock ( ) ;
2008-08-04 18:56:36 +03:00
}
2007-06-06 22:29:40 +03:00
}
else
{
2008-09-19 11:16:19 +03:00
tlog1 < < " Something was wrong: " < < SDL_GetError ( ) < < std : : endl ;
2007-06-06 22:29:40 +03:00
return - 1 ;
}
2007-06-07 20:45:56 +03:00
}
2008-09-17 13:18:22 +03:00
2008-10-19 02:20:48 +03:00
void processCommand ( const std : : string & message , CClient * & client )
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 ;
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 :
LOCPLINT - > curint - > activate ( ) ;
break ;
case 1 :
LOCPLINT - > adventureInt - > activate ( ) ;
break ;
case 2 :
LOCPLINT - > castleInt - > activate ( ) ;
break ;
}
}
2008-11-16 03:06:15 +02:00
else if ( cn = = " save " )
{
std : : string fname ;
readed > > fname ;
client - > save ( fname ) ;
}
2009-01-11 00:08:18 +02:00
else if ( cn = = " load " )
{
std : : string fname ;
readed > > fname ;
client - > load ( fname ) ;
}
2009-02-01 22:31:41 +02:00
else if ( cn = = " resolution " )
{
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 ;
if ( ! i )
return ;
2009-02-11 19:03:30 +02:00
else if ( i < 0 | | i > conf . guiOptions . size ( ) )
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-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 ;
2008-11-01 00:41:22 +02:00
txth - > init ( std : : string ( DATA_DIR " Data " PATHSEPARATOR " 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 ) )
{
txth - > extractFile ( std : : string ( " Extracted_txts \\ " ) + pom , pom ) ;
}
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
}
2008-10-19 02:20:48 +03:00
else if ( client & & client - > serv & & client - > serv - > connected ) //send to server
{
2009-03-12 20:50:36 +02:00
* client - > serv < < & PlayerMessage ( LOCPLINT - > playerID , message ) ;
2008-10-19 02:20:48 +03:00
}
2009-01-11 00:08:18 +02:00
}