mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
2290 lines
105 KiB
C++
2290 lines
105 KiB
C++
// ==============================================================
|
|
// This file is part of Glest (www.glest.org)
|
|
//
|
|
// Copyright (C) 2001-2008 Martiño Figueroa
|
|
//
|
|
// 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 "logger.h"
|
|
#include "window.h"
|
|
|
|
#include "platform_util.h"
|
|
#include "game_util.h"
|
|
#include "conversion.h"
|
|
#include "config.h"
|
|
#include "lang.h"
|
|
#include "config.h"
|
|
#include <stdexcept>
|
|
#include <cassert>
|
|
|
|
#include "leak_dumper.h"
|
|
|
|
using namespace std;
|
|
using namespace Shared::Platform;
|
|
using namespace Shared::Util;
|
|
|
|
#ifdef WIN32
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#endif
|
|
|
|
namespace Glest{ namespace Game{
|
|
|
|
const bool debugClientInterfacePerf = false;
|
|
|
|
const int ClientInterface::messageWaitTimeout = 10000; //10 seconds
|
|
const int ClientInterface::waitSleepTime = 10;
|
|
const int ClientInterface::maxNetworkCommandListSendTimeWait = 5;
|
|
|
|
// =====================================================
|
|
// class ClientInterfaceThread
|
|
// =====================================================
|
|
|
|
ClientInterfaceThread::ClientInterfaceThread(ClientInterface *client) : BaseThread() {
|
|
this->clientInterface = client;
|
|
this->uniqueID = "ClientInterfaceThread";
|
|
}
|
|
|
|
ClientInterfaceThread::~ClientInterfaceThread() {
|
|
this->clientInterface = NULL;
|
|
}
|
|
|
|
void ClientInterfaceThread::setQuitStatus(bool value) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
|
|
|
|
BaseThread::setQuitStatus(value);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
bool ClientInterfaceThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
|
|
bool ret = (getExecutingTask() == false);
|
|
if(ret == false && deleteSelfIfShutdownDelayed == true) {
|
|
setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
|
|
deleteSelfIfRequired();
|
|
signalQuit();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ClientInterfaceThread::execute() {
|
|
RunningStatusSafeWrapper runningStatus(this);
|
|
try {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** STARTING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this);
|
|
|
|
// Set socket to non blocking
|
|
if(clientInterface != NULL && clientInterface->getSocket(true) != NULL) {
|
|
clientInterface->getSocket(true)->setBlock(false);
|
|
}
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("ClientInterfaceThread::exec Line: %d\n",__LINE__);
|
|
|
|
time_t clientSimulationLagStartTime = 0;
|
|
Chrono chrono;
|
|
for(;this->clientInterface != NULL;) {
|
|
|
|
if(getQuitStatus() == true) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
break;
|
|
}
|
|
|
|
ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
|
|
|
|
if(debugClientInterfacePerf == true) printf("START === Client thread\n");
|
|
|
|
//printf("ClientInterfaceThread::exec Line: %d\n",__LINE__);
|
|
|
|
uint64 loopCount = 0;
|
|
if(debugClientInterfacePerf == true) {
|
|
chrono.start();
|
|
}
|
|
while( this->getQuitStatus() == false &&
|
|
clientInterface != NULL) {
|
|
//printf("ClientInterfaceThread::exec Line: %d this->getQuitStatus(): %d\n",__LINE__,this->getQuitStatus());
|
|
|
|
// START: Test simulating lag for the client
|
|
int simulateLag = Config::getInstance().getInt("SimulateClientLag","0");
|
|
if(simulateLag > 0) {
|
|
if(clientSimulationLagStartTime == 0) {
|
|
clientSimulationLagStartTime = time(NULL);
|
|
}
|
|
if(difftime((long int)time(NULL),clientSimulationLagStartTime) <= Config::getInstance().getInt("SimulateClientLagDurationSeconds","0")) {
|
|
sleep(simulateLag);
|
|
}
|
|
}
|
|
// END: Test simulating lag for the client
|
|
|
|
clientInterface->updateNetworkFrame();
|
|
|
|
//printf("ClientInterfaceThread::exec Line: %d this->getQuitStatus(): %d\n",__LINE__,this->getQuitStatus());
|
|
|
|
if(debugClientInterfacePerf == true) {
|
|
loopCount++;
|
|
if(chrono.getMillis() >= 1000) {
|
|
printf("Client thread loopCount = %llu\n",(long long unsigned int)loopCount);
|
|
|
|
loopCount = 0;
|
|
//sleep(0);
|
|
chrono.start();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(debugClientInterfacePerf == true) {
|
|
printf("END === Client thread\n");
|
|
}
|
|
|
|
//printf("ClientInterfaceThread::exec Line: %d\n",__LINE__);
|
|
|
|
if(getQuitStatus() == true) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
break;
|
|
}
|
|
|
|
//printf("ClientInterfaceThread::exec Line: %d\n",__LINE__);
|
|
}
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("ClientInterfaceThread::exec Line: %d\n",__LINE__);
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** ENDING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this);
|
|
}
|
|
catch(const exception &ex) {
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
if(clientInterface == NULL || clientInterface->getSocket(true) == NULL || clientInterface->getSocket(true)->isConnected() == true) {
|
|
throw megaglest_runtime_error(ex.what());
|
|
}
|
|
}
|
|
catch(...) {
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
// =====================================================
|
|
// class ClientInterface
|
|
// =====================================================
|
|
|
|
ClientInterface::ClientInterface() : GameNetworkInterface() {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] constructor for %p\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this);
|
|
|
|
networkCommandListThreadAccessor = new Mutex(CODE_AT_LINE);
|
|
networkCommandListThread = NULL;
|
|
cachedPendingCommandsIndex = 0;
|
|
cachedLastPendingFrameCount = 0;
|
|
timeClientWaitedForLastMessage = 0;
|
|
|
|
flagAccessor = new Mutex(CODE_AT_LINE);
|
|
|
|
clientSocket = NULL;
|
|
sessionKey = 0;
|
|
launchGame = false;
|
|
introDone = false;
|
|
|
|
this->joinGameInProgress = false;
|
|
this->joinGameInProgressLaunch = false;
|
|
this->readyForInGameJoin = false;
|
|
this->resumeInGameJoin = false;
|
|
|
|
quitThreadAccessor = new Mutex(CODE_AT_LINE);
|
|
setQuitThread(false);
|
|
|
|
playerIndex = -1;
|
|
gameSettingsReceivedCount = 0;
|
|
setGameSettingsReceived(false);
|
|
gameSettingsReceivedCount = 0;
|
|
connectedTime = 0;
|
|
port = 0;
|
|
serverFTPPort = 0;
|
|
|
|
gotIntro = false;
|
|
lastNetworkCommandListSendTime = 0;
|
|
currentFrameCount = 0;
|
|
lastSentFrameCount = 0;
|
|
clientSimulationLagStartTime = 0;
|
|
|
|
networkGameDataSynchCheckOkMap = false;
|
|
networkGameDataSynchCheckOkTile = false;
|
|
networkGameDataSynchCheckOkTech = false;
|
|
this->setNetworkGameDataSynchCheckTechMismatchReport("");
|
|
this->setReceivedDataSynchCheck(false);
|
|
}
|
|
|
|
void ClientInterface::shutdownNetworkCommandListThread(MutexSafeWrapper &safeMutexWrapper) {
|
|
if(networkCommandListThread != NULL) {
|
|
//printf("START === shutdownNetworkCommandListThread\n");
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
setQuitThread(true);
|
|
networkCommandListThread->signalQuit();
|
|
safeMutexWrapper.ReleaseLock(true);
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
Chrono chronoElapsed(true);
|
|
for(;chronoElapsed.getMillis() <= 10000;) {
|
|
safeMutexWrapper.Lock();
|
|
if(networkCommandListThread != NULL &&
|
|
networkCommandListThread->canShutdown(false) == false &&
|
|
networkCommandListThread->getRunningStatus() == true) {
|
|
|
|
safeMutexWrapper.ReleaseLock(true);
|
|
if(chronoElapsed.getMillis() % 1000 == 0) {
|
|
sleep(1);
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
}
|
|
}
|
|
else {
|
|
safeMutexWrapper.ReleaseLock(true);
|
|
break;
|
|
}
|
|
//printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n chronoElapsed.getMillis(): %lld",__FUNCTION__,__LINE__,(long long int)chronoElapsed.getMillis());
|
|
//printf("A === shutdownNetworkCommandListThread\n");
|
|
|
|
safeMutexWrapper.Lock();
|
|
if(networkCommandListThread != NULL &&
|
|
networkCommandListThread->canShutdown(true)) {
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
delete networkCommandListThread;
|
|
networkCommandListThread = NULL;
|
|
}
|
|
else {
|
|
networkCommandListThread = NULL;
|
|
}
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
//printf("END === shutdownNetworkCommandListThread\n");
|
|
}
|
|
}
|
|
|
|
ClientInterface::~ClientInterface() {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] destructor for %p\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,this);
|
|
//printf("START === Client destructor\n");
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
shutdownNetworkCommandListThread(safeMutex);
|
|
//printf("A === Client destructor\n");
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
if(clientSocket != NULL &&
|
|
clientSocket->isConnected() == true) {
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int langIndex = 0; langIndex < languageList.size(); ++langIndex) {
|
|
|
|
string sQuitText = "has chosen to leave the game!";
|
|
if(lang.hasString("PlayerLeftGame",languageList[langIndex]) == true) {
|
|
sQuitText = lang.getString("PlayerLeftGame",languageList[langIndex]);
|
|
}
|
|
|
|
if(clientSocket != NULL && clientSocket->isConnected() == true) {
|
|
sendTextMessage(sQuitText,-1,false,languageList[langIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
//printf("B === Client destructor\n");
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
close(false);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
//printf("C === Client destructor\n");
|
|
|
|
networkCommandListThreadAccessor = NULL;
|
|
safeMutex.ReleaseLock(false,true);
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
|
|
delete flagAccessor;
|
|
flagAccessor = NULL;
|
|
//printf("END === Client destructor\n");
|
|
|
|
delete quitThreadAccessor;
|
|
quitThreadAccessor = NULL;
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s Line: %d\n",__FUNCTION__,__LINE__);
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
bool ClientInterface::getQuitThread() {
|
|
MutexSafeWrapper safeMutex(quitThreadAccessor,CODE_AT_LINE);
|
|
return this->quitThread;
|
|
}
|
|
void ClientInterface::setQuitThread(bool value) {
|
|
MutexSafeWrapper safeMutex(quitThreadAccessor,CODE_AT_LINE);
|
|
this->quitThread = value;
|
|
}
|
|
|
|
bool ClientInterface::getQuit() {
|
|
MutexSafeWrapper safeMutex(quitThreadAccessor,CODE_AT_LINE);
|
|
return this->quit;
|
|
}
|
|
void ClientInterface::setQuit(bool value) {
|
|
MutexSafeWrapper safeMutex(quitThreadAccessor,CODE_AT_LINE);
|
|
this->quit = value;
|
|
}
|
|
|
|
bool ClientInterface::getJoinGameInProgress() {
|
|
MutexSafeWrapper safeMutex(flagAccessor,CODE_AT_LINE);
|
|
return joinGameInProgress;
|
|
}
|
|
bool ClientInterface::getJoinGameInProgressLaunch() {
|
|
MutexSafeWrapper safeMutex(flagAccessor,CODE_AT_LINE);
|
|
return joinGameInProgressLaunch;
|
|
}
|
|
|
|
bool ClientInterface::getReadyForInGameJoin() {
|
|
MutexSafeWrapper safeMutex(flagAccessor,CODE_AT_LINE);
|
|
return readyForInGameJoin;
|
|
}
|
|
|
|
bool ClientInterface::getResumeInGameJoin() {
|
|
MutexSafeWrapper safeMutex(flagAccessor,CODE_AT_LINE);
|
|
return resumeInGameJoin;
|
|
}
|
|
|
|
void ClientInterface::connect(const Ip &ip, int port) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
this->ip = ip;
|
|
this->port = port;
|
|
|
|
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
shutdownNetworkCommandListThread(safeMutex);
|
|
|
|
delete clientSocket;
|
|
clientSocket = NULL;
|
|
|
|
safeMutex.ReleaseLock();
|
|
|
|
clientSocket = new ClientSocket();
|
|
clientSocket->setBlock(false);
|
|
clientSocket->connect(ip, port);
|
|
connectedTime = time(NULL);
|
|
//clientSocket->setBlock(true);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END - socket = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,clientSocket->getSocketId());
|
|
}
|
|
|
|
void ClientInterface::reset() {
|
|
if(getSocket() != NULL) {
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int langIndex = 0; langIndex < languageList.size(); ++langIndex) {
|
|
|
|
string sQuitText = "has chosen to leave the game!";
|
|
if(lang.hasString("PlayerLeftGame",languageList[langIndex]) == true) {
|
|
sQuitText = lang.getString("PlayerLeftGame",languageList[langIndex]);
|
|
}
|
|
sendTextMessage(sQuitText,-1,false,languageList[langIndex]);
|
|
}
|
|
close();
|
|
}
|
|
}
|
|
|
|
void ClientInterface::update() {
|
|
bool wasConnected = this->isConnected();
|
|
if(gotIntro == true &&
|
|
wasConnected == false) {
|
|
string playerNameStr = getHumanPlayerName();
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
|
|
char szBuf1[8096]="";
|
|
string statusTextFormat= lang.getString("PlayerDisconnected");
|
|
snprintf(szBuf1,8096,statusTextFormat.c_str(),playerNameStr.c_str());
|
|
|
|
DisplayErrorMessage(szBuf1);
|
|
setQuit(true);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
NetworkMessageCommandList networkMessageCommandList(currentFrameCount);
|
|
for(int index = 0; index < GameConstants::maxPlayers; ++index) {
|
|
networkMessageCommandList.setNetworkPlayerFactionCRC(index,this->getNetworkPlayerFactionCRC(index));
|
|
}
|
|
|
|
//send as many commands as we can
|
|
while(requestedCommands.empty() == false) {
|
|
if(networkMessageCommandList.addCommand(&requestedCommands.back())) {
|
|
requestedCommands.pop_back();
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
double lastSendElapsed = difftime((long int)time(NULL),lastNetworkCommandListSendTime);
|
|
|
|
// If we are on a frame that should send packets or we have commands
|
|
// to send now, send it now.
|
|
if((currentFrameCount >= this->gameSettings.getNetworkFramePeriod() &&
|
|
currentFrameCount % this->gameSettings.getNetworkFramePeriod() == 0) ||
|
|
networkMessageCommandList.getCommandCount() > 0) {
|
|
|
|
if(lastSentFrameCount < currentFrameCount ||
|
|
networkMessageCommandList.getCommandCount() > 0) {
|
|
|
|
lastSentFrameCount = currentFrameCount;
|
|
sendMessage(&networkMessageCommandList);
|
|
|
|
lastNetworkCommandListSendTime = time(NULL);
|
|
lastSendElapsed = 0;
|
|
}
|
|
}
|
|
|
|
// If we have not sent anything for maxNetworkCommandListSendTimeWait
|
|
// seconds, send one now.
|
|
if(lastNetworkCommandListSendTime > 0 &&
|
|
lastSendElapsed >= ClientInterface::maxNetworkCommandListSendTimeWait) {
|
|
|
|
lastSentFrameCount = currentFrameCount;
|
|
sendMessage(&networkMessageCommandList);
|
|
lastNetworkCommandListSendTime = time(NULL);
|
|
}
|
|
|
|
// Possible cause of out of synch since we have more commands that need
|
|
// to be sent in this frame
|
|
if(requestedCommands.empty() == false) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING / ERROR, requestedCommands.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,requestedCommands.size());
|
|
|
|
string sMsg = "may go out of synch: client requestedCommands.size() = " + intToStr(requestedCommands.size());
|
|
sendTextMessage(sMsg,-1, true,"");
|
|
sleep(1);
|
|
}
|
|
}
|
|
catch(const megaglest_runtime_error &ex) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
|
|
|
|
if(this->isConnected() == false) {
|
|
if(gotIntro == false || wasConnected == false) {
|
|
string sErr = string(extractFileFromDirectoryPath(__FILE__).c_str()) + "::" + string(__FUNCTION__) + " network error: " + string(ex.what());
|
|
DisplayErrorMessage(sErr);
|
|
}
|
|
|
|
setQuit(true);
|
|
}
|
|
else {
|
|
throw megaglest_runtime_error(ex.what());
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string ClientInterface::getIpAddress(bool mutexLock) {
|
|
string result = "";
|
|
//MutexSafeWrapper safeMutexSlot((mutexLock == true ? mutexSocket : NULL),CODE_AT_LINE);
|
|
if(clientSocket != NULL) {
|
|
result = clientSocket->getIpAddress();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::string ClientInterface::getServerIpAddress() {
|
|
return this->ip.getString();
|
|
}
|
|
|
|
void ClientInterface::updateLobby() {
|
|
Chrono chrono;
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
|
|
|
|
NetworkMessageType networkMessageType = getNextMessageType();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
switch(networkMessageType)
|
|
{
|
|
case nmtInvalid:
|
|
break;
|
|
|
|
case nmtIntro:
|
|
{
|
|
NetworkMessageIntro networkMessageIntro;
|
|
if(receiveMessage(&networkMessageIntro)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
gotIntro = true;
|
|
sessionKey = networkMessageIntro.getSessionId();
|
|
versionString = networkMessageIntro.getVersionString();
|
|
playerIndex = networkMessageIntro.getPlayerIndex();
|
|
serverName = networkMessageIntro.getName();
|
|
serverUUID = networkMessageIntro.getPlayerUUID();
|
|
serverPlatform = networkMessageIntro.getPlayerPlatform();
|
|
serverFTPPort = networkMessageIntro.getFtpPort();
|
|
|
|
if(playerIndex < 0 || playerIndex >= GameConstants::maxPlayers) {
|
|
throw megaglest_runtime_error("playerIndex < 0 || playerIndex >= GameConstants::maxPlayers");
|
|
}
|
|
|
|
MutexSafeWrapper safeMutexFlags(flagAccessor,CODE_AT_LINE);
|
|
this->joinGameInProgress = (networkMessageIntro.getGameInProgress() != 0);
|
|
this->joinGameInProgressLaunch = false;
|
|
safeMutexFlags.ReleaseLock();
|
|
|
|
//printf("Client got intro playerIndex = %d\n",playerIndex);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got NetworkMessageIntro, networkMessageIntro.getGameState() = %d, versionString [%s], sessionKey = %d, playerIndex = %d, serverFTPPort = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageIntro.getGameState(),versionString.c_str(),sessionKey,playerIndex,serverFTPPort);
|
|
|
|
//check consistency
|
|
bool compatible = checkVersionComptability(networkMessageIntro.getVersionString(), getNetworkVersionGITString());
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got NetworkMessageIntro, networkMessageIntro.getGameState() = %d, versionString [%s], sessionKey = %d, playerIndex = %d, serverFTPPort = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageIntro.getGameState(),versionString.c_str(),sessionKey,playerIndex,serverFTPPort);
|
|
|
|
if(compatible == false) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
bool versionMatched = false;
|
|
string platformFreeVersion = getNetworkPlatformFreeVersionString();
|
|
string sErr = "";
|
|
|
|
if(strncmp(platformFreeVersion.c_str(),networkMessageIntro.getVersionString().c_str(),strlen(platformFreeVersion.c_str())) != 0) {
|
|
string playerNameStr = getHumanPlayerName();
|
|
sErr = "Server and client binary mismatch!\nYou have to use the exactly same binaries!\n\nServer: " + networkMessageIntro.getVersionString() +
|
|
"\nClient: " + getNetworkVersionGITString() + " player [" + playerNameStr + "]";
|
|
printf("%s\n",sErr.c_str());
|
|
|
|
sendTextMessage("Server and client binary mismatch!!",-1, true,"");
|
|
sendTextMessage(" Server:" + networkMessageIntro.getVersionString(),-1, true,"");
|
|
sendTextMessage(" Client: "+ getNetworkVersionGITString(),-1, true,"");
|
|
sendTextMessage(" Client player [" + playerNameStr + "]",-1, true,"");
|
|
}
|
|
else {
|
|
versionMatched = true;
|
|
string playerNameStr = getHumanPlayerName();
|
|
sErr = "Warning, Server and client are using the same version but different platforms.\n\nServer: " + networkMessageIntro.getVersionString() +
|
|
"\nClient: " + getNetworkVersionGITString() + " player [" + playerNameStr + "]";
|
|
//printf("%s\n",sErr.c_str());
|
|
}
|
|
|
|
// error message and disconnect only if checked
|
|
if(Config::getInstance().getBool("PlatformConsistencyChecks","true") &&
|
|
versionMatched == false) {
|
|
|
|
DisplayErrorMessage(sErr);
|
|
sleep(1);
|
|
|
|
setQuit(true);
|
|
close();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
if(networkMessageIntro.getGameState() == nmgstOk) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
//send intro message
|
|
Lang &lang= Lang::getInstance();
|
|
NetworkMessageIntro sendNetworkMessageIntro(
|
|
sessionKey,getNetworkVersionGITString(),
|
|
getHumanPlayerName(),
|
|
-1,
|
|
nmgstOk,
|
|
this->getSocket()->getConnectedIPAddress(),
|
|
serverFTPPort,
|
|
lang.getLanguage(),
|
|
networkMessageIntro.getGameInProgress(),
|
|
Config::getInstance().getString("PlayerId",""),
|
|
getPlatformNameString());
|
|
sendMessage(&sendNetworkMessageIntro);
|
|
|
|
//printf("Got intro sending client details to server\n");
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
if(clientSocket == NULL ||
|
|
clientSocket->isConnected() == false) {
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
string sErr = "Disconnected from server during intro handshake.";
|
|
DisplayErrorMessage(sErr);
|
|
setQuit(true);
|
|
close();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
}
|
|
else {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
introDone = true;
|
|
}
|
|
}
|
|
else if(networkMessageIntro.getGameState() == nmgstNoSlots) {
|
|
string sErr = "Cannot join the server because there are no open slots for new players.";
|
|
DisplayErrorMessage(sErr);
|
|
setQuit(true);
|
|
close();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
}
|
|
else {
|
|
string sErr = "Unknown response from server: " + intToStr(networkMessageIntro.getGameState());
|
|
DisplayErrorMessage(sErr);
|
|
setQuit(true);
|
|
close();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
}
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtPing:
|
|
{
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
NetworkMessagePing networkMessagePing;
|
|
if(receiveMessage(&networkMessagePing)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
this->setLastPingInfo(networkMessagePing);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtSynchNetworkGameData:
|
|
{
|
|
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData;
|
|
|
|
if(receiveMessage(&networkMessageSynchNetworkGameData)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got NetworkMessageSynchNetworkGameData, getTechCRCFileCount() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageSynchNetworkGameData.getTechCRCFileCount());
|
|
|
|
this->setLastPingInfoToNow();
|
|
|
|
networkGameDataSynchCheckOkMap = false;
|
|
networkGameDataSynchCheckOkTile = false;
|
|
networkGameDataSynchCheckOkTech = false;
|
|
this->setNetworkGameDataSynchCheckTechMismatchReport("");
|
|
this->setReceivedDataSynchCheck(false);
|
|
|
|
uint32 tilesetCRC = 0;
|
|
uint32 techCRC = 0;
|
|
uint32 mapCRC = 0;
|
|
vector<std::pair<string,uint32> > vctFileList;
|
|
|
|
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);
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,gameSettings.getScenarioDir().c_str(),gameSettings.getScenario().c_str(),scenarioDir.c_str());
|
|
}
|
|
|
|
// check the checksum's
|
|
tilesetCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + networkMessageSynchNetworkGameData.getTileset() + string("/*"), ".xml", NULL);
|
|
|
|
this->setNetworkGameDataSynchCheckOkTile((tilesetCRC == networkMessageSynchNetworkGameData.getTilesetCRC()));
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] tilesetCRC info, local = %d, remote = %d, networkMessageSynchNetworkGameData.getTileset() = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC(),networkMessageSynchNetworkGameData.getTileset().c_str());
|
|
|
|
//tech, load before map because of resources
|
|
techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,scenarioDir), string("/") + networkMessageSynchNetworkGameData.getTech() + string("/*"), ".xml", NULL);
|
|
|
|
this->setNetworkGameDataSynchCheckOkTech((techCRC == networkMessageSynchNetworkGameData.getTechCRC()));
|
|
|
|
if(this->getNetworkGameDataSynchCheckOkTech() == false) {
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
string pathSearchString = "/" + networkMessageSynchNetworkGameData.getTech() + "/*";
|
|
vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),pathSearchString, ".xml", NULL);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
string report = networkMessageSynchNetworkGameData.getTechCRCFileMismatchReport(vctFileList);
|
|
this->setNetworkGameDataSynchCheckTechMismatchReport(report);
|
|
|
|
}
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] techCRC info, local = %d, remote = %d, networkMessageSynchNetworkGameData.getTech() = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC(),networkMessageSynchNetworkGameData.getTech().c_str());
|
|
|
|
//map
|
|
Checksum checksum;
|
|
string file = Config::getMapPath(networkMessageSynchNetworkGameData.getMap(),scenarioDir, false);
|
|
if(file != "") {
|
|
checksum.addFile(file);
|
|
mapCRC = checksum.getSum();
|
|
}
|
|
this->setNetworkGameDataSynchCheckOkMap((mapCRC == networkMessageSynchNetworkGameData.getMapCRC()));
|
|
this->setReceivedDataSynchCheck(true);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] mapCRC info, local = %d, remote = %d, file = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,mapCRC,networkMessageSynchNetworkGameData.getMapCRC(),file.c_str());
|
|
}
|
|
catch(const runtime_error &ex) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
|
|
string sErr = ex.what();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error during processing, sErr = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,sErr.c_str());
|
|
|
|
DisplayErrorMessage(sErr);
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
NetworkMessageSynchNetworkGameDataStatus sendNetworkMessageSynchNetworkGameDataStatus(mapCRC,tilesetCRC,techCRC,vctFileList);
|
|
sendMessage(&sendNetworkMessageSynchNetworkGameDataStatus);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtSynchNetworkGameDataFileCRCCheck:
|
|
{
|
|
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck;
|
|
if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
|
|
Checksum checksum;
|
|
string file = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName();
|
|
checksum.addFile(file);
|
|
uint32 fileCRC = checksum.getSum();
|
|
|
|
if(fileCRC != networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC()) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck localCRC = %d, remoteCRC = %d, file [%s]\n",
|
|
extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,fileCRC,
|
|
networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(),
|
|
networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str());
|
|
|
|
// Here we initiate a download of missing or mismatched content
|
|
|
|
NetworkMessageSynchNetworkGameDataFileGet sendNetworkMessageSynchNetworkGameDataFileGet(networkMessageSynchNetworkGameDataFileCRCCheck.getFileName());
|
|
sendMessage(&sendNetworkMessageSynchNetworkGameDataFileGet);
|
|
|
|
FileTransferInfo fileInfo;
|
|
fileInfo.hostType = eClient;
|
|
fileInfo.serverIP = this->ip.getString();
|
|
fileInfo.serverPort = this->port;
|
|
fileInfo.fileName = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName();
|
|
|
|
FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo);
|
|
fileXferThread->start();
|
|
}
|
|
|
|
if(networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() < networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount())
|
|
{
|
|
NetworkMessageSynchNetworkGameDataFileCRCCheck sendNetworkMessageSynchNetworkGameDataFileCRCCheck(
|
|
networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(),
|
|
networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() + 1,
|
|
0,
|
|
"");
|
|
sendMessage(&sendNetworkMessageSynchNetworkGameDataFileCRCCheck);
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtText:
|
|
{
|
|
NetworkMessageText networkMessageText;
|
|
if(receiveMessage(&networkMessageText)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtText\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),networkMessageText.getTargetLanguage());
|
|
this->addChatInfo(msg);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtMarkCell:
|
|
{
|
|
NetworkMessageMarkCell networkMessageMarkCell;
|
|
if(receiveMessage(&networkMessageMarkCell)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtMarkCell\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
MarkedCell msg(networkMessageMarkCell.getTarget(),
|
|
networkMessageMarkCell.getFactionIndex(),
|
|
networkMessageMarkCell.getText().c_str(),
|
|
networkMessageMarkCell.getPlayerIndex());
|
|
this->addMarkedCell(msg);
|
|
}
|
|
}
|
|
break;
|
|
case nmtUnMarkCell:
|
|
{
|
|
NetworkMessageUnMarkCell networkMessageMarkCell;
|
|
if(receiveMessage(&networkMessageMarkCell)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtMarkCell\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
UnMarkedCell msg(networkMessageMarkCell.getTarget(),
|
|
networkMessageMarkCell.getFactionIndex());
|
|
this->addUnMarkedCell(msg);
|
|
}
|
|
}
|
|
break;
|
|
case nmtHighlightCell:
|
|
{
|
|
NetworkMessageHighlightCell networkMessageHighlightCell;
|
|
if(receiveMessage(&networkMessageHighlightCell)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtHighlightCell\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
MarkedCell msg(networkMessageHighlightCell.getTarget(),
|
|
networkMessageHighlightCell.getFactionIndex(),
|
|
"none",-1);
|
|
this->setHighlightedCell(msg);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtLaunch:
|
|
case nmtBroadCastSetup:
|
|
{
|
|
//printf("#1 Got new game setup playerIndex = %d!\n",playerIndex);
|
|
|
|
NetworkMessageLaunch networkMessageLaunch;
|
|
if(receiveMessage(&networkMessageLaunch, networkMessageType)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
|
|
if(networkMessageLaunch.getMessageType() == nmtLaunch) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtLaunch\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtBroadCastSetup\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
else {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
|
|
|
|
char szBuf[1024]="";
|
|
snprintf(szBuf,1023,"In [%s::%s Line: %d] Invalid networkMessageLaunch.getMessageType() = %d",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
networkMessageLaunch.buildGameSettings(&gameSettings);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
//printf("Client got game settings playerIndex = %d lookingfor match...\n",playerIndex);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
|
|
//replace server player by network
|
|
for(int factionIndex = 0; factionIndex<gameSettings.getFactionCount(); ++factionIndex) {
|
|
|
|
//printf("Faction = %d start location = %d faction name = %s\n",i,gameSettings.getStartLocationIndex(factionIndex),gameSettings.getFactionTypeName(factionIndex).c_str());
|
|
|
|
//replace by network
|
|
if(gameSettings.getFactionControl(factionIndex) == ctHuman) {
|
|
gameSettings.setFactionControl(factionIndex, ctNetwork);
|
|
}
|
|
|
|
//printf("factionIndex = %d gameSettings.getStartLocationIndex(factionIndex) = %d playerIndex = %d, gameSettings.getFactionControl(factionIndex) = %d\n",factionIndex,gameSettings.getStartLocationIndex(factionIndex),playerIndex,gameSettings.getFactionControl(i));
|
|
|
|
//set the faction index
|
|
if(gameSettings.getStartLocationIndex(factionIndex) == playerIndex) {
|
|
//printf("Setting my factionindex to: %d for playerIndex: %d\n",i,playerIndex);
|
|
|
|
gameSettings.setThisFactionIndex(factionIndex);
|
|
|
|
//printf("Client got game settings playerIndex = %d factionIndex = %d control = %d name = %s\n",playerIndex,factionIndex,gameSettings.getFactionControl(factionIndex),gameSettings.getFactionTypeName(i).c_str());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] gameSettings.getThisFactionIndex(factionIndex) = %d, playerIndex = %d, factionIndex = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,gameSettings.getThisFactionIndex(),playerIndex,factionIndex);
|
|
}
|
|
}
|
|
|
|
if(networkMessageLaunch.getMessageType() == nmtLaunch) {
|
|
launchGame = true;
|
|
}
|
|
else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) {
|
|
setGameSettingsReceived(true);
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
}
|
|
}
|
|
break;
|
|
case nmtPlayerIndexMessage:
|
|
{
|
|
PlayerIndexMessage playerIndexMessage(-1);
|
|
if(receiveMessage(&playerIndexMessage)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
playerIndex= playerIndexMessage.getPlayerIndex();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtPlayerIndexMessage, playerIndex = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,playerIndex);
|
|
}
|
|
|
|
//printf("Got player index changed msg: %d\n",playerIndex);
|
|
}
|
|
break;
|
|
|
|
case nmtReady:
|
|
{
|
|
NetworkMessageReady networkMessageReady;
|
|
if(receiveMessage(&networkMessageReady)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
MutexSafeWrapper safeMutexFlags(flagAccessor,CODE_AT_LINE);
|
|
this->readyForInGameJoin = true;
|
|
}
|
|
|
|
//printf("ClientInterface got nmtReady this->readyForInGameJoin: %d\n",this->readyForInGameJoin);
|
|
}
|
|
break;
|
|
|
|
case nmtCommandList:
|
|
{
|
|
|
|
//make sure we read the message
|
|
//time_t receiveTimeElapsed = time(NULL);
|
|
NetworkMessageCommandList networkMessageCommandList;
|
|
bool gotCmd = receiveMessage(&networkMessageCommandList);
|
|
if(gotCmd == false) {
|
|
throw megaglest_runtime_error("error retrieving nmtCommandList returned false!");
|
|
}
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
}
|
|
break;
|
|
|
|
case nmtQuit:
|
|
{
|
|
//time_t receiveTimeElapsed = time(NULL);
|
|
NetworkMessageQuit networkMessageQuit;
|
|
bool gotCmd = receiveMessage(&networkMessageQuit);
|
|
if(gotCmd == false) {
|
|
throw megaglest_runtime_error("error retrieving nmtQuit returned false!");
|
|
}
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
setQuit(true);
|
|
close();
|
|
}
|
|
break;
|
|
|
|
case nmtLoadingStatusMessage:
|
|
{
|
|
NetworkMessageLoadingStatus networkMessageLoadingStatus(nmls_NONE);
|
|
if(receiveMessage(&networkMessageLoadingStatus)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
this->setLastPingInfoToNow();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
string sErr = string(extractFileFromDirectoryPath(__FILE__).c_str()) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType);
|
|
//throw megaglest_runtime_error(string(extractFileFromDirectoryPath(__FILE__).c_str()) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType));
|
|
sendTextMessage("Unexpected network message: " + intToStr(networkMessageType),-1, true,"");
|
|
DisplayErrorMessage(sErr);
|
|
sleep(1);
|
|
|
|
setQuit(true);
|
|
close();
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
|
|
if( clientSocket != NULL && clientSocket->isConnected() == true &&
|
|
gotIntro == false && difftime((long int)time(NULL),connectedTime) > GameConstants::maxClientConnectHandshakeSecs) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] difftime(time(NULL),connectedTime) = %f\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,difftime((long int)time(NULL),connectedTime));
|
|
close();
|
|
}
|
|
|
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
|
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
|
|
}
|
|
|
|
void ClientInterface::updateNetworkFrame() {
|
|
this->updateFrame(NULL);
|
|
}
|
|
|
|
void ClientInterface::updateFrame(int *checkFrame) {
|
|
//printf("#1 ClientInterface::updateFrame\n");
|
|
|
|
//printf("In updateFrame: %d\n",(checkFrame ? *checkFrame : -1));
|
|
|
|
if(isConnected() == true && getQuitThread() == false) {
|
|
//printf("#2 ClientInterface::updateFrame\n");
|
|
|
|
uint64 loopCount = 0;
|
|
Chrono chronoPerf;
|
|
if(debugClientInterfacePerf == true) {
|
|
chronoPerf.start();
|
|
}
|
|
|
|
int waitMicroseconds = (checkFrame == NULL ? 10 : 0);
|
|
|
|
bool done= false;
|
|
while(done == false && getQuitThread() == false) {
|
|
//printf("BEFORE Client get networkMessageType\n");
|
|
|
|
|
|
//wait for the next message
|
|
NetworkMessageType networkMessageType = waitForMessage(waitMicroseconds);
|
|
|
|
//printf("AFTER Client got networkMessageType = %d\n",networkMessageType);
|
|
|
|
//check we have an expected message
|
|
//NetworkMessageType networkMessageType= getNextMessageType();
|
|
|
|
//printf("Got Network networkMessageType: %d\n",networkMessageType);
|
|
|
|
switch(networkMessageType)
|
|
{
|
|
case nmtCommandList:
|
|
{
|
|
|
|
//make sure we read the message
|
|
//time_t receiveTimeElapsed = time(NULL);
|
|
NetworkMessageCommandList networkMessageCommandList;
|
|
bool gotCmd = receiveMessage(&networkMessageCommandList);
|
|
if(gotCmd == false) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] error retrieving nmtCommandList returned false!\n",__FILE__,__FUNCTION__,__LINE__);
|
|
if(isConnected() == false) {
|
|
setQuit(true);
|
|
close();
|
|
return;
|
|
}
|
|
|
|
throw megaglest_runtime_error("error retrieving nmtCommandList returned false!");
|
|
}
|
|
|
|
//printf("Client Thread getFrameCount(): %d getCommandCount(): %d\n",networkMessageCommandList.getFrameCount(),networkMessageCommandList.getCommandCount());
|
|
|
|
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
cachedLastPendingFrameCount = networkMessageCommandList.getFrameCount();
|
|
//printf("cachedLastPendingFrameCount = %lld\n",(long long int)cachedLastPendingFrameCount);
|
|
|
|
//check that we are in the right frame
|
|
if(checkFrame != NULL) {
|
|
if(networkMessageCommandList.getFrameCount() != *checkFrame) {
|
|
string sErr = "Player: " + getHumanPlayerName() +
|
|
" got a Network synchronization error, frame counts do not match, server frameCount = " +
|
|
intToStr(networkMessageCommandList.getFrameCount()) + ", local frameCount = " +
|
|
intToStr(*checkFrame);
|
|
sendTextMessage(sErr,-1, true,"");
|
|
DisplayErrorMessage(sErr);
|
|
sleep(1);
|
|
|
|
setQuit(true);
|
|
close();
|
|
return;
|
|
}
|
|
for(int index = 0; index < GameConstants::maxPlayers; ++index) {
|
|
printf("Frame: %d faction: %d local CRC: %u Remote CRC: %u\n",*checkFrame,index,getNetworkPlayerFactionCRC(index),networkMessageCommandList.getNetworkPlayerFactionCRC(index));
|
|
|
|
if(networkMessageCommandList.getNetworkPlayerFactionCRC(index) != getNetworkPlayerFactionCRC(index)) {
|
|
string sErr = "Player: " + getHumanPlayerName() +
|
|
" got a Network CRC error, CRC's do not match, server CRC = " +
|
|
uIntToStr(networkMessageCommandList.getNetworkPlayerFactionCRC(index)) + ", local CRC = " +
|
|
uIntToStr(getNetworkPlayerFactionCRC(index));
|
|
sendTextMessage(sErr,-1, true,"");
|
|
DisplayErrorMessage(sErr);
|
|
sleep(1);
|
|
|
|
setQuit(true);
|
|
close();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
cachedPendingCommands[networkMessageCommandList.getFrameCount()].reserve(networkMessageCommandList.getCommandCount());
|
|
|
|
// give all commands
|
|
for(int i= 0; i < networkMessageCommandList.getCommandCount(); ++i) {
|
|
//pendingCommands.push_back(*networkMessageCommandList.getCommand(i));
|
|
|
|
//if(networkMessageCommandList.getCommand(i)->getNetworkCommandType() == nctPauseResume) {
|
|
//printf("Network cmd type: %d [%d] frame: %d\n",networkMessageCommandList.getCommand(i)->getNetworkCommandType(),nctPauseResume,networkMessageCommandList.getFrameCount());
|
|
//}
|
|
|
|
cachedPendingCommands[networkMessageCommandList.getFrameCount()].push_back(*networkMessageCommandList.getCommand(i));
|
|
|
|
if(cachedPendingCommandCRCs.find(networkMessageCommandList.getFrameCount()) == cachedPendingCommandCRCs.end()) {
|
|
cachedPendingCommandCRCs[networkMessageCommandList.getFrameCount()].reserve(GameConstants::maxPlayers);
|
|
for(int index = 0; index < GameConstants::maxPlayers; ++index) {
|
|
cachedPendingCommandCRCs[networkMessageCommandList.getFrameCount()].push_back(networkMessageCommandList.getNetworkPlayerFactionCRC(index));
|
|
}
|
|
}
|
|
}
|
|
safeMutex.ReleaseLock();
|
|
|
|
done = true;
|
|
}
|
|
break;
|
|
|
|
case nmtPing:
|
|
{
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
NetworkMessagePing networkMessagePing;
|
|
if(receiveMessage(&networkMessagePing)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
this->setLastPingInfo(networkMessagePing);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtQuit:
|
|
{
|
|
NetworkMessageQuit networkMessageQuit;
|
|
bool gotCmd = receiveMessage(&networkMessageQuit);
|
|
if(gotCmd == false) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] error retrieving nmtQuit returned false!\n",__FILE__,__FUNCTION__,__LINE__);
|
|
if(isConnected() == false) {
|
|
setQuit(true);
|
|
close();
|
|
return;
|
|
}
|
|
|
|
throw megaglest_runtime_error("error retrieving nmtQuit returned false!");
|
|
}
|
|
setQuit(true);
|
|
done = true;
|
|
}
|
|
break;
|
|
|
|
case nmtText:
|
|
{
|
|
NetworkMessageText networkMessageText;
|
|
bool gotCmd = receiveMessage(&networkMessageText);
|
|
if(gotCmd == false) {
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] error retrieving nmtText returned false!\n",__FILE__,__FUNCTION__,__LINE__);
|
|
if(isConnected() == false) {
|
|
|
|
setQuit(true);
|
|
close();
|
|
return;
|
|
}
|
|
|
|
throw megaglest_runtime_error("error retrieving nmtText returned false!");
|
|
}
|
|
|
|
ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),networkMessageText.getTargetLanguage());
|
|
this->addChatInfo(msg);
|
|
}
|
|
break;
|
|
|
|
case nmtMarkCell:
|
|
{
|
|
NetworkMessageMarkCell networkMessageMarkCell;
|
|
if(receiveMessage(&networkMessageMarkCell)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtMarkCell\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
MarkedCell msg(networkMessageMarkCell.getTarget(),
|
|
networkMessageMarkCell.getFactionIndex(),
|
|
networkMessageMarkCell.getText().c_str(),
|
|
networkMessageMarkCell.getPlayerIndex());
|
|
this->addMarkedCell(msg);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case nmtUnMarkCell:
|
|
{
|
|
NetworkMessageUnMarkCell networkMessageMarkCell;
|
|
if(receiveMessage(&networkMessageMarkCell)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtMarkCell\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
UnMarkedCell msg(networkMessageMarkCell.getTarget(),
|
|
networkMessageMarkCell.getFactionIndex());
|
|
this->addUnMarkedCell(msg);
|
|
}
|
|
}
|
|
break;
|
|
case nmtHighlightCell:
|
|
{
|
|
NetworkMessageHighlightCell networkMessageHighlightCell;
|
|
if(receiveMessage(&networkMessageHighlightCell)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtHighlightCell\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
MarkedCell msg(networkMessageHighlightCell.getTarget(),
|
|
networkMessageHighlightCell.getFactionIndex(),
|
|
"none",-1);
|
|
this->setHighlightedCell(msg);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case nmtLaunch:
|
|
case nmtBroadCastSetup:
|
|
{
|
|
//printf("#2 Got new game setup playerIndex = %d!\n",playerIndex);
|
|
|
|
NetworkMessageLaunch networkMessageLaunch;
|
|
if(receiveMessage(&networkMessageLaunch,networkMessageType)) {
|
|
|
|
if(networkMessageLaunch.getMessageType() == nmtLaunch) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtLaunch\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtBroadCastSetup\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
else {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
|
|
|
|
char szBuf[1024]="";
|
|
snprintf(szBuf,1023,"In [%s::%s Line: %d] Invalid networkMessageLaunch.getMessageType() = %d",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
networkMessageLaunch.buildGameSettings(&gameSettings);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType());
|
|
//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);
|
|
}
|
|
|
|
//printf("i = %d gameSettings.getStartLocationIndex(i) = %d playerIndex = %d!\n",i,gameSettings.getStartLocationIndex(i),playerIndex);
|
|
|
|
//set the faction index
|
|
if(gameSettings.getStartLocationIndex(i) == playerIndex) {
|
|
//printf("Setting my factionindex to: %d for playerIndex: %d\n",i,playerIndex);
|
|
|
|
gameSettings.setThisFactionIndex(i);
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] gameSettings.getThisFactionIndex(i) = %d, playerIndex = %d, i = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,gameSettings.getThisFactionIndex(),playerIndex,i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case nmtLoadingStatusMessage:
|
|
break;
|
|
|
|
case nmtInvalid:
|
|
break;
|
|
|
|
default:
|
|
{
|
|
sendTextMessage("Unexpected message in client interface: " + intToStr(networkMessageType),-1, true,"");
|
|
DisplayErrorMessage(string(extractFileFromDirectoryPath(__FILE__).c_str()) + "::" + string(__FUNCTION__) + " Unexpected message in client interface: " + intToStr(networkMessageType));
|
|
sleep(1);
|
|
|
|
setQuit(true);
|
|
close();
|
|
done = true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(isConnected() == false && getQuit() == true) {
|
|
done = true;
|
|
}
|
|
|
|
if(debugClientInterfacePerf == true) {
|
|
loopCount++;
|
|
if(chronoPerf.getMillis() >= 1000) {
|
|
printf("Client updateFrame loopCount = %llu\n",(long long unsigned int)loopCount);
|
|
|
|
loopCount = 0;
|
|
//sleep(0);
|
|
chronoPerf.start();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(done == true) {
|
|
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
cachedPendingCommandsIndex++;
|
|
}
|
|
}
|
|
//printf("#3 ClientInterface::updateFrame\n");
|
|
}
|
|
|
|
uint64 ClientInterface::getCachedLastPendingFrameCount() {
|
|
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
uint64 result = cachedLastPendingFrameCount;
|
|
return result;
|
|
}
|
|
|
|
int64 ClientInterface::getTimeClientWaitedForLastMessage() {
|
|
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
uint64 result = timeClientWaitedForLastMessage;
|
|
return result;
|
|
}
|
|
|
|
bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPendingCommandsIndex) {
|
|
bool result = false;
|
|
bool waitForData = false;
|
|
uint64 copyCachedLastPendingFrameCount = 0;
|
|
uint64 waitCount = 0;
|
|
uint64 frameCountAsUInt64 = frameCount;
|
|
timeClientWaitedForLastMessage = 0;
|
|
|
|
//printf("In getNetworkCommand: %d [%d]\n",frameCount,currentCachedPendingCommandsIndex);
|
|
|
|
if(getQuit() == false && getQuitThread() == false) {
|
|
|
|
Chrono chrono;
|
|
MutexSafeWrapper safeMutex(NULL,CODE_AT_LINE);
|
|
|
|
for(;getQuit() == false && getQuitThread() == false;) {
|
|
|
|
if(safeMutex.isValidMutex() == false) {
|
|
safeMutex.setMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
}
|
|
else {
|
|
safeMutex.Lock();
|
|
}
|
|
copyCachedLastPendingFrameCount = cachedLastPendingFrameCount;
|
|
|
|
if(cachedPendingCommands.find(frameCount) != cachedPendingCommands.end()) {
|
|
|
|
Commands &frameCmdList = cachedPendingCommands[frameCount];
|
|
|
|
//printf("In getNetworkCommand frameCmdList.size(): %d\n",(int)frameCmdList.size());
|
|
|
|
if(frameCmdList.empty() == false) {
|
|
for(int index = 0; index < (int)frameCmdList.size(); ++index) {
|
|
pendingCommands.push_back(frameCmdList[index]);
|
|
}
|
|
cachedPendingCommands[frameCount].clear();
|
|
|
|
if(frameCount >= 0) {
|
|
for(int index = 0; index < GameConstants::maxPlayers; ++index) {
|
|
//printf("X**X Frame: %d faction: %d local CRC: %u Remote CRC: %u\n",frameCount,index,getNetworkPlayerFactionCRC(index),cachedPendingCommandCRCs[frameCount][index]);
|
|
|
|
if(cachedPendingCommandCRCs[frameCount][index] != getNetworkPlayerFactionCRC(index)) {
|
|
|
|
printf("X**X Frame: %d faction: %d local CRC: %u Remote CRC: %u\n",frameCount,index,getNetworkPlayerFactionCRC(index),cachedPendingCommandCRCs[frameCount][index]);
|
|
|
|
string sErr = "Player: " + getHumanPlayerName() +
|
|
" got a Network CRC error, CRC's do not match, server CRC = " +
|
|
uIntToStr(cachedPendingCommandCRCs[frameCount][index]) + ", local CRC = " +
|
|
uIntToStr(getNetworkPlayerFactionCRC(index));
|
|
sendTextMessage(sErr,-1, true,"");
|
|
DisplayErrorMessage(sErr);
|
|
sleep(1);
|
|
|
|
setQuit(true);
|
|
close();
|
|
}
|
|
}
|
|
}
|
|
cachedPendingCommandCRCs.erase(frameCount);
|
|
}
|
|
if(waitForData == true) {
|
|
timeClientWaitedForLastMessage = chrono.getMillis();
|
|
chrono.stop();
|
|
}
|
|
safeMutex.ReleaseLock(true);
|
|
|
|
result = true;
|
|
break;
|
|
}
|
|
else {
|
|
safeMutex.ReleaseLock(true);
|
|
// No data for this frame
|
|
if(waitForData == false) {
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Client waiting for packet for frame: %d, copyCachedLastPendingFrameCount = %lld\n",frameCount,(long long int)copyCachedLastPendingFrameCount);
|
|
chrono.start();
|
|
}
|
|
if(copyCachedLastPendingFrameCount > frameCountAsUInt64) {
|
|
break;
|
|
}
|
|
|
|
if(waitForData == false) {
|
|
waitForData = true;
|
|
sleep(0);
|
|
}
|
|
|
|
waitCount++;
|
|
//printf("Client waiting for packet for frame: %d, currentCachedPendingCommandsIndex = %d, cachedPendingCommandsIndex = %lld\n",frameCount,currentCachedPendingCommandsIndex,(long long int)cachedPendingCommandsIndex);
|
|
}
|
|
}
|
|
}
|
|
if(waitForData == true) {
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Client waiting for packet FINISHED for frame: %d, copyCachedLastPendingFrameCount = %lld waitCount = %llu\n",frameCount,(long long int)copyCachedLastPendingFrameCount,(long long unsigned int)waitCount);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void ClientInterface::updateKeyframe(int frameCount) {
|
|
currentFrameCount = frameCount;
|
|
|
|
//printf("In updateKeyFrame: %d\n",currentFrameCount);
|
|
|
|
if(getQuit() == false && getQuitThread() == false) {
|
|
if(networkCommandListThread == NULL) {
|
|
static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
|
|
networkCommandListThread = new ClientInterfaceThread(this);
|
|
networkCommandListThread->setUniqueID(mutexOwnerId);
|
|
networkCommandListThread->start();
|
|
|
|
sleep(0);
|
|
}
|
|
|
|
getNetworkCommand(frameCount,cachedPendingCommandsIndex);
|
|
}
|
|
}
|
|
|
|
bool ClientInterface::isMasterServerAdminOverride() {
|
|
return (gameSettings.getMasterserver_admin() == this->getSessionKey());
|
|
}
|
|
|
|
void ClientInterface::waitUntilReady(Checksum* checksum) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
MutexSafeWrapper safeMutexFlags(flagAccessor,CODE_AT_LINE);
|
|
bool signalServerWhenReadyToStartJoinedGame = this->readyForInGameJoin;
|
|
this->readyForInGameJoin = false;
|
|
safeMutexFlags.ReleaseLock();
|
|
|
|
Logger &logger= Logger::getInstance();
|
|
|
|
Chrono chrono;
|
|
chrono.start();
|
|
|
|
// FOR TESTING ONLY - delay to see the client count up while waiting
|
|
//sleep(5000);
|
|
|
|
//clientSocket->setBlock(true);
|
|
//send ready message
|
|
NetworkMessageReady networkMessageReady;
|
|
sendMessage(&networkMessageReady);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
NetworkMessageLoadingStatus networkMessageLoadingStatus(nmls_NONE);
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
|
|
int64 lastMillisCheck = 0;
|
|
uint64 waitLoopIterationCount = 0;
|
|
uint64 MAX_LOOP_COUNT_BEFORE_SLEEP = 100;
|
|
MAX_LOOP_COUNT_BEFORE_SLEEP = Config::getInstance().getInt("NetworkClientLoopGameLoadingCap",intToStr(MAX_LOOP_COUNT_BEFORE_SLEEP).c_str());
|
|
if(MAX_LOOP_COUNT_BEFORE_SLEEP == 0) {
|
|
MAX_LOOP_COUNT_BEFORE_SLEEP = 1;
|
|
}
|
|
int sleepMillis = Config::getInstance().getInt("NetworkClientLoopGameLoadingCapSleepMillis","10");
|
|
|
|
//wait until we get a ready message from the server
|
|
while(true) {
|
|
// FOR TESTING ONLY - delay to see the client count up while waiting
|
|
//sleep(2000);
|
|
|
|
waitLoopIterationCount++;
|
|
if(waitLoopIterationCount > 0 &&
|
|
waitLoopIterationCount % MAX_LOOP_COUNT_BEFORE_SLEEP == 0) {
|
|
sleep(sleepMillis);
|
|
waitLoopIterationCount = 0;
|
|
}
|
|
|
|
if(isConnected() == false) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
string sErr = "Error, Server has disconnected!";
|
|
DisplayErrorMessage(sErr);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
setQuit(true);
|
|
close();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
}
|
|
NetworkMessageType networkMessageType = getNextMessageType();
|
|
|
|
// consume old messages from the lobby
|
|
bool discarded = shouldDiscardNetworkMessage(networkMessageType);
|
|
if(discarded == false) {
|
|
if(networkMessageType == nmtReady) {
|
|
if(receiveMessage(&networkMessageReady)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
break;
|
|
}
|
|
}
|
|
else if(networkMessageType == nmtLoadingStatusMessage) {
|
|
if(receiveMessage(&networkMessageLoadingStatus)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
}
|
|
else if(networkMessageType == nmtQuit) {
|
|
NetworkMessageQuit networkMessageQuit;
|
|
if(receiveMessage(&networkMessageQuit)) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
DisplayErrorMessage(lang.getString("GameCancelledByUser"));
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
setQuit(true);
|
|
close();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
|
|
}
|
|
}
|
|
else if(networkMessageType == nmtCommandList) {
|
|
//make sure we read the message
|
|
NetworkMessageCommandList networkMessageCommandList;
|
|
bool gotCmd = receiveMessage(&networkMessageCommandList);
|
|
if(gotCmd == false) {
|
|
throw megaglest_runtime_error("error retrieving nmtCommandList returned false!");
|
|
}
|
|
}
|
|
else if(networkMessageType == nmtInvalid) {
|
|
if(chrono.getMillis() > readyWaitTimeout) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int i = 0; i < languageList.size(); ++i) {
|
|
string sErr = "Timeout waiting for server";
|
|
if(lang.hasString("TimeoutWaitingForServer",languageList[i]) == true) {
|
|
sErr = lang.getString("TimeoutWaitingForServer",languageList[i]);
|
|
}
|
|
bool echoLocal = lang.isLanguageLocal(lang.getLanguage());
|
|
sendTextMessage(sErr,-1,echoLocal,languageList[i]);
|
|
|
|
if(echoLocal) {
|
|
DisplayErrorMessage(sErr);
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
sleep(1);
|
|
setQuit(true);
|
|
close();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
}
|
|
else {
|
|
if(chrono.getMillis() % 100 == 0) {
|
|
lastMillisCheck = (chrono.getMillis() / 1000);
|
|
|
|
char szBuf[8096]="";
|
|
string updateTextFormat = "Waiting for network: %lld seconds elapsed (maximum wait time: %d seconds)";
|
|
if(lang.hasString("NetworkGameClientLoadStatus") == true) {
|
|
updateTextFormat = lang.getString("NetworkGameClientLoadStatus");
|
|
}
|
|
|
|
string waitForHosts = "";
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER1_CONNECTED) == nmls_PLAYER1_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER1_READY) != nmls_PLAYER1_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(0);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER2_CONNECTED) == nmls_PLAYER2_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER2_READY) != nmls_PLAYER2_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(1);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER3_CONNECTED) == nmls_PLAYER3_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER3_READY) != nmls_PLAYER3_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(2);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER4_CONNECTED) == nmls_PLAYER4_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER4_READY) != nmls_PLAYER4_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(3);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER5_CONNECTED) == nmls_PLAYER5_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER5_READY) != nmls_PLAYER5_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(4);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER6_CONNECTED) == nmls_PLAYER6_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER6_READY) != nmls_PLAYER6_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(5);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER7_CONNECTED) == nmls_PLAYER7_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER7_READY) != nmls_PLAYER7_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(6);
|
|
}
|
|
}
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER8_CONNECTED) == nmls_PLAYER8_CONNECTED) {
|
|
if((networkMessageLoadingStatus.getStatus() & nmls_PLAYER8_READY) != nmls_PLAYER8_READY) {
|
|
if(waitForHosts != "") {
|
|
waitForHosts += ", ";
|
|
}
|
|
waitForHosts += gameSettings.getNetworkPlayerNameByPlayerIndex(7);
|
|
}
|
|
}
|
|
|
|
if(waitForHosts == "") {
|
|
waitForHosts = lang.getString("Server");
|
|
}
|
|
snprintf(szBuf,8096,updateTextFormat.c_str(),(long long int)lastMillisCheck,int(readyWaitTimeout / 1000));
|
|
|
|
char szBuf1[8096]="";
|
|
string statusTextFormat = "Waiting for players: %s";
|
|
if(lang.hasString("NetworkGameStatusWaiting") == true) {
|
|
statusTextFormat = lang.getString("NetworkGameStatusWaiting");
|
|
}
|
|
snprintf(szBuf1,8096,statusTextFormat.c_str(),waitForHosts.c_str());
|
|
|
|
logger.add(szBuf, true, szBuf1);
|
|
|
|
sleep(0);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
sendTextMessage("Unexpected network message: " + intToStr(networkMessageType),-1, true,"");
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
DisplayErrorMessage(string(extractFileFromDirectoryPath(__FILE__).c_str()) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType));
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
sleep(1);
|
|
setQuit(true);
|
|
close();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
return;
|
|
}
|
|
|
|
Shared::Platform::Window::handleEvent();
|
|
// sleep a bit
|
|
sleep(waitSleepTime);
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
//check checksum
|
|
if(getJoinGameInProgress() == false &&
|
|
networkMessageReady.getChecksum() != checksum->getSum()) {
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int langIndex = 0; langIndex < languageList.size(); ++langIndex) {
|
|
|
|
string sErr = "Checksum error, you don't have the same data as the server";
|
|
if(lang.hasString("CheckSumGameLoadError",languageList[langIndex]) == true) {
|
|
sErr = lang.getString("CheckSumGameLoadError",languageList[langIndex]);
|
|
}
|
|
bool echoLocal = lang.isLanguageLocal(lang.getLanguage());
|
|
sendTextMessage(sErr,-1,echoLocal,languageList[langIndex]);
|
|
|
|
string playerNameStr = "Player with error is: " + getHumanPlayerName();
|
|
if(lang.hasString("CheckSumGameLoadPlayer",languageList[langIndex]) == true) {
|
|
playerNameStr = lang.getString("CheckSumGameLoadPlayer",languageList[langIndex]) + " " + getHumanPlayerName();
|
|
}
|
|
sendTextMessage(playerNameStr,-1,echoLocal,languageList[langIndex]);
|
|
|
|
string sErr1 = "Client Checksum: " + intToStr(checksum->getSum());
|
|
if(lang.hasString("CheckSumGameLoadClient",languageList[langIndex]) == true) {
|
|
sErr1 = lang.getString("CheckSumGameLoadClient",languageList[langIndex]) + " " + intToStr(checksum->getSum());
|
|
}
|
|
|
|
sendTextMessage(sErr1,-1,echoLocal,languageList[langIndex]);
|
|
|
|
string sErr2 = "Server Checksum: " + intToStr(networkMessageReady.getChecksum());
|
|
if(lang.hasString("CheckSumGameLoadServer",languageList[langIndex]) == true) {
|
|
sErr2 = lang.getString("CheckSumGameLoadServer",languageList[langIndex]) + " " + intToStr(networkMessageReady.getChecksum());
|
|
}
|
|
sendTextMessage(sErr2,-1,echoLocal,languageList[langIndex]);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d %s %s %s\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,sErr.c_str(),sErr1.c_str(),sErr2.c_str());
|
|
|
|
if(echoLocal == true) {
|
|
if(Config::getInstance().getBool("NetworkConsistencyChecks")) {
|
|
// error message and disconnect only if checked
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
string niceError = sErr + string("\n") + sErr1 + string("\n") + sErr2;
|
|
DisplayErrorMessage(niceError);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Config::getInstance().getBool("NetworkConsistencyChecks")) {
|
|
// error message and disconnect only if checked
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
sleep(1);
|
|
setQuit(true);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
close();
|
|
}
|
|
return;
|
|
}
|
|
|
|
MutexSafeWrapper safeMutexFlags2(flagAccessor,CODE_AT_LINE);
|
|
this->joinGameInProgress = false;
|
|
this->joinGameInProgressLaunch = false;
|
|
|
|
//printf("Client signalServerWhenReadyToStartJoinedGame = %d\n",signalServerWhenReadyToStartJoinedGame);
|
|
if(signalServerWhenReadyToStartJoinedGame == true) {
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int langIndex = 0; langIndex < languageList.size(); ++langIndex) {
|
|
|
|
string sText = "Player: %s is joining the game now.";
|
|
if(lang.hasString("JoinPlayerToCurrentGameLaunchDone",languageList[langIndex]) == true) {
|
|
sText = lang.getString("JoinPlayerToCurrentGameLaunchDone",languageList[langIndex]);
|
|
}
|
|
|
|
if(clientSocket != NULL && clientSocket->isConnected() == true) {
|
|
string playerNameStr = getHumanPlayerName();
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,sText.c_str(),playerNameStr.c_str());
|
|
|
|
sendTextMessage(szBuf,-1,false,languageList[langIndex]);
|
|
}
|
|
}
|
|
|
|
this->resumeInGameJoin = true;
|
|
safeMutexFlags2.ReleaseLock();
|
|
}
|
|
else {
|
|
safeMutexFlags2.ReleaseLock();
|
|
// delay the start a bit, so clients have more room to get messages
|
|
// This is to ensure clients don't start ahead of the server and thus
|
|
// constantly freeze because they are waiting for the server to catch up
|
|
sleep(120);
|
|
}
|
|
|
|
// This triggers LAG update packets to begin as required
|
|
lastNetworkCommandListSendTime = time(NULL);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
}
|
|
|
|
void ClientInterface::sendResumeGameMessage() {
|
|
NetworkMessageReady networkMessageReady;
|
|
sendMessage(&networkMessageReady);
|
|
}
|
|
|
|
void ClientInterface::sendTextMessage(const string &text, int teamIndex, bool echoLocal,
|
|
string targetLanguage) {
|
|
|
|
string humanPlayerName = getHumanPlayerName();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] humanPlayerName = [%s] playerIndex = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,humanPlayerName.c_str(),playerIndex);
|
|
|
|
NetworkMessageText networkMessageText(text, teamIndex,playerIndex,targetLanguage);
|
|
sendMessage(&networkMessageText);
|
|
|
|
if(echoLocal == true) {
|
|
ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),targetLanguage);
|
|
this->addChatInfo(msg);
|
|
}
|
|
}
|
|
|
|
void ClientInterface::sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note,int playerIndex) {
|
|
string humanPlayerName = getHumanPlayerName();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] humanPlayerName = [%s] playerIndex = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,humanPlayerName.c_str(),playerIndex);
|
|
|
|
NetworkMessageMarkCell networkMessageMarkCell(targetPos,factionIndex, note,playerIndex);
|
|
sendMessage(&networkMessageMarkCell);
|
|
}
|
|
|
|
void ClientInterface::sendHighlightCellMessage(Vec2i targetPos, int factionIndex) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,playerIndex);
|
|
|
|
NetworkMessageHighlightCell networkMessageHighlightCell(targetPos,factionIndex);
|
|
sendMessage(&networkMessageHighlightCell);
|
|
}
|
|
|
|
void ClientInterface::sendUnMarkCellMessage(Vec2i targetPos, int factionIndex) {
|
|
string humanPlayerName = getHumanPlayerName();
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] humanPlayerName = [%s] playerIndex = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,humanPlayerName.c_str(),playerIndex);
|
|
|
|
NetworkMessageUnMarkCell networkMessageMarkCell(targetPos,factionIndex);
|
|
sendMessage(&networkMessageMarkCell);
|
|
}
|
|
|
|
void ClientInterface::sendPingMessage(int32 pingFrequency, int64 pingTime) {
|
|
NetworkMessagePing networkMessagePing(pingFrequency,pingTime);
|
|
sendMessage(&networkMessagePing);
|
|
}
|
|
|
|
string ClientInterface::getNetworkStatus() {
|
|
std::string label = Lang::getInstance().getString("Server") + ": " + serverName;
|
|
//float pingTime = getThreadedPingMS(getServerIpAddress().c_str());
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"%s",label.c_str());
|
|
|
|
return szBuf;
|
|
}
|
|
|
|
NetworkMessageType ClientInterface::waitForMessage(int waitMicroseconds)
|
|
{
|
|
// Debug!
|
|
/*
|
|
sendTextMessage("Timeout waiting for message",-1);
|
|
DisplayErrorMessage("Timeout waiting for message");
|
|
quit= true;
|
|
close();
|
|
return;
|
|
*/
|
|
|
|
uint64 loopCount = 0;
|
|
Chrono chronoPerf;
|
|
if(debugClientInterfacePerf == true) {
|
|
chronoPerf.start();
|
|
}
|
|
|
|
Chrono chrono;
|
|
chrono.start();
|
|
|
|
NetworkMessageType msg = nmtInvalid;
|
|
while( msg == nmtInvalid &&
|
|
getQuitThread() == false) {
|
|
|
|
msg = getNextMessageType(waitMicroseconds);
|
|
if(msg == nmtInvalid) {
|
|
if(getSocket() == NULL || (chrono.getMillis() % 250 == 0 && isConnected() == false)) {
|
|
if(getQuit() == false) {
|
|
//throw megaglest_runtime_error("Disconnected");
|
|
//sendTextMessage("Server has Disconnected.",-1);
|
|
DisplayErrorMessage("Server has Disconnected.");
|
|
setQuit(true);
|
|
}
|
|
close();
|
|
return msg;
|
|
}
|
|
|
|
if(chrono.getMillis() > messageWaitTimeout) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int langIndex = 0; langIndex < languageList.size(); ++langIndex) {
|
|
|
|
string msg = "Timeout waiting for message.";
|
|
if(lang.hasString("TimeoutWaitingForMessage",languageList[langIndex]) == true) {
|
|
msg = lang.getString("TimeoutWaitingForMessage",languageList[langIndex]);
|
|
}
|
|
|
|
sendTextMessage(msg,-1, lang.isLanguageLocal(languageList[langIndex]),languageList[langIndex]);
|
|
if(lang.isLanguageLocal(languageList[langIndex]) == true) {
|
|
DisplayErrorMessage(msg);
|
|
}
|
|
}
|
|
|
|
sleep(1);
|
|
setQuit(true);
|
|
close();
|
|
return msg;
|
|
}
|
|
// Sleep every x milli-seconds we wait to let other threads work
|
|
else if(chrono.getMillis() % 2 == 0) {
|
|
sleep(1);
|
|
}
|
|
else {
|
|
sleep(0);
|
|
}
|
|
}
|
|
|
|
if(debugClientInterfacePerf == true) {
|
|
loopCount++;
|
|
if(chronoPerf.getMillis() >= 100) {
|
|
printf("Client waitForMessage loopCount = %llu\n",(long long unsigned int)loopCount);
|
|
|
|
loopCount = 0;
|
|
chronoPerf.start();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] waiting took %lld msecs, msg = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),msg);
|
|
|
|
return msg;
|
|
}
|
|
|
|
void ClientInterface::quitGame(bool userManuallyQuit)
|
|
{
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] userManuallyQuit = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,userManuallyQuit);
|
|
|
|
if(clientSocket != NULL && userManuallyQuit == true) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
Lang &lang= Lang::getInstance();
|
|
const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
|
|
for(unsigned int langIndex = 0; langIndex < languageList.size(); ++langIndex) {
|
|
|
|
string msg = "has chosen to leave the game!";
|
|
if(lang.hasString("PlayerLeftGame",languageList[langIndex]) == true) {
|
|
msg = lang.getString("PlayerLeftGame",languageList[langIndex]);
|
|
}
|
|
|
|
sendTextMessage(msg,-1, lang.isLanguageLocal(languageList[langIndex]),languageList[langIndex]);
|
|
}
|
|
sleep(1);
|
|
close();
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void ClientInterface::close(bool lockMutex) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] START, clientSocket = %p\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,clientSocket);
|
|
|
|
MutexSafeWrapper safeMutex(NULL,CODE_AT_LINE);
|
|
if(lockMutex == true) {
|
|
safeMutex.setMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
|
|
}
|
|
shutdownNetworkCommandListThread(safeMutex);
|
|
|
|
delete clientSocket;
|
|
clientSocket = NULL;
|
|
|
|
safeMutex.ReleaseLock();
|
|
|
|
connectedTime = 0;
|
|
gotIntro = false;
|
|
|
|
MutexSafeWrapper safeMutexFlags(flagAccessor,CODE_AT_LINE);
|
|
this->joinGameInProgress = false;
|
|
this->joinGameInProgressLaunch = false;
|
|
this->readyForInGameJoin = false;
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] END\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void ClientInterface::close() {
|
|
close(true);
|
|
}
|
|
|
|
void ClientInterface::discoverServers(DiscoveredServersInterface *cb) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
ClientSocket::discoverServers(cb);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
void ClientInterface::stopServerDiscovery() {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
ClientSocket::stopBroadCastClientThread();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void ClientInterface::sendSwitchSetupRequest(string selectedFactionName, int8 currentSlotIndex,
|
|
int8 toSlotIndex,int8 toTeam, string networkPlayerName,
|
|
int8 networkPlayerStatus, int8 flags,
|
|
string language) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] networkPlayerName [%s] flags = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkPlayerName.c_str(),flags);
|
|
SwitchSetupRequest message = SwitchSetupRequest(selectedFactionName,
|
|
currentSlotIndex, toSlotIndex,toTeam,networkPlayerName,
|
|
networkPlayerStatus, flags,language);
|
|
sendMessage(&message);
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
bool ClientInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMessageType) {
|
|
bool discard = false;
|
|
|
|
switch(networkMessageType) {
|
|
case nmtIntro:
|
|
{
|
|
discard = true;
|
|
NetworkMessageIntro msg = NetworkMessageIntro();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtPing:
|
|
{
|
|
discard = true;
|
|
NetworkMessagePing msg = NetworkMessagePing();
|
|
this->receiveMessage(&msg);
|
|
this->setLastPingInfo(msg);
|
|
}
|
|
break;
|
|
case nmtLaunch:
|
|
{
|
|
discard = true;
|
|
NetworkMessageLaunch msg = NetworkMessageLaunch();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtText:
|
|
{
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtText\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
discard = true;
|
|
NetworkMessageText netMsg = NetworkMessageText();
|
|
this->receiveMessage(&netMsg);
|
|
|
|
ChatMsgInfo msg(netMsg.getText().c_str(),netMsg.getTeamIndex(),netMsg.getPlayerIndex(),netMsg.getTargetLanguage());
|
|
this->addChatInfo(msg);
|
|
}
|
|
break;
|
|
|
|
case nmtMarkCell:
|
|
{
|
|
discard = true;
|
|
NetworkMessageMarkCell networkMessageMarkCell;
|
|
receiveMessage(&networkMessageMarkCell);
|
|
|
|
MarkedCell msg(networkMessageMarkCell.getTarget(),
|
|
networkMessageMarkCell.getFactionIndex(),
|
|
networkMessageMarkCell.getText().c_str(),
|
|
networkMessageMarkCell.getPlayerIndex());
|
|
this->addMarkedCell(msg);
|
|
}
|
|
break;
|
|
|
|
case nmtUnMarkCell:
|
|
{
|
|
discard = true;
|
|
NetworkMessageUnMarkCell networkMessageMarkCell;
|
|
receiveMessage(&networkMessageMarkCell);
|
|
|
|
UnMarkedCell msg(networkMessageMarkCell.getTarget(),
|
|
networkMessageMarkCell.getFactionIndex());
|
|
this->addUnMarkedCell(msg);
|
|
}
|
|
break;
|
|
|
|
case nmtHighlightCell:
|
|
{
|
|
discard = true;
|
|
NetworkMessageHighlightCell networkMessageHighlightCell;
|
|
receiveMessage(&networkMessageHighlightCell);
|
|
|
|
MarkedCell msg(networkMessageHighlightCell.getTarget(),
|
|
networkMessageHighlightCell.getFactionIndex(),
|
|
"none",-1);
|
|
this->setHighlightedCell(msg);
|
|
}
|
|
break;
|
|
|
|
case nmtSynchNetworkGameData:
|
|
{
|
|
discard = true;
|
|
NetworkMessageSynchNetworkGameData msg = NetworkMessageSynchNetworkGameData();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtSynchNetworkGameDataStatus:
|
|
{
|
|
discard = true;
|
|
NetworkMessageSynchNetworkGameDataStatus msg = NetworkMessageSynchNetworkGameDataStatus();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtSynchNetworkGameDataFileCRCCheck:
|
|
{
|
|
discard = true;
|
|
NetworkMessageSynchNetworkGameDataFileCRCCheck msg = NetworkMessageSynchNetworkGameDataFileCRCCheck();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtSynchNetworkGameDataFileGet:
|
|
{
|
|
discard = true;
|
|
NetworkMessageSynchNetworkGameDataFileGet msg = NetworkMessageSynchNetworkGameDataFileGet();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtSwitchSetupRequest:
|
|
{
|
|
discard = true;
|
|
SwitchSetupRequest msg = SwitchSetupRequest();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
case nmtBroadCastSetup:
|
|
{
|
|
discard = true;
|
|
NetworkMessageLaunch msg = NetworkMessageLaunch();
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
|
|
case nmtPlayerIndexMessage:
|
|
{
|
|
discard = true;
|
|
PlayerIndexMessage msg = PlayerIndexMessage(0);
|
|
this->receiveMessage(&msg);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return discard;
|
|
}
|
|
|
|
string ClientInterface::getHumanPlayerName(int index) {
|
|
string result = Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str());
|
|
|
|
if(index >= 0 || gameSettings.getThisFactionIndex() >= 0) {
|
|
if(index < 0) {
|
|
index = gameSettings.getThisFactionIndex();
|
|
}
|
|
if(gameSettings.getNetworkPlayerName(index) != "") {
|
|
result = gameSettings.getNetworkPlayerName(index);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void ClientInterface::setGameSettings(GameSettings *serverGameSettings) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
|
|
gameSettings = *serverGameSettings;
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
|
|
}
|
|
|
|
void ClientInterface::broadcastGameSetup(const GameSettings *gameSettings) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
NetworkMessageLaunch networkMessageLaunch(gameSettings, nmtBroadCastSetup);
|
|
sendMessage(&networkMessageLaunch);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void ClientInterface::broadcastGameStart(const GameSettings *gameSettings) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
MutexSafeWrapper safeMutexFlags(flagAccessor,CODE_AT_LINE);
|
|
if(this->joinGameInProgress == true) {
|
|
this->joinGameInProgressLaunch = true;
|
|
}
|
|
safeMutexFlags.ReleaseLock();
|
|
|
|
//printf("Sending game launch joinGameInProgress: %d\n",joinGameInProgress);
|
|
|
|
NetworkMessageLaunch networkMessageLaunch(gameSettings, nmtLaunch);
|
|
sendMessage(&networkMessageLaunch);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void ClientInterface::setGameSettingsReceived(bool value) {
|
|
//printf("In [%s:%s] Line: %d gameSettingsReceived = %d value = %d, gameSettingsReceivedCount = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,gameSettingsReceived,value,gameSettingsReceivedCount);
|
|
gameSettingsReceived = value;
|
|
gameSettingsReceivedCount++;
|
|
}
|
|
|
|
}}//end namespace
|