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
|
|
|
|
|
const int ClientInterface::waitSleepTime= 50;
|
|
|
|
|
|
|
|
|
|
ClientInterface::ClientInterface(){
|
|
|
|
|
clientSocket= NULL;
|
|
|
|
|
launchGame= false;
|
|
|
|
|
introDone= false;
|
|
|
|
|
playerIndex= -1;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
string sQuitText = getHostName() + " has chosen to leave the game!";
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
string sQuitText = getHostName() + " has chosen to leave the game!";
|
|
|
|
|
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 21:57:19 +01:00
|
|
|
|
|
2010-03-17 14:22:08 +01:00
|
|
|
|
if(networkMessageIntro.getVersionString() != getNetworkVersionString())
|
2010-03-17 21:57:19 +01:00
|
|
|
|
//if(1)
|
2010-03-16 22:37:11 +01:00
|
|
|
|
{
|
2010-03-17 14:22:08 +01:00
|
|
|
|
string sErr = "Server and client binary mismatch!\nYou have to use the exactly same binaries!\n\nServer: " +
|
|
|
|
|
networkMessageIntro.getVersionString() +
|
|
|
|
|
"\nClient: " + getNetworkVersionString();
|
|
|
|
|
printf("%s\n",sErr.c_str());
|
|
|
|
|
|
|
|
|
|
sendTextMessage("Server and client binary mismatch!!",-1);
|
|
|
|
|
sendTextMessage(" Server:" + networkMessageIntro.getVersionString(),-1);
|
|
|
|
|
sendTextMessage(" Client: "+ getNetworkVersionString(),-1);
|
|
|
|
|
if(Config::getInstance().getBool("NetworkConsistencyChecks"))
|
|
|
|
|
{// 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
|
|
|
|
|
|
|
|
|
// check the checksum's
|
|
|
|
|
int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(string(GameConstants::folder_path_tilesets) + "/" +
|
|
|
|
|
networkMessageSynchNetworkGameData.getTileset() + "/*", ".xml", NULL);
|
|
|
|
|
|
|
|
|
|
this->setNetworkGameDataSynchCheckOkTile((tilesetCRC == networkMessageSynchNetworkGameData.getTilesetCRC()));
|
|
|
|
|
if(this->getNetworkGameDataSynchCheckOkTile() == false)
|
|
|
|
|
{
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] tilesetCRC mismatch, local = %d, remote = %d\n",
|
2010-03-16 22:37:11 +01:00
|
|
|
|
__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//tech, load before map because of resources
|
|
|
|
|
int32 techCRC = getFolderTreeContentsCheckSumRecursively(string(GameConstants::folder_path_techs) + "/" +
|
|
|
|
|
networkMessageSynchNetworkGameData.getTech() + "/*", ".xml", NULL);
|
|
|
|
|
|
|
|
|
|
this->setNetworkGameDataSynchCheckOkTech((techCRC == networkMessageSynchNetworkGameData.getTechCRC()));
|
|
|
|
|
|
|
|
|
|
if(this->getNetworkGameDataSynchCheckOkTech() == false)
|
|
|
|
|
{
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] techCRC mismatch, local = %d, remote = %d\n",
|
2010-03-16 22:37:11 +01:00
|
|
|
|
__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//map
|
|
|
|
|
Checksum checksum;
|
|
|
|
|
string file = Map::getMapPath(networkMessageSynchNetworkGameData.getMap());
|
|
|
|
|
checksum.addFile(file);
|
|
|
|
|
int32 mapCRC = checksum.getSum();
|
2010-03-20 00:26:00 +01:00
|
|
|
|
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),mapCRC);
|
2010-03-16 22:37:11 +01:00
|
|
|
|
|
|
|
|
|
this->setNetworkGameDataSynchCheckOkMap((mapCRC == networkMessageSynchNetworkGameData.getMapCRC()));
|
|
|
|
|
|
|
|
|
|
if(this->getNetworkGameDataSynchCheckOkMap() == false)
|
|
|
|
|
{
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] mapCRC mismatch, local = %d, remote = %d\n",
|
2010-03-16 22:37:11 +01:00
|
|
|
|
__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameData.getMapCRC());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this->setNetworkGameDataSynchCheckOkFogOfWar((getFogOfWar() == networkMessageSynchNetworkGameData.getFogOfWar()));
|
|
|
|
|
|
|
|
|
|
if(this->getNetworkGameDataSynchCheckOkFogOfWar() == false)
|
|
|
|
|
{
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] getFogOfWar mismatch, local = %d, remote = %d\n",
|
2010-03-16 22:37:11 +01:00
|
|
|
|
__FILE__,__FUNCTION__,getFogOfWar(),networkMessageSynchNetworkGameData.getFogOfWar());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetworkMessageSynchNetworkGameDataStatus sendNetworkMessageSynchNetworkGameDataStatus(mapCRC,tilesetCRC,techCRC,getFogOfWar());
|
|
|
|
|
sendMessage(&sendNetworkMessageSynchNetworkGameDataStatus);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
//make sure we read the message
|
|
|
|
|
NetworkMessageCommandList networkMessageCommandList;
|
|
|
|
|
while(!receiveMessage(&networkMessageCommandList))
|
|
|
|
|
{
|
|
|
|
|
sleep(waitSleepTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//check that we are in the right frame
|
|
|
|
|
if(networkMessageCommandList.getFrameCount()!=frameCount)
|
|
|
|
|
{
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-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
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
int64 lastMillisCheck = 0;
|
|
|
|
|
//wait until we get a ready message from the server
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
NetworkMessageType networkMessageType = getNextMessageType(true);
|
|
|
|
|
|
|
|
|
|
if(networkMessageType == nmtReady)
|
|
|
|
|
{
|
|
|
|
|
if(receiveMessage(&networkMessageReady))
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(networkMessageType == nmtInvalid)
|
|
|
|
|
{
|
|
|
|
|
if(chrono.getMillis() > readyWaitTimeout)
|
|
|
|
|
{
|
2010-03-17 07:25:19 +01:00
|
|
|
|
//throw runtime_error("Timeout waiting for server");
|
|
|
|
|
string sErr = "Timeout waiting for server";
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
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-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);
|
|
|
|
|
DisplayErrorMessage(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType));
|
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 a bit
|
|
|
|
|
sleep(waitSleepTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//check checksum
|
2010-03-17 14:22:08 +01:00
|
|
|
|
if(networkMessageReady.getChecksum() != checksum->getSum())
|
2010-03-17 21:57:19 +01:00
|
|
|
|
//if(1)
|
2010-03-16 22:37:11 +01:00
|
|
|
|
{
|
2010-03-17 14:22:08 +01:00
|
|
|
|
string sErr = "Checksum error, you don't have the same data as the server";
|
|
|
|
|
//throw runtime_error("Checksum error, you don't have the same data as the server");
|
|
|
|
|
sendTextMessage(sErr,-1);
|
|
|
|
|
if(Config::getInstance().getBool("NetworkConsistencyChecks"))
|
|
|
|
|
{// error message and disconnect only if checked
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
//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();
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
string sQuitText = getHostName() + " has chosen to leave the game!";
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ClientInterface::getFogOfWar()
|
|
|
|
|
{
|
|
|
|
|
return Config::getInstance().getBool("FogOfWar");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}}//end namespace
|