slowdown and speedup clients based on recorded stats
This commit is contained in:
parent
e8e7b96865
commit
4a436066e7
|
@ -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<GameConstants::networkSmoothInterval;i++){
|
||||
frameWhenMessageWasReceived[i]==-1;
|
||||
framesNeededToWaitForServerMessage[i]==-1;
|
||||
}
|
||||
|
||||
fadeMusicMilliseconds = Config::getInstance().getInt("GameStartStopFadeSoundMilliseconds",intToStr(fadeMusicMilliseconds).c_str());
|
||||
GAME_STATS_DUMP_INTERVAL = Config::getInstance().getInt("GameStatsDumpIntervalSeconds",intToStr(GAME_STATS_DUMP_INTERVAL).c_str());
|
||||
|
@ -235,6 +240,7 @@ void Game::resetMembers() {
|
|||
renderFps=0;
|
||||
lastUpdateFps=0;
|
||||
framesToCatchUpAsClient=0;
|
||||
framesToSlowDownAsClient=0;
|
||||
lastRenderFps=-1;
|
||||
avgUpdateFps=-1;
|
||||
avgRenderFps=-1;
|
||||
|
@ -266,6 +272,12 @@ void Game::resetMembers() {
|
|||
|
||||
inJoinGameLoading = false;
|
||||
|
||||
for( int i=0;i<GameConstants::networkSmoothInterval;i++){
|
||||
frameWhenMessageWasReceived[i]==-1;
|
||||
framesNeededToWaitForServerMessage[i]==-1;
|
||||
}
|
||||
|
||||
|
||||
fadeMusicMilliseconds = Config::getInstance().getInt("GameStartStopFadeSoundMilliseconds",intToStr(fadeMusicMilliseconds).c_str());
|
||||
GAME_STATS_DUMP_INTERVAL = Config::getInstance().getInt("GameStatsDumpIntervalSeconds",intToStr(GAME_STATS_DUMP_INTERVAL).c_str());
|
||||
|
||||
|
@ -1733,39 +1745,113 @@ void Game::update() {
|
|||
ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(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;i<GameConstants::networkSmoothInterval;i++){
|
||||
if(frameWhenMessageWasReceived[i]>allowedMaxFallback){
|
||||
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;i<GameConstants::networkSmoothInterval;i++){
|
||||
frameWhenMessageWasReceived[i]=-1;
|
||||
framesNeededToWaitForServerMessage[index]=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// we catch up a bit smoother with updateLoops = 2
|
||||
if(framesToCatchUpAsClient>0)
|
||||
{
|
||||
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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -87,6 +87,7 @@ private:
|
|||
std::map<int,Commands> 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();
|
||||
|
|
Loading…
Reference in New Issue