2010-03-16 22:37:11 +01:00
// ==============================================================
// This file is part of Glest (www.glest.org)
//
2010-03-17 14:22:08 +01:00
// Copyright (C) 2001-2008 Marti<74> o Figueroa
2010-03-16 22:37:11 +01:00
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
# include "client_interface.h"
# include <stdexcept>
# include <cassert>
# include "platform_util.h"
# include "game_util.h"
# include "conversion.h"
# include "config.h"
# include "lang.h"
# include "leak_dumper.h"
# include "map.h"
# include "config.h"
# include "logger.h"
using namespace std ;
using namespace Shared : : Platform ;
using namespace Shared : : Util ;
namespace Glest { namespace Game {
// =====================================================
// class ClientInterface
// =====================================================
const int ClientInterface : : messageWaitTimeout = 10000 ; //10 seconds
2010-04-15 03:19:00 +02:00
const int ClientInterface : : waitSleepTime = 10 ;
2010-03-16 22:37:11 +01:00
ClientInterface : : ClientInterface ( ) {
clientSocket = NULL ;
launchGame = false ;
introDone = false ;
playerIndex = - 1 ;
2010-04-22 01:13:39 +02:00
gameSettingsReceived = false ;
2010-03-16 22:37:11 +01:00
networkGameDataSynchCheckOkMap = false ;
networkGameDataSynchCheckOkTile = false ;
networkGameDataSynchCheckOkTech = false ;
}
ClientInterface : : ~ ClientInterface ( )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
if ( clientSocket ! = NULL & & clientSocket - > isConnected ( ) = = true )
{
2010-03-24 00:32:25 +01:00
string sQuitText = Config : : getInstance ( ) . getString ( " NetPlayerName " , Socket : : getHostName ( ) . c_str ( ) ) + " has chosen to leave the game! " ;
2010-03-16 22:37:11 +01:00
sendTextMessage ( sQuitText , - 1 ) ;
}
delete clientSocket ;
clientSocket = NULL ;
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] END \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
}
void ClientInterface : : connect ( const Ip & ip , int port )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
delete clientSocket ;
this - > ip = ip ;
this - > port = port ;
clientSocket = new ClientSocket ( ) ;
clientSocket - > setBlock ( false ) ;
clientSocket - > connect ( ip , port ) ;
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] END - socket = %d \n " , __FILE__ , __FUNCTION__ , clientSocket - > getSocketId ( ) ) ;
2010-03-16 22:37:11 +01:00
}
void ClientInterface : : reset ( )
{
if ( getSocket ( ) ! = NULL )
{
2010-03-24 00:32:25 +01:00
string sQuitText = Config : : getInstance ( ) . getString ( " NetPlayerName " , Socket : : getHostName ( ) . c_str ( ) ) + " has chosen to leave the game! " ;
2010-03-16 22:37:11 +01:00
sendTextMessage ( sQuitText , - 1 ) ;
close ( ) ;
}
}
void ClientInterface : : update ( )
{
NetworkMessageCommandList networkMessageCommandList ;
//send as many commands as we can
while ( ! requestedCommands . empty ( ) ) {
if ( networkMessageCommandList . addCommand ( & requestedCommands . back ( ) ) ) {
requestedCommands . pop_back ( ) ;
}
else {
break ;
}
}
if ( networkMessageCommandList . getCommandCount ( ) > 0 ) {
sendMessage ( & networkMessageCommandList ) ;
}
//clear chat variables
chatText . clear ( ) ;
chatSender . clear ( ) ;
chatTeamIndex = - 1 ;
}
void ClientInterface : : updateLobby ( )
{
//clear chat variables
chatText . clear ( ) ;
chatSender . clear ( ) ;
chatTeamIndex = - 1 ;
NetworkMessageType networkMessageType = getNextMessageType ( true ) ;
switch ( networkMessageType )
{
case nmtInvalid :
break ;
case nmtIntro :
{
NetworkMessageIntro networkMessageIntro ;
if ( receiveMessage ( & networkMessageIntro ) )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] got NetworkMessageIntro \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
//check consistency
2010-03-17 14:22:08 +01:00
if ( networkMessageIntro . getVersionString ( ) ! = getNetworkVersionString ( ) )
2010-03-16 22:37:11 +01:00
{
2010-04-30 03:32:37 +02:00
bool versionMatched = false ;
string platformFreeVersion = getNetworkPlatformFreeVersionString ( ) ;
string sErr = " " ;
if ( strncmp ( platformFreeVersion . c_str ( ) , networkMessageIntro . getVersionString ( ) . c_str ( ) , strlen ( platformFreeVersion . c_str ( ) ) ) ! = 0 ) {
sErr = " Server and client binary mismatch! \n You have to use the exactly same binaries! \n \n Server: " +
networkMessageIntro . getVersionString ( ) +
" \n Client: " + getNetworkVersionString ( ) ;
printf ( " %s \n " , sErr . c_str ( ) ) ;
sendTextMessage ( " Server and client binary mismatch!! " , - 1 ) ;
sendTextMessage ( " Server: " + networkMessageIntro . getVersionString ( ) , - 1 ) ;
sendTextMessage ( " Client: " + getNetworkVersionString ( ) , - 1 ) ;
}
else {
versionMatched = true ;
2010-04-30 04:20:27 +02:00
sErr = " Warning, Server and client are using the same version but different platforms. \n \n Server: " +
2010-04-30 03:32:37 +02:00
networkMessageIntro . getVersionString ( ) + " \n Client: " + getNetworkVersionString ( ) ;
printf ( " %s \n " , sErr . c_str ( ) ) ;
sendTextMessage ( " Server and client platform mismatch. " , - 1 ) ;
sendTextMessage ( " Server: " + networkMessageIntro . getVersionString ( ) , - 1 ) ;
sendTextMessage ( " Client: " + getNetworkVersionString ( ) , - 1 ) ;
}
if ( Config : : getInstance ( ) . getBool ( " PlatformConsistencyChecks " , " true " ) & & versionMatched = = false )
2010-03-17 14:22:08 +01:00
{ // error message and disconnect only if checked
2010-03-17 07:25:19 +01:00
DisplayErrorMessage ( sErr ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-03-17 14:22:08 +01:00
return ;
}
2010-03-16 22:37:11 +01:00
}
2010-03-17 21:57:19 +01:00
2010-03-16 22:37:11 +01:00
//send intro message
2010-03-23 03:37:41 +01:00
NetworkMessageIntro sendNetworkMessageIntro ( getNetworkVersionString ( ) , Config : : getInstance ( ) . getString ( " NetPlayerName " , Socket : : getHostName ( ) . c_str ( ) ) , - 1 ) ;
2010-03-16 22:37:11 +01:00
playerIndex = networkMessageIntro . getPlayerIndex ( ) ;
serverName = networkMessageIntro . getName ( ) ;
sendMessage ( & sendNetworkMessageIntro ) ;
assert ( playerIndex > = 0 & & playerIndex < GameConstants : : maxPlayers ) ;
introDone = true ;
}
}
break ;
case nmtSynchNetworkGameData :
{
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData ;
if ( receiveMessage ( & networkMessageSynchNetworkGameData ) )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] got NetworkMessageSynchNetworkGameData \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
2010-04-29 09:59:44 +02:00
int32 tilesetCRC = 0 ;
int32 techCRC = 0 ;
int32 mapCRC = 0 ;
try {
Config & config = Config : : getInstance ( ) ;
string scenarioDir = " " ;
if ( gameSettings . getScenarioDir ( ) ! = " " ) {
scenarioDir = gameSettings . getScenarioDir ( ) ;
if ( EndsWith ( scenarioDir , " .xml " ) = = true ) {
scenarioDir = scenarioDir . erase ( scenarioDir . size ( ) - 4 , 4 ) ;
scenarioDir = scenarioDir . erase ( scenarioDir . size ( ) - gameSettings . getScenario ( ) . size ( ) , gameSettings . getScenario ( ) . size ( ) + 1 ) ;
}
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , gameSettings . getScenarioDir ( ) . c_str ( ) , gameSettings . getScenario ( ) . c_str ( ) , scenarioDir . c_str ( ) ) ;
}
// check the checksum's
//int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(string(GameConstants::folder_path_tilesets) + "/" + networkMessageSynchNetworkGameData.getTileset() + "/*", ".xml", NULL);
tilesetCRC = getFolderTreeContentsCheckSumRecursively ( config . getPathListForType ( ptTilesets , scenarioDir ) , string ( " / " ) + networkMessageSynchNetworkGameData . getTileset ( ) + string ( " /* " ) , " .xml " , NULL ) ;
this - > setNetworkGameDataSynchCheckOkTile ( ( tilesetCRC = = networkMessageSynchNetworkGameData . getTilesetCRC ( ) ) ) ;
//if(this->getNetworkGameDataSynchCheckOkTile() == false)
//{
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] tilesetCRC info, local = %d, remote = %d, networkMessageSynchNetworkGameData.getTileset() = [%s] \n " , __FILE__ , __FUNCTION__ , tilesetCRC , networkMessageSynchNetworkGameData . getTilesetCRC ( ) , networkMessageSynchNetworkGameData . getTileset ( ) . c_str ( ) ) ;
//}
//tech, load before map because of resources
//int32 techCRC = getFolderTreeContentsCheckSumRecursively(string(GameConstants::folder_path_techs) + "/" + networkMessageSynchNetworkGameData.getTech() + "/*", ".xml", NULL);
techCRC = getFolderTreeContentsCheckSumRecursively ( config . getPathListForType ( ptTechs , scenarioDir ) , string ( " / " ) + networkMessageSynchNetworkGameData . getTech ( ) + string ( " /* " ) , " .xml " , NULL ) ;
this - > setNetworkGameDataSynchCheckOkTech ( ( techCRC = = networkMessageSynchNetworkGameData . getTechCRC ( ) ) ) ;
//if(this->getNetworkGameDataSynchCheckOkTech() == false)
//{
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] techCRC info, local = %d, remote = %d, networkMessageSynchNetworkGameData.getTech() = [%s] \n " , __FILE__ , __FUNCTION__ , techCRC , networkMessageSynchNetworkGameData . getTechCRC ( ) , networkMessageSynchNetworkGameData . getTech ( ) . c_str ( ) ) ;
//}
//map
Checksum checksum ;
string file = Map : : getMapPath ( networkMessageSynchNetworkGameData . getMap ( ) , scenarioDir , false ) ;
if ( file ! = " " ) {
checksum . addFile ( file ) ;
mapCRC = checksum . getSum ( ) ;
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),mapCRC);
this - > setNetworkGameDataSynchCheckOkMap ( ( mapCRC = = networkMessageSynchNetworkGameData . getMapCRC ( ) ) ) ;
//if(this->getNetworkGameDataSynchCheckOkMap() == false)
//{
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] mapCRC info, local = %d, remote = %d, file = [%s] \n " , __FILE__ , __FUNCTION__ , mapCRC , networkMessageSynchNetworkGameData . getMapCRC ( ) , file . c_str ( ) ) ;
//}
}
catch ( const runtime_error & ex ) {
string sErr = ex . what ( ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] error during processing, sErr = [%s] \n " , __FILE__ , __FUNCTION__ , sErr . c_str ( ) ) ;
DisplayErrorMessage ( sErr ) ;
}
NetworkMessageSynchNetworkGameDataStatus sendNetworkMessageSynchNetworkGameDataStatus ( mapCRC , tilesetCRC , techCRC ) ;
sendMessage ( & sendNetworkMessageSynchNetworkGameDataStatus ) ;
2010-03-16 22:37:11 +01:00
}
}
break ;
case nmtSynchNetworkGameDataFileCRCCheck :
{
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck ;
if ( receiveMessage ( & networkMessageSynchNetworkGameDataFileCRCCheck ) )
{
2010-03-20 00:26:00 +01:00
Checksum checksum ;
string file = networkMessageSynchNetworkGameDataFileCRCCheck . getFileName ( ) ;
checksum . addFile ( file ) ;
int32 fileCRC = checksum . getSum ( ) ;
2010-03-16 22:37:11 +01:00
2010-03-20 00:26:00 +01:00
if ( fileCRC ! = networkMessageSynchNetworkGameDataFileCRCCheck . getFileCRC ( ) )
{
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck localCRC = %d, remoteCRC = %d, file [%s] \n " ,
__FILE__ , __FUNCTION__ , fileCRC ,
networkMessageSynchNetworkGameDataFileCRCCheck . getFileCRC ( ) ,
networkMessageSynchNetworkGameDataFileCRCCheck . getFileName ( ) . c_str ( ) ) ;
2010-03-16 22:37:11 +01:00
2010-03-20 00:26:00 +01:00
// Here we initiate a download of missing or mismatched content
2010-03-16 22:37:11 +01:00
2010-03-20 00:26:00 +01:00
NetworkMessageSynchNetworkGameDataFileGet sendNetworkMessageSynchNetworkGameDataFileGet ( networkMessageSynchNetworkGameDataFileCRCCheck . getFileName ( ) ) ;
sendMessage ( & sendNetworkMessageSynchNetworkGameDataFileGet ) ;
2010-03-16 22:37:11 +01:00
2010-03-20 00:26:00 +01:00
FileTransferInfo fileInfo ;
fileInfo . hostType = eClient ;
fileInfo . serverIP = this - > ip . getString ( ) ;
fileInfo . serverPort = this - > port ;
fileInfo . fileName = networkMessageSynchNetworkGameDataFileCRCCheck . getFileName ( ) ;
2010-03-16 22:37:11 +01:00
2010-03-20 00:26:00 +01:00
FileTransferSocketThread * fileXferThread = new FileTransferSocketThread ( fileInfo ) ;
fileXferThread - > start ( ) ;
}
if ( networkMessageSynchNetworkGameDataFileCRCCheck . getFileIndex ( ) < networkMessageSynchNetworkGameDataFileCRCCheck . getTotalFileCount ( ) )
{
NetworkMessageSynchNetworkGameDataFileCRCCheck sendNetworkMessageSynchNetworkGameDataFileCRCCheck (
networkMessageSynchNetworkGameDataFileCRCCheck . getTotalFileCount ( ) ,
networkMessageSynchNetworkGameDataFileCRCCheck . getFileIndex ( ) + 1 ,
0 ,
" " ) ;
sendMessage ( & sendNetworkMessageSynchNetworkGameDataFileCRCCheck ) ;
}
2010-03-16 22:37:11 +01:00
}
}
break ;
case nmtText :
{
NetworkMessageText networkMessageText ;
if ( receiveMessage ( & networkMessageText ) )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] got nmtText \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
chatText = networkMessageText . getText ( ) ;
chatSender = networkMessageText . getSender ( ) ;
chatTeamIndex = networkMessageText . getTeamIndex ( ) ;
}
}
break ;
case nmtLaunch :
{
NetworkMessageLaunch networkMessageLaunch ;
if ( receiveMessage ( & networkMessageLaunch ) )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] got NetworkMessageLaunch \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
networkMessageLaunch . buildGameSettings ( & gameSettings ) ;
//replace server player by network
for ( int i = 0 ; i < gameSettings . getFactionCount ( ) ; + + i )
{
//replace by network
if ( gameSettings . getFactionControl ( i ) = = ctHuman )
{
gameSettings . setFactionControl ( i , ctNetwork ) ;
}
//set the faction index
if ( gameSettings . getStartLocationIndex ( i ) = = playerIndex )
{
gameSettings . setThisFactionIndex ( i ) ;
}
}
launchGame = true ;
}
}
break ;
2010-04-22 01:13:39 +02:00
case nmtBroadCastSetup :
{
NetworkMessageLaunch networkMessageLaunch ;
if ( receiveMessage ( & networkMessageLaunch ) )
{
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] got NetworkMessageLaunch \n " , __FILE__ , __FUNCTION__ ) ;
networkMessageLaunch . buildGameSettings ( & gameSettings ) ;
//replace server player by network
for ( int i = 0 ; i < gameSettings . getFactionCount ( ) ; + + i )
{
//replace by network
if ( gameSettings . getFactionControl ( i ) = = ctHuman )
{
gameSettings . setFactionControl ( i , ctNetwork ) ;
}
//set the faction index
if ( gameSettings . getStartLocationIndex ( i ) = = playerIndex )
{
gameSettings . setThisFactionIndex ( i ) ;
}
}
gameSettingsReceived = true ;
}
}
break ;
2010-04-30 03:08:29 +02:00
case nmtPlayerIndexMessage :
{
PlayerIndexMessage playerIndexMessage ( - 1 ) ;
if ( receiveMessage ( & playerIndexMessage ) )
{
playerIndex = playerIndexMessage . getPlayerIndex ( ) ;
}
}
break ;
2010-03-16 22:37:11 +01:00
default :
2010-03-17 07:25:19 +01:00
{
string sErr = string ( __FILE__ ) + " :: " + string ( __FUNCTION__ ) + " Unexpected network message: " + intToStr ( networkMessageType ) ;
//throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType));
sendTextMessage ( " Unexpected network message: " + intToStr ( networkMessageType ) , - 1 ) ;
DisplayErrorMessage ( sErr ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-03-17 07:25:19 +01:00
}
2010-03-16 22:37:11 +01:00
}
}
void ClientInterface : : updateKeyframe ( int frameCount )
{
bool done = false ;
while ( ! done )
{
//wait for the next message
waitForMessage ( ) ;
//check we have an expected message
NetworkMessageType networkMessageType = getNextMessageType ( true ) ;
switch ( networkMessageType )
{
case nmtCommandList :
{
2010-04-15 03:19:00 +02:00
Chrono chrono ;
chrono . start ( ) ;
int waitCount = 0 ;
2010-03-16 22:37:11 +01:00
//make sure we read the message
NetworkMessageCommandList networkMessageCommandList ;
2010-04-15 03:19:00 +02:00
while ( receiveMessage ( & networkMessageCommandList ) = = false )
2010-03-16 22:37:11 +01:00
{
sleep ( waitSleepTime ) ;
2010-04-15 03:19:00 +02:00
waitCount + + ;
2010-03-16 22:37:11 +01:00
}
2010-04-15 03:19:00 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] receiveMessage took %d msecs, waitCount = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) , waitCount ) ;
chrono . start ( ) ;
2010-03-16 22:37:11 +01:00
//check that we are in the right frame
2010-04-15 03:19:00 +02:00
if ( networkMessageCommandList . getFrameCount ( ) ! = frameCount )
2010-03-16 22:37:11 +01:00
{
2010-03-17 07:25:19 +01:00
string sErr = " Network synchronization error, frame counts do not match " ;
//throw runtime_error("Network synchronization error, frame counts do not match");
sendTextMessage ( sErr , - 1 ) ;
DisplayErrorMessage ( sErr ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-03-17 07:25:19 +01:00
return ;
2010-03-16 22:37:11 +01:00
}
// give all commands
for ( int i = 0 ; i < networkMessageCommandList . getCommandCount ( ) ; + + i )
{
pendingCommands . push_back ( * networkMessageCommandList . getCommand ( i ) ) ;
}
2010-04-15 03:19:00 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] transfer network commands took %d msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-03-16 22:37:11 +01:00
done = true ;
}
break ;
case nmtQuit :
{
NetworkMessageQuit networkMessageQuit ;
if ( receiveMessage ( & networkMessageQuit ) )
{
quit = true ;
}
done = true ;
}
break ;
case nmtText :
{
NetworkMessageText networkMessageText ;
if ( receiveMessage ( & networkMessageText ) )
{
chatText = networkMessageText . getText ( ) ;
chatSender = networkMessageText . getSender ( ) ;
chatTeamIndex = networkMessageText . getTeamIndex ( ) ;
}
}
break ;
case nmtInvalid :
break ;
default :
2010-03-17 07:25:19 +01:00
{
//throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected message in client interface: " + intToStr(networkMessageType));
sendTextMessage ( " Unexpected message in client interface: " + intToStr ( networkMessageType ) , - 1 ) ;
DisplayErrorMessage ( string ( __FILE__ ) + " :: " + string ( __FUNCTION__ ) + " Unexpected message in client interface: " + intToStr ( networkMessageType ) ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-03-17 07:25:19 +01:00
}
2010-03-16 22:37:11 +01:00
}
}
}
void ClientInterface : : waitUntilReady ( Checksum * checksum )
{
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-16 22:37:11 +01:00
Logger & logger = Logger : : getInstance ( ) ;
Chrono chrono ;
chrono . start ( ) ;
// FOR TESTING ONLY - delay to see the client count up while waiting
//sleep(5000);
//send ready message
NetworkMessageReady networkMessageReady ;
sendMessage ( & networkMessageReady ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-16 22:37:11 +01:00
int64 lastMillisCheck = 0 ;
//wait until we get a ready message from the server
while ( true )
{
2010-04-12 22:32:47 +02:00
if ( isConnected ( ) = = false ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
string sErr = " Error, Server has disconnected! " ;
sendTextMessage ( sErr , - 1 ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-16 22:37:11 +01:00
2010-04-12 22:32:47 +02:00
DisplayErrorMessage ( sErr ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
quit = true ;
close ( ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
return ;
}
NetworkMessageType networkMessageType = getNextMessageType ( true ) ;
2010-03-16 22:37:11 +01:00
if ( networkMessageType = = nmtReady )
{
if ( receiveMessage ( & networkMessageReady ) )
{
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-16 22:37:11 +01:00
break ;
}
}
else if ( networkMessageType = = nmtInvalid )
{
if ( chrono . getMillis ( ) > readyWaitTimeout )
{
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 07:25:19 +01:00
//throw runtime_error("Timeout waiting for server");
string sErr = " Timeout waiting for server " ;
sendTextMessage ( sErr , - 1 ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 07:25:19 +01:00
DisplayErrorMessage ( sErr ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 07:25:19 +01:00
return ;
2010-03-16 22:37:11 +01:00
}
else
{
if ( chrono . getMillis ( ) / 1000 > lastMillisCheck )
{
lastMillisCheck = ( chrono . getMillis ( ) / 1000 ) ;
char szBuf [ 1024 ] = " " ;
sprintf ( szBuf , " Waiting for network: %llu seconds elapsed (maximum wait time: %d seconds) " , lastMillisCheck , int ( readyWaitTimeout / 1000 ) ) ;
logger . add ( szBuf , true ) ;
}
}
}
else
{
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 07:25:19 +01:00
//throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType) );
sendTextMessage ( " Unexpected network message: " + intToStr ( networkMessageType ) , - 1 ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 07:25:19 +01:00
DisplayErrorMessage ( string ( __FILE__ ) + " :: " + string ( __FUNCTION__ ) + " Unexpected network message: " + intToStr ( networkMessageType ) ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 07:25:19 +01:00
return ;
2010-03-16 22:37:11 +01:00
}
// sleep a bit
sleep ( waitSleepTime ) ;
}
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-16 22:37:11 +01:00
//check checksum
2010-03-17 14:22:08 +01:00
if ( networkMessageReady . getChecksum ( ) ! = checksum - > getSum ( ) )
2010-03-16 22:37:11 +01:00
{
2010-04-12 22:32:47 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-17 14:22:08 +01:00
string sErr = " Checksum error, you don't have the same data as the server " ;
sendTextMessage ( sErr , - 1 ) ;
2010-04-12 22:32:47 +02:00
2010-04-28 23:38:15 +02:00
string sErr1 = " Client Checksum: " + intToStr ( checksum - > getSum ( ) ) ;
sendTextMessage ( sErr1 , - 1 ) ;
string sErr2 = " Server Checksum: " + intToStr ( networkMessageReady . getChecksum ( ) ) ;
sendTextMessage ( sErr2 , - 1 ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d %s %s %s \n " , __FILE__ , __FUNCTION__ , __LINE__ , sErr . c_str ( ) , sErr1 . c_str ( ) , sErr2 . c_str ( ) ) ;
2010-04-12 22:32:47 +02:00
if ( Config : : getInstance ( ) . getBool ( " NetworkConsistencyChecks " ) ) {
// error message and disconnect only if checked
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-04-28 23:38:15 +02:00
string niceError = sErr + string ( " \n " ) + sErr1 + string ( " \n " ) + sErr2 ;
DisplayErrorMessage ( niceError ) ;
2010-04-12 22:32:47 +02:00
quit = true ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] Line: %d \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
close ( ) ;
}
2010-03-17 14:22:08 +01:00
return ;
2010-03-16 22:37:11 +01:00
}
2010-03-17 21:57:19 +01:00
2010-03-16 22:37:11 +01:00
//delay the start a bit, so clients have nore room to get messages
sleep ( GameConstants : : networkExtraLatency ) ;
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] END \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
}
void ClientInterface : : sendTextMessage ( const string & text , int teamIndex ) {
NetworkMessageText networkMessageText ( text , getHostName ( ) , teamIndex ) ;
sendMessage ( & networkMessageText ) ;
}
string ClientInterface : : getNetworkStatus ( ) const {
return Lang : : getInstance ( ) . get ( " Server " ) + " : " + serverName ;
}
void ClientInterface : : waitForMessage ( )
{
Chrono chrono ;
chrono . start ( ) ;
2010-04-15 03:19:00 +02:00
int waitLoopCount = 0 ;
2010-03-16 22:37:11 +01:00
while ( getNextMessageType ( true ) = = nmtInvalid )
{
if ( ! isConnected ( ) )
{
2010-03-17 07:25:19 +01:00
//throw runtime_error("Disconnected");
sendTextMessage ( " Disconnected " , - 1 ) ;
DisplayErrorMessage ( " Disconnected " ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-03-17 07:25:19 +01:00
return ;
2010-03-16 22:37:11 +01:00
}
if ( chrono . getMillis ( ) > messageWaitTimeout )
{
2010-03-17 07:25:19 +01:00
//throw runtime_error("Timeout waiting for message");
sendTextMessage ( " Timeout waiting for message " , - 1 ) ;
DisplayErrorMessage ( " Timeout waiting for message " ) ;
2010-03-17 21:57:19 +01:00
quit = true ;
close ( ) ;
2010-03-17 07:25:19 +01:00
return ;
2010-03-16 22:37:11 +01:00
}
sleep ( waitSleepTime ) ;
2010-04-15 03:19:00 +02:00
waitLoopCount + + ;
2010-03-16 22:37:11 +01:00
}
2010-04-15 03:19:00 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] waiting took %d msecs, waitLoopCount = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) , waitLoopCount ) ;
2010-03-16 22:37:11 +01:00
}
void ClientInterface : : quitGame ( bool userManuallyQuit )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
if ( clientSocket ! = NULL & & userManuallyQuit = = true )
{
2010-03-24 00:32:25 +01:00
string sQuitText = Config : : getInstance ( ) . getString ( " NetPlayerName " , Socket : : getHostName ( ) . c_str ( ) ) + " has chosen to leave the game! " ;
2010-03-16 22:37:11 +01:00
sendTextMessage ( sQuitText , - 1 ) ;
close ( ) ;
}
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] END \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
}
void ClientInterface : : close ( )
{
2010-03-20 00:26:00 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s] START \n " , __FILE__ , __FUNCTION__ ) ;
2010-03-16 22:37:11 +01:00
delete clientSocket ;
clientSocket = NULL ;
}
2010-04-01 08:31:10 +02:00
2010-04-02 04:33:32 +02:00
void ClientInterface : : discoverServers ( DiscoveredServersInterface * cb ) {
2010-04-01 08:31:10 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-04-02 04:33:32 +02:00
ClientSocket : : discoverServers ( cb ) ;
2010-04-01 08:31:10 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-04-02 04:33:32 +02:00
}
void ClientInterface : : stopServerDiscovery ( ) {
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-04-01 08:31:10 +02:00
2010-04-02 04:33:32 +02:00
ClientSocket : : stopBroadCastClientThread ( ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-04-01 08:31:10 +02:00
}
2010-04-29 01:59:37 +02:00
void ClientInterface : : sendSwitchSetupRequest ( string selectedFactionName , int8 currentFactionIndex , int8 toFactionIndex , int8 toTeam )
{
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
//printf("string-cuf-tof-team= %s-%d-%d-%d\n",selectedFactionName.c_str(),currentFactionIndex,toFactionIndex,toTeam);
SwitchSetupRequest message = SwitchSetupRequest ( selectedFactionName , currentFactionIndex , toFactionIndex , toTeam ) ;
sendMessage ( & message ) ;
SystemFlags : : OutputDebug ( SystemFlags : : debugNetwork , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
}
2010-03-27 08:09:34 +01:00
/*
2010-03-16 22:37:11 +01:00
bool ClientInterface : : getFogOfWar ( )
{
return Config : : getInstance ( ) . getBool ( " FogOfWar " ) ;
}
2010-03-27 08:09:34 +01:00
*/
2010-03-16 22:37:11 +01:00
} } //end namespace