#include <eTimer.h>
Public Member Functions | |
eTimer () | |
eTimer (nMessage &m) | |
virtual | ~eTimer () |
virtual void | WriteSync (nMessage &m) |
virtual void | ReadSync (nMessage &m) |
virtual nDescriptor & | CreatorDescriptor () const |
REAL | Time () |
REAL | TimeNoSync () |
void | pause (bool p) |
void | SyncTime () |
void | Reset (REAL t=0) |
REAL | AverageFPS () |
REAL | AverageFrameTime () |
REAL | FrameTime () |
bool | IsSynced () const |
returns whether the timer is synced sufficiently well to allow rendering | |
Public Attributes | |
REAL | speed |
Private Attributes | |
double | creationSystemTime_ |
the rough system time this timer was created at | |
double | smoothedSystemTime_ |
the smoothed system time | |
double | startTime_ |
when was the last game started? | |
nAverager | startTimeOffset_ |
the smoothed average of this averager is added to the start time on the client | |
REAL | startTimeSmoothedOffset_ |
the smoothed average of startTimeOffset_ | |
nAverager | qualityTester_ |
averager that tells us about the quality of the sync messages | |
REAL | spf_ |
last frame time | |
nAverager | averageSpf_ |
averager over seconds per frame | |
double | lastTime_ |
the smoothed system time of the last update | |
double | nextSync_ |
system time of the next sync to the clients |
Definition at line 35 of file eTimer.h.
eTimer::eTimer | ( | ) |
Definition at line 42 of file eTimer.cpp.
References nAverager::Add(), averageSpf_, creationSystemTime_, nSERVER, nNetObject::RequestSync(), nAverager::Reset(), Reset(), sn_GetNetState(), speed, and tSysTimeFloat().
00042 :nNetObject(), startTimeSmoothedOffset_(0){ 00043 //con << "Creating own eTimer.\n"; 00044 00045 speed = 1.0; 00046 00047 Reset(0); 00048 00049 if (se_mainGameTimer) 00050 delete se_mainGameTimer; 00051 se_mainGameTimer=this; 00052 if (sn_GetNetState()==nSERVER) 00053 RequestSync(); 00054 00055 averageSpf_.Reset(); 00056 averageSpf_.Add(1/60.0,5); 00057 00058 creationSystemTime_ = tSysTimeFloat(); 00059 }
eTimer::eTimer | ( | nMessage & | m | ) |
Definition at line 61 of file eTimer.cpp.
References nAverager::Add(), averageSpf_, creationSystemTime_, nAverager::Reset(), Reset(), speed, and tSysTimeFloat().
00061 :nNetObject(m), startTimeSmoothedOffset_(0){ 00062 //con << "Creating remote eTimer.\n"; 00063 00064 speed = 1.0; 00065 00066 Reset(0); 00067 00068 if (se_mainGameTimer) 00069 delete se_mainGameTimer; 00070 se_mainGameTimer=this; 00071 00072 averageSpf_.Reset(); 00073 averageSpf_.Add(1/60.0,5); 00074 00075 creationSystemTime_ = tSysTimeFloat(); 00076 }
eTimer::~eTimer | ( | ) | [virtual] |
Definition at line 78 of file eTimer.cpp.
References NULL.
00078 { 00079 //con << "Deleting eTimer.\n"; 00080 se_mainGameTimer=NULL; 00081 }
void eTimer::WriteSync | ( | nMessage & | m | ) | [virtual] |
Reimplemented from nNetObject.
Definition at line 90 of file eTimer.cpp.
References nextSync_, REAL, se_clientLagCompensation, se_lagOffsetLegacy, smoothedSystemTime_, speed, nVersionFeature::Supported(), nNetObject::SyncedUser(), Time(), and nNetObject::WriteSync().
00090 { 00091 nNetObject::WriteSync(m); 00092 REAL time = Time(); 00093 00094 if ( SyncedUser() > 0 && !se_clientLagCompensation.Supported( SyncedUser() ) ) 00095 time += se_lagOffsetLegacy; 00096 00097 m << time; 00098 m << speed; 00099 //std::cerr << "syncing:" << currentTime << ":" << speed << '\n'; 00100 00101 // plan next sync 00102 const REAL stopFast = 3; 00103 const REAL maxFast = 3; 00104 if ( time < stopFast ) 00105 { 00106 nextSync_ = smoothedSystemTime_ + maxFast/(stopFast+maxFast-time); 00107 } 00108 else 00109 { 00110 nextSync_ = smoothedSystemTime_ + 1; 00111 } 00112 }
void eTimer::ReadSync | ( | nMessage & | m | ) | [virtual] |
Reimplemented from nNetObject.
Definition at line 119 of file eTimer.cpp.
References nAverager::Add(), EPS, nAverager::GetAverageVariance(), nPingAverager::GetFastAverager(), nPingAverager::GetPing(), nConnectionInfo::ping, qualityTester_, nNetObject::ReadSync(), REAL, nAverager::Reset(), se_timerStartFudge, se_timerStartFudgeStop, nMessage::SenderID(), smoothedSystemTime_, sn_Connections, sn_pingCharityServer, speed, startTime_, startTimeOffset_, and nAverager::Timestep().
00119 { 00120 nNetObject::ReadSync(m); 00121 00122 //std::cerr << "Got sync:" << remote_currentTime << ":" << speed << '\n'; 00123 00124 // determine the best estimate of the start time offset that reproduces the sent remote 00125 // time and its expected quality. 00126 REAL remoteStartTimeOffset = 0; 00127 REAL remoteTimeNonQuality = 0; 00128 { 00129 //REAL oldTime=currentTime; 00130 REAL remote_currentTime, remoteSpeed; 00131 m >> remote_currentTime; // read in the remote time 00132 m >> remoteSpeed; 00133 00134 // forget about earlier syncs if the speed changed 00135 if ( fabs( speed - remoteSpeed ) > 10 * EPS ) 00136 { 00137 qualityTester_.Timestep( 100 ); 00138 startTimeOffset_.Reset(); 00139 } 00140 00141 speed = remoteSpeed; 00142 00143 // determine ping 00144 nPingAverager & averager = sn_Connections[m.SenderID()].ping; 00145 // pingAverager_.Add( rawAverager.GetPing(), remote_currentTime > .01 ? remote_currentTime : .01 ); 00146 REAL ping = averager.GetPing(); 00147 00148 // add half our ping (see Einsteins SRT on clock syncronisation) 00149 REAL real_remoteTime=remote_currentTime+ping*speed*.5; 00150 00151 // and the normal time including ping charity 00152 REAL min_remoteTime=remote_currentTime+ping*speed- 00153 sn_pingCharityServer*.001; 00154 00155 if (real_remoteTime<min_remoteTime) 00156 remote_currentTime=min_remoteTime; 00157 else 00158 remote_currentTime=real_remoteTime; 00159 00160 // HACK: warp time into the future at the beginning of the round. 00161 // I can't explain why this is required; without it, the timer is late. 00162 if ( remote_currentTime < se_timerStartFudgeStop ) 00163 { 00164 remote_currentTime += ping * ( se_timerStartFudgeStop - remote_currentTime ) * se_timerStartFudge; 00165 } 00166 00167 // determine quality from ping variance 00168 remoteTimeNonQuality = averager.GetFastAverager().GetAverageVariance(); 00169 00170 // determine start time 00171 remoteStartTimeOffset = smoothedSystemTime_ - startTime_ - remote_currentTime; 00172 00173 // let the averagers decay faster at the beginning 00174 if ( remote_currentTime < 0 ) 00175 { 00176 qualityTester_.Timestep( .2 ); 00177 startTimeOffset_.Timestep( .2 ); 00178 } 00179 } 00180 00181 // try to get independend quality measure: get the variance of the received start times 00182 qualityTester_.Add( remoteStartTimeOffset ); 00183 00184 // add the variance to the non-quality, along with an offset to avoid division by zero 00185 remoteTimeNonQuality += 0.00001 + 4 * qualityTester_.GetAverageVariance(); 00186 00187 // add the offset to the statistics, weighted by the quality 00188 startTimeOffset_.Add( remoteStartTimeOffset, 1/remoteTimeNonQuality ); 00189 }
nDescriptor & eTimer::CreatorDescriptor | ( | void | ) | const [virtual] |
Implements nNetObject.
Definition at line 193 of file eTimer.cpp.
References eTimer_init.
00193 { 00194 return eTimer_init; 00195 }
REAL eTimer::Time | ( | ) |
Definition at line 215 of file eTimer.cpp.
References eLag::Current(), smoothedSystemTime_, startTime_, and startTimeSmoothedOffset_.
Referenced by gCycle::Act(), gWallRim::RenderReal(), se_GameTime(), SyncTime(), TimeNoSync(), and WriteSync().
00216 { 00217 return ( smoothedSystemTime_ - startTime_ ) - startTimeSmoothedOffset_ + eLag::Current(); 00218 }
REAL eTimer::TimeNoSync | ( | ) | [inline] |
Definition at line 47 of file eTimer.h.
References lastTime_, REAL, speed, Time(), and tSysTimeFloat().
Referenced by se_GameTimeNoSync().
00047 {return REAL(Time()+(tSysTimeFloat()-lastTime_)*speed);}
void eTimer::pause | ( | bool | p | ) |
Definition at line 362 of file eTimer.cpp.
References nSERVER, nNetObject::RequestSync(), sn_GetNetState(), and speed.
Referenced by se_PauseGameTimer().
00362 { 00363 if (p){ 00364 if(speed!=0){ 00365 speed=0; 00366 if (sn_GetNetState()==nSERVER) 00367 RequestSync(); 00368 } 00369 } 00370 else{ 00371 if (speed!=1){ 00372 speed=1; 00373 //Reset(currentTime_); 00374 00375 if (sn_GetNetState()==nSERVER) 00376 RequestSync(); 00377 } 00378 } 00379 }
void eTimer::SyncTime | ( | ) |
Definition at line 220 of file eTimer.cpp.
References nAverager::Add(), averageSpf_, nAverager::GetAverage(), nAverager::GetAverageVariance(), tRecorderBase::IsRunning(), lastTime_, nextSync_, nSERVER, nSTANDALONE, qualityTester_, REAL, nNetObject::RequestSync(), se_SmoothTime(), smoothedSystemTime_, sn_GetNetState(), speed, spf_, st_Breakpoint(), startTime_, startTimeOffset_, startTimeSmoothedOffset_, Time(), nAverager::Timestep(), eLag::Timestep(), tSysTimeFloat(), and tTimerIsAccurate().
Referenced by se_SyncGameTimer().
00220 { 00221 // get current system time 00222 { 00223 double newTime=tSysTimeFloat(); 00224 00225 static bool smooth = se_SmoothTime(); 00226 00227 // recheck if no recording/playback is running 00228 if ( !tRecorder::IsRunning() ) 00229 { 00230 smooth = !tTimerIsAccurate(); 00231 } 00232 00233 if ( !smooth ) 00234 { 00235 // take it 00236 smoothedSystemTime_ = newTime; 00237 } 00238 else 00239 { 00240 // smooth it 00241 REAL smoothDecay = .2f; 00242 smoothedSystemTime_ = ( smoothedSystemTime_ + smoothDecay * newTime )/( 1 + smoothDecay ); 00243 } 00244 } 00245 00246 // update timers 00247 REAL timeStep=smoothedSystemTime_ - lastTime_; 00248 lastTime_ = smoothedSystemTime_; 00249 00250 #ifdef DEBUG 00251 #ifndef DEDICATED 00252 // maximum effective timestep in SP debug mode: .1s 00253 if (timeStep > .1f && sn_GetNetState() == nSTANDALONE && !tRecorder::IsRunning() ) 00254 { 00255 startTime_ += timeStep - .1f; 00256 timeStep = .1f; 00257 } 00258 #endif 00259 #endif 00260 00261 // update lag compensation 00262 eLag::Timestep( timeStep ); 00263 00264 // store and average frame times 00265 spf_ = timeStep; 00266 if ( timeStep > 0 && speed > 0 ) 00267 { 00268 averageSpf_.Add( timeStep ); 00269 averageSpf_.Timestep( timeStep ); 00270 } 00271 00272 // let averagers decay 00273 startTimeOffset_.Timestep( timeStep * .1 ); 00274 qualityTester_ .Timestep( timeStep * .3 ); 00275 // pingAverager_ .Timestep( timeStep * .05); 00276 00277 // if we're not running at default speed, update the virtual start time 00278 startTime_ += ( 1.0 - speed ) * timeStep; 00279 00280 // smooth time offset 00281 { 00282 REAL startTimeOffset = startTimeOffset_.GetAverage(); 00283 00284 // correct huge deviations (compared to variance) faster 00285 REAL deviation = startTimeSmoothedOffset_ - startTimeOffset; 00286 REAL extraSmooth = deviation * deviation / ( startTimeOffset_.GetAverageVariance() + .0001 ); 00287 00288 // allow for faster smoothing at the beginning of the round 00289 REAL time = Time(); 00290 if ( time < 0 ) 00291 extraSmooth -= 4 * time; 00292 00293 REAL smooth = timeStep * ( .5 + extraSmooth ); 00294 startTimeSmoothedOffset_ = ( startTimeSmoothedOffset_ + startTimeOffset * smooth )/(1 + smooth); 00295 00296 if ( !finite( startTimeSmoothedOffset_ ) ) 00297 { 00298 // emergency, smoothing the timer produced infinite results 00299 st_Breakpoint(); 00300 startTimeSmoothedOffset_ = startTimeOffset; 00301 } 00302 } 00303 00304 // request syncs 00305 if (sn_GetNetState()==nSERVER && smoothedSystemTime_ >= nextSync_ ) 00306 { 00307 #ifdef nSIMULATE_PING 00308 RequestSync(); // ack. 00309 #else 00310 RequestSync(false); // NO ack. 00311 #endif 00312 } 00313 }
void eTimer::Reset | ( | REAL | t = 0 |
) |
Definition at line 315 of file eTimer.cpp.
References nAverager::Add(), EPS, nAverager::GetAverage(), lastTime_, nCLIENT, nextSync_, qualityTester_, REAL, nAverager::Reset(), smoothedSystemTime_, sn_GetNetState(), speed, sqrt(), startTime_, startTimeOffset_, startTimeSmoothedOffset_, and tSysTimeFloat().
Referenced by eTimer(), and se_ResetGameTimer().
00315 { 00316 if (sn_GetNetState()!=nCLIENT) 00317 speed=1; 00318 00319 // reset start time 00320 smoothedSystemTime_ = tSysTimeFloat(); 00321 startTime_ = smoothedSystemTime_ - t; 00322 00323 // reset averagers 00324 startTimeOffset_.Reset(); 00325 startTimeOffset_.Add(100,EPS); 00326 startTimeOffset_.Add(-100,EPS); 00327 00328 qualityTester_.Reset(); 00329 static const REAL qual = sqrt(1/EPS); 00330 qualityTester_.Add(qual,EPS); 00331 qualityTester_.Add(-qual,EPS); 00332 00333 // reset times of actions 00334 lastTime_ = nextSync_ = smoothedSystemTime_; 00335 startTimeSmoothedOffset_ = startTimeOffset_.GetAverage(); 00336 }
REAL eTimer::AverageFPS | ( | ) | [inline] |
Definition at line 54 of file eTimer.h.
References averageSpf_, EPS, and nAverager::GetAverage().
Referenced by se_AverageFPS().
00054 {return 1/(averageSpf_.GetAverage()+EPS);}
REAL eTimer::AverageFrameTime | ( | ) | [inline] |
Definition at line 55 of file eTimer.h.
References averageSpf_, and nAverager::GetAverage().
00055 {return averageSpf_.GetAverage();}
REAL eTimer::FrameTime | ( | ) | [inline] |
bool eTimer::IsSynced | ( | ) | const |
returns whether the timer is synced sufficiently well to allow rendering
Definition at line 338 of file eTimer.cpp.
References creationSystemTime_, nAverager::GetAverage(), nAverager::GetAverageVariance(), tRecorderBase::IsPlayingBack(), nCLIENT, tRecorder::Playback(), tRecorder::Record(), section, smoothedSystemTime_, sn_GetNetState(), startTimeOffset_, and startTimeSmoothedOffset_.
Referenced by display_cockpit_lucifer(), and gGame::GameLoop().
00339 { 00340 // allow non-synced status only during the first ten seconds of a connection 00341 if ( smoothedSystemTime_ - creationSystemTime_ > 10 || sn_GetNetState() != nCLIENT ) 00342 return true; 00343 00344 // the quality of the start time offset needs to be good enough (to .1 s, variance is the square of the expected) 00345 bool synced = startTimeOffset_.GetAverageVariance() < .01 && 00346 fabs( startTimeOffset_.GetAverage() - startTimeSmoothedOffset_ ) < .01; 00347 00348 static char const * section = "TIMER_SYNCED"; 00349 00350 if ( tRecorder::IsPlayingBack() ? tRecorder::Playback( section ) : synced ) 00351 { 00352 tRecorder::Record( section ); 00353 00354 // and make sure the next calls also return true. 00355 creationSystemTime_ = smoothedSystemTime_ - 11; 00356 return true; 00357 } 00358 00359 return false; 00360 }
Definition at line 37 of file eTimer.h.
Referenced by gCycle::Act(), gGame::Analysis(), display_cockpit_lucifer(), eTimer(), pause(), ReadSync(), Reset(), sg_FullscreenMessage(), SyncTime(), TimeNoSync(), and WriteSync().
double eTimer::creationSystemTime_ [mutable, private] |
the rough system time this timer was created at
Definition at line 61 of file eTimer.h.
Referenced by eTimer(), and IsSynced().
double eTimer::smoothedSystemTime_ [private] |
the smoothed system time
Definition at line 62 of file eTimer.h.
Referenced by IsSynced(), ReadSync(), Reset(), SyncTime(), Time(), and WriteSync().
double eTimer::startTime_ [private] |
when was the last game started?
Definition at line 63 of file eTimer.h.
Referenced by ReadSync(), Reset(), SyncTime(), and Time().
nAverager eTimer::startTimeOffset_ [private] |
the smoothed average of this averager is added to the start time on the client
Definition at line 64 of file eTimer.h.
Referenced by IsSynced(), ReadSync(), Reset(), and SyncTime().
REAL eTimer::startTimeSmoothedOffset_ [private] |
the smoothed average of startTimeOffset_
Definition at line 65 of file eTimer.h.
Referenced by IsSynced(), Reset(), SyncTime(), and Time().
nAverager eTimer::qualityTester_ [private] |
averager that tells us about the quality of the sync messages
Definition at line 66 of file eTimer.h.
Referenced by ReadSync(), Reset(), and SyncTime().
REAL eTimer::spf_ [private] |
nAverager eTimer::averageSpf_ [private] |
averager over seconds per frame
Definition at line 71 of file eTimer.h.
Referenced by AverageFPS(), AverageFrameTime(), eTimer(), and SyncTime().
double eTimer::lastTime_ [private] |
the smoothed system time of the last update
Definition at line 73 of file eTimer.h.
Referenced by Reset(), SyncTime(), and TimeNoSync().
double eTimer::nextSync_ [private] |
system time of the next sync to the clients
Definition at line 74 of file eTimer.h.
Referenced by Reset(), SyncTime(), and WriteSync().