diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 7b89f976..993ffbcf 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -74,6 +74,7 @@ Game::Game() : ProgramState(NULL) { lastUpdateFps=0; avgUpdateFps=0; framesToCatchUpAsClient=0; + framesToSlowDownAsClient=0; totalRenderFps=0; renderFps=0; lastRenderFps=0; @@ -161,6 +162,10 @@ Game::Game() : ProgramState(NULL) { lastNetworkPlayerConnectionCheck = time(NULL); inJoinGameLoading = false; + for( int i=0;i(networkManager.getClientInterface()); if(clientInterface != NULL) { uint64 lastNetworkFrameFromServer = clientInterface->getCachedLastPendingFrameCount(); -// if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > (world.getFrameCount() + gameSettings.getNetworkFramePeriod())+1) { -// //if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) { -// int frameDifference = ((lastNetworkFrameFromServer - world.getFrameCount()) / gameSettings.getNetworkFramePeriod()) * gameSettings.getNetworkFramePeriod(); -// -// //int frameDifference = lastNetworkFrameFromServer - world.getFrameCount(); - if(framesToCatchUpAsClient==0){ - if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > (world.getFrameCount() + gameSettings.getNetworkFramePeriod()/4)) { - //if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) { - int frameDifference = lastNetworkFrameFromServer - world.getFrameCount(); - printf("Client will speed up: %d frames lastNetworkFrameFromServer: %lld world.getFrameCount() = %d updateLoops = %d\n",frameDifference,(long long int)lastNetworkFrameFromServer,world.getFrameCount(),updateLoops); - framesToCatchUpAsClient=frameDifference; - // done below now: updateLoops += frameDifference; +//// if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > (world.getFrameCount() + gameSettings.getNetworkFramePeriod())+1) { +//// //if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) { +//// int frameDifference = ((lastNetworkFrameFromServer - world.getFrameCount()) / gameSettings.getNetworkFramePeriod()) * gameSettings.getNetworkFramePeriod(); +//// +//// //int frameDifference = lastNetworkFrameFromServer - world.getFrameCount(); +// if(framesToCatchUpAsClient==0){ +// if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > (world.getFrameCount() + gameSettings.getNetworkFramePeriod()/4)) { +// //if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) { +// int frameDifference = lastNetworkFrameFromServer - world.getFrameCount(); +// printf("Client will speed up: %d frames lastNetworkFrameFromServer: %lld world.getFrameCount() = %d updateLoops = %d\n",frameDifference,(long long int)lastNetworkFrameFromServer,world.getFrameCount(),updateLoops); +// framesToCatchUpAsClient=frameDifference; +// // done below now: updateLoops += frameDifference; +// } +// } +//// //If client is ahead maybe this fixes it ( by titi ): +// if(updateLoops!=0 && lastNetworkFrameFromServer > 0 && world.getFrameCount() > lastNetworkFrameFromServer && (world.getFrameCount()%GameConstants::updateFps)>38 ){ +// printf("Client will slow down because no message has arrived yet. currentFrame=%d \n",world.getFrameCount()); +// updateLoops = 0; +// } + + ///////////////////////////////// + // TTTT new attempt to make things smoother: + /////////////// + + //////////////////////////////////////////// + //get stats of received/waiting for packages + //////////////////////////////////////////// + // calculate current receive Index slot: + int index = (world.getFrameCount() + - (world.getFrameCount() + % gameSettings.getNetworkFramePeriod()) + / gameSettings.getNetworkFramePeriod()) + % GameConstants::networkSmoothInterval; + + if(frameWhenMessageWasReceived[index]==-1){ + // we need to check if we already received something for next frame + if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) { + frameWhenMessageWasReceived[index]= lastNetworkFrameFromServer-world.getFrameCount(); + } } -// //If client is ahead maybe this fixes it ( by titi ): - if(updateLoops!=0 && lastNetworkFrameFromServer > 0 && world.getFrameCount() > lastNetworkFrameFromServer && (world.getFrameCount()%GameConstants::updateFps)>38 ){ - printf("Client will slow down because no message has arrived yet. currentFrame=%d \n",world.getFrameCount()); - updateLoops = 0; + if(frameWhenMessageWasReceived[index]==-1){ + // calc time waiting for message in milliseconds to frames + framesNeededToWaitForServerMessage[index]=clientInterface->getTimeClientWaitedForLastMessage()/1000/GameConstants::updateFps; + } + + //////////////////////////////////////////// + //use the recorded stats of received/waiting for packages + //////////////////////////////////////////// + //lets see if the client is in front and had to wait for messages ... + + //lets see if all last recorded frames where received too early + int minimum=0; + int allowedMaxFallback=5; + int countOfMessagesReceivedTooEarly=0; + int countOfMessagesReceivedTooLate=0; + int sumOfTooLateFrames=0; + bool cleanupStats=false; + + + for( int i=0;iallowedMaxFallback){ + countOfMessagesReceivedTooEarly++; + if ( minimum == 0 || minimum > frameWhenMessageWasReceived[i] ){ + minimum=frameWhenMessageWasReceived[i]; + } + } + if(framesNeededToWaitForServerMessage[i]>0){ + countOfMessagesReceivedTooLate++; + sumOfTooLateFrames+=framesNeededToWaitForServerMessage[i]; + } + } + + if( countOfMessagesReceivedTooEarly==GameConstants::networkSmoothInterval ) + {// all packages where too early + // we catch up the minimum-catchupInterval of what we recorded + framesToCatchUpAsClient=minimum-allowedMaxFallback; + framesToSlowDownAsClient=0; + cleanupStats=true; + printf("Worldframe %d : Client will speed up: %d frames\n",world.getFrameCount(),framesToCatchUpAsClient); + } + else if(countOfMessagesReceivedTooLate>3){ + framesToSlowDownAsClient=sumOfTooLateFrames/countOfMessagesReceivedTooLate; + framesToCatchUpAsClient=0; + cleanupStats=true; + printf("Worldframe %d : Client will slow down: %d frames\n",world.getFrameCount(),framesToCatchUpAsClient); + } + + if(cleanupStats==true) { + // Once we decided to use the stats to do some correction, we reset/cleanup our recorded stats + for( int i=0;i0) { - if(framesToCatchUpAsClient==1) - { - //ignore it and don't catch up this one frame - framesToCatchUpAsClient=0; - } - else if(framesToCatchUpAsClient>1){ updateLoops = 2; - framesToCatchUpAsClient=framesToCatchUpAsClient-2; - } + framesToCatchUpAsClient=framesToCatchUpAsClient-1; + } + if(framesToSlowDownAsClient>0) + {// slowdown still the hard way. + updateLoops = 0; + framesToSlowDownAsClient=framesToSlowDownAsClient-1; } 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()); diff --git a/source/glest_game/game/game.h b/source/glest_game/game/game.h index d21ad38c..6f06969b 100644 --- a/source/glest_game/game/game.h +++ b/source/glest_game/game/game.h @@ -88,6 +88,9 @@ private: int updateFps, lastUpdateFps, avgUpdateFps; int framesToCatchUpAsClient; + int framesToSlowDownAsClient; + int frameWhenMessageWasReceived[GameConstants::networkSmoothInterval]; + int framesNeededToWaitForServerMessage[GameConstants::networkSmoothInterval]; int totalRenderFps, renderFps, lastRenderFps, avgRenderFps,currentAvgRenderFpsTotal; uint64 tickCount; bool paused; diff --git a/source/glest_game/game/game_constants.h b/source/glest_game/game/game_constants.h index 8b5345d9..7bea5136 100644 --- a/source/glest_game/game/game_constants.h +++ b/source/glest_game/game/game_constants.h @@ -133,6 +133,7 @@ public: static int networkFramePeriod; static const int networkPingInterval = 5; + static const int networkSmoothInterval= 30; //static const int networkExtraLatency= 200; static const int maxClientConnectHandshakeSecs= 10; diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 89eb48b1..74bd6c7a 100644 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -166,6 +166,7 @@ ClientInterface::ClientInterface() : GameNetworkInterface() { networkCommandListThread = NULL; cachedPendingCommandsIndex = 0; cachedLastPendingFrameCount = 0; + timeClientWaitedForLastMessage = 0; flagAccessor = new Mutex(CODE_AT_LINE); @@ -1190,6 +1191,16 @@ uint64 ClientInterface::getCachedLastPendingFrameCount() { return result; } +int64 ClientInterface::getTimeClientWaitedForLastMessage() { + MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); + uint64 result = timeClientWaitedForLastMessage; + safeMutex.ReleaseLock(); + + return result; +} + + + //void ClientInterface::simpleTask(BaseThread *callingThread) { // Chrono chrono; // if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); @@ -1211,6 +1222,8 @@ bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPending bool waitForData = false; uint64 copyCachedLastPendingFrameCount = 0; uint64 waitCount = 0; + Chrono chrono; + timeClientWaitedForLastMessage = 0; if(quit == false && this->quitThread == false) { //MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); @@ -1236,6 +1249,10 @@ bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPending //cachedPendingCommands.erase(frameCount); cachedPendingCommands[frameCount].clear(); } + if(waitForData == true) { + timeClientWaitedForLastMessage=chrono.getMillis(); + chrono.stop(); + } safeMutex.ReleaseLock(true); result = true; @@ -1250,6 +1267,7 @@ bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPending if(waitForData == false) { printf("Client waiting for packet for frame: %d, copyCachedLastPendingFrameCount = %lld\n",frameCount,(long long int)copyCachedLastPendingFrameCount); + chrono.start(); } if(copyCachedLastPendingFrameCount > frameCount) { break; diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index b1c69a98..cbb8e665 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -87,6 +87,7 @@ private: std::map cachedPendingCommands; //commands ready to be given uint64 cachedPendingCommandsIndex; uint64 cachedLastPendingFrameCount; + int64 timeClientWaitedForLastMessage; Mutex *flagAccessor; bool joinGameInProgress; @@ -112,6 +113,7 @@ public: void sendResumeGameMessage(); uint64 getCachedLastPendingFrameCount(); + int64 getTimeClientWaitedForLastMessage(); //message processing virtual void update();