Bugfixes for network game launching:
- discard inprogress messages that don't apply during launch - added better error handling of disconnects during game launch and play on both server and clients
This commit is contained in:
parent
acf4bebba6
commit
4b1a392f00
|
@ -405,7 +405,7 @@ void ClientInterface::updateKeyframe(int frameCount)
|
|||
{
|
||||
bool done= false;
|
||||
|
||||
while(!done)
|
||||
while(done == false)
|
||||
{
|
||||
//wait for the next message
|
||||
waitForMessage();
|
||||
|
@ -489,13 +489,17 @@ void ClientInterface::updateKeyframe(int frameCount)
|
|||
DisplayErrorMessage(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected message in client interface: " + intToStr(networkMessageType));
|
||||
quit= true;
|
||||
close();
|
||||
done= true;
|
||||
}
|
||||
}
|
||||
|
||||
if(isConnected() == false && quit == true) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::waitUntilReady(Checksum* checksum)
|
||||
{
|
||||
void ClientInterface::waitUntilReady(Checksum* checksum) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
Logger &logger= Logger::getInstance();
|
||||
|
@ -514,15 +518,15 @@ void ClientInterface::waitUntilReady(Checksum* checksum)
|
|||
|
||||
int64 lastMillisCheck = 0;
|
||||
//wait until we get a ready message from the server
|
||||
while(true)
|
||||
{
|
||||
while(true) {
|
||||
|
||||
if(isConnected() == false) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
string sErr = "Error, Server has disconnected!";
|
||||
sendTextMessage(sErr,-1);
|
||||
//sendTextMessage(sErr,-1);
|
||||
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
DisplayErrorMessage(sErr);
|
||||
|
||||
|
@ -535,18 +539,14 @@ void ClientInterface::waitUntilReady(Checksum* checksum)
|
|||
return;
|
||||
}
|
||||
NetworkMessageType networkMessageType = getNextMessageType(true);
|
||||
if(networkMessageType == nmtReady)
|
||||
{
|
||||
if(receiveMessage(&networkMessageReady))
|
||||
{
|
||||
if(networkMessageType == nmtReady) {
|
||||
if(receiveMessage(&networkMessageReady)) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(networkMessageType == nmtInvalid)
|
||||
{
|
||||
if(chrono.getMillis() > readyWaitTimeout)
|
||||
{
|
||||
else if(networkMessageType == nmtInvalid) {
|
||||
if(chrono.getMillis() > readyWaitTimeout) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//throw runtime_error("Timeout waiting for server");
|
||||
string sErr = "Timeout waiting for server";
|
||||
|
@ -564,10 +564,8 @@ void ClientInterface::waitUntilReady(Checksum* checksum)
|
|||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(chrono.getMillis() / 1000 > lastMillisCheck)
|
||||
{
|
||||
else {
|
||||
if(chrono.getMillis() / 1000 > lastMillisCheck) {
|
||||
lastMillisCheck = (chrono.getMillis() / 1000);
|
||||
|
||||
char szBuf[1024]="";
|
||||
|
@ -576,8 +574,7 @@ void ClientInterface::waitUntilReady(Checksum* checksum)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType) );
|
||||
sendTextMessage("Unexpected network message: " + intToStr(networkMessageType),-1);
|
||||
|
@ -602,8 +599,7 @@ void ClientInterface::waitUntilReady(Checksum* checksum)
|
|||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
//check checksum
|
||||
if(networkMessageReady.getChecksum() != checksum->getSum())
|
||||
{
|
||||
if(networkMessageReady.getChecksum() != checksum->getSum()) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
string sErr = "Checksum error, you don't have the same data as the server";
|
||||
|
@ -633,8 +629,7 @@ void ClientInterface::waitUntilReady(Checksum* checksum)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
//delay the start a bit, so clients have nore room to get messages
|
||||
//delay the start a bit, so clients have more room to get messages
|
||||
sleep(GameConstants::networkExtraLatency);
|
||||
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
|
@ -657,11 +652,11 @@ void ClientInterface::waitForMessage()
|
|||
int waitLoopCount = 0;
|
||||
while(getNextMessageType(true) == nmtInvalid)
|
||||
{
|
||||
if(!isConnected())
|
||||
if(isConnected() == false)
|
||||
{
|
||||
//throw runtime_error("Disconnected");
|
||||
sendTextMessage("Disconnected",-1);
|
||||
DisplayErrorMessage("Disconnected");
|
||||
sendTextMessage("Server has Disconnected.",-1);
|
||||
DisplayErrorMessage("Server has Disconnected.");
|
||||
quit= true;
|
||||
close();
|
||||
return;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Glest{ namespace Game{
|
|||
|
||||
class GameSettings;
|
||||
|
||||
enum NetworkMessageType{
|
||||
enum NetworkMessageType {
|
||||
nmtInvalid,
|
||||
nmtIntro,
|
||||
nmtPing,
|
||||
|
@ -51,7 +51,7 @@ const int32 commandListHeaderSize = 6;
|
|||
// class NetworkMessage
|
||||
// =====================================================
|
||||
|
||||
class NetworkMessage{
|
||||
class NetworkMessage {
|
||||
public:
|
||||
virtual ~NetworkMessage(){}
|
||||
virtual bool receive(Socket* socket)= 0;
|
||||
|
|
|
@ -280,6 +280,79 @@ void ServerInterface::updateKeyframe(int frameCount){
|
|||
SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] broadcastMessage took %d msecs, networkMessageCommandList.getCommandCount() = %d, frameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),networkMessageCommandList.getCommandCount(),frameCount);
|
||||
}
|
||||
|
||||
bool ServerInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMessageType,
|
||||
ConnectionSlot* connectionSlot) {
|
||||
bool discard = false;
|
||||
if(connectionSlot != NULL) {
|
||||
switch(networkMessageType) {
|
||||
case nmtIntro:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageIntro msg = NetworkMessageIntro();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtLaunch:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageLaunch msg = NetworkMessageLaunch();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtText:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageText msg = NetworkMessageText();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtSynchNetworkGameData:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageSynchNetworkGameData msg = NetworkMessageSynchNetworkGameData();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtSynchNetworkGameDataStatus:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageSynchNetworkGameDataStatus msg = NetworkMessageSynchNetworkGameDataStatus();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtSynchNetworkGameDataFileCRCCheck:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageSynchNetworkGameDataFileCRCCheck msg = NetworkMessageSynchNetworkGameDataFileCRCCheck();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtSynchNetworkGameDataFileGet:
|
||||
{
|
||||
discard = true;
|
||||
NetworkMessageSynchNetworkGameDataFileGet msg = NetworkMessageSynchNetworkGameDataFileGet();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtSwitchSetupRequest:
|
||||
{
|
||||
discard = true;
|
||||
SwitchSetupRequest msg = SwitchSetupRequest();
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
case nmtPlayerIndexMessage:
|
||||
{
|
||||
discard = true;
|
||||
PlayerIndexMessage msg = PlayerIndexMessage(0);
|
||||
connectionSlot->receiveMessage(&msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return discard;
|
||||
}
|
||||
|
||||
void ServerInterface::waitUntilReady(Checksum* checksum){
|
||||
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] START\n",__FUNCTION__);
|
||||
|
@ -293,44 +366,33 @@ void ServerInterface::waitUntilReady(Checksum* checksum){
|
|||
chrono.start();
|
||||
|
||||
//wait until we get a ready message from all clients
|
||||
while(allReady == false)
|
||||
{
|
||||
while(allReady == false) {
|
||||
vector<string> waitingForHosts;
|
||||
allReady= true;
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected() == true)
|
||||
{
|
||||
if(connectionSlot->isReady() == false)
|
||||
{
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
|
||||
if(connectionSlot->isReady() == false) {
|
||||
NetworkMessageType networkMessageType= connectionSlot->getNextMessageType(true);
|
||||
NetworkMessageReady networkMessageReady;
|
||||
|
||||
// consume old messages from the setup
|
||||
while(networkMessageType == nmtSwitchSetupRequest)
|
||||
{
|
||||
SwitchSetupRequest switchSetupRequest;
|
||||
connectionSlot->receiveMessage(&switchSetupRequest);
|
||||
networkMessageType= connectionSlot->getNextMessageType(true);
|
||||
}
|
||||
if(networkMessageType == nmtReady &&
|
||||
connectionSlot->receiveMessage(&networkMessageReady))
|
||||
{
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] networkMessageType==nmtReady\n",__FUNCTION__);
|
||||
// consume old messages from the lobby
|
||||
bool discarded = shouldDiscardNetworkMessage(networkMessageType,connectionSlot);
|
||||
if(discarded == false) {
|
||||
NetworkMessageReady networkMessageReady;
|
||||
if(networkMessageType == nmtReady &&
|
||||
connectionSlot->receiveMessage(&networkMessageReady)) {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] networkMessageType==nmtReady\n",__FUNCTION__);
|
||||
|
||||
connectionSlot->setReady();
|
||||
connectionSlot->setReady();
|
||||
}
|
||||
else if(networkMessageType != nmtInvalid) {
|
||||
//throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
|
||||
string sErr = "Unexpected network message: " + intToStr(networkMessageType);
|
||||
sendTextMessage(sErr,-1);
|
||||
DisplayErrorMessage(sErr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(networkMessageType != nmtInvalid)
|
||||
{
|
||||
//throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
|
||||
string sErr = "Unexpected network message: " + intToStr(networkMessageType);
|
||||
sendTextMessage(sErr,-1);
|
||||
DisplayErrorMessage(sErr);
|
||||
return;
|
||||
}
|
||||
|
||||
//waitingForHosts.push_back(connectionSlot->getHostName());
|
||||
waitingForHosts.push_back(connectionSlot->getName());
|
||||
|
||||
|
@ -340,25 +402,19 @@ void ServerInterface::waitUntilReady(Checksum* checksum){
|
|||
}
|
||||
|
||||
//check for timeout
|
||||
if(allReady == false)
|
||||
{
|
||||
if(chrono.getMillis() > readyWaitTimeout)
|
||||
{
|
||||
if(allReady == false) {
|
||||
if(chrono.getMillis() > readyWaitTimeout) {
|
||||
//throw runtime_error("Timeout waiting for clients");
|
||||
string sErr = "Timeout waiting for clients.";
|
||||
sendTextMessage(sErr,-1);
|
||||
DisplayErrorMessage(sErr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(chrono.getMillis() % 1000 == 0)
|
||||
{
|
||||
else {
|
||||
if(chrono.getMillis() % 1000 == 0) {
|
||||
string waitForHosts = "";
|
||||
for(int i = 0; i < waitingForHosts.size(); i++)
|
||||
{
|
||||
if(waitForHosts != "")
|
||||
{
|
||||
for(int i = 0; i < waitingForHosts.size(); i++) {
|
||||
if(waitForHosts != "") {
|
||||
waitForHosts += ", ";
|
||||
}
|
||||
waitForHosts += waitingForHosts[i];
|
||||
|
@ -372,20 +428,16 @@ void ServerInterface::waitUntilReady(Checksum* checksum){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// FOR TESTING ONLY - delay to see the client count up while waiting
|
||||
//sleep(5000);
|
||||
|
||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] PART B (telling client we are ready!\n",__FUNCTION__);
|
||||
|
||||
//send ready message after, so clients start delayed
|
||||
for(int i= 0; i < GameConstants::maxPlayers; ++i)
|
||||
{
|
||||
NetworkMessageReady networkMessageReady(checksum->getSum());
|
||||
|
||||
for(int i= 0; i < GameConstants::maxPlayers; ++i) {
|
||||
ConnectionSlot* connectionSlot= slots[i];
|
||||
if(connectionSlot!=NULL)
|
||||
{
|
||||
if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
|
||||
NetworkMessageReady networkMessageReady(checksum->getSum());
|
||||
connectionSlot->sendMessage(&networkMessageReady);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ private:
|
|||
void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1);
|
||||
void updateListen();
|
||||
void broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot = -1);
|
||||
bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType,ConnectionSlot* connectionSlot);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
|
|
@ -143,6 +143,28 @@ void deleteMapValues(T beginIt, T endIt){
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
class create_map
|
||||
{
|
||||
private:
|
||||
std::map<T, U> m_map;
|
||||
public:
|
||||
create_map(const T& key, const U& val)
|
||||
{
|
||||
m_map[key] = val;
|
||||
}
|
||||
|
||||
create_map<T, U>& operator()(const T& key, const U& val)
|
||||
{
|
||||
m_map[key] = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator std::map<T, U>()
|
||||
{
|
||||
return m_map;
|
||||
}
|
||||
};
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user