~swag/armagetronad/0.2.9-sty+ct+ap-fork

« back to all changes in this revision

Viewing changes to src/engine/eTimer.cpp

  • Committer: Voodoo
  • Date: 2011-07-28 18:46:18 UTC
  • mfrom: (563.24.161 merge)
  • Revision ID: voodoo-20110728184618-0djbrm75ftd07c4v
merge -r 1285..1297 lp:armagetronad/0.2.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include "tConfiguration.h"
35
35
#include "eLagCompensation.h"
36
36
 
 
37
// #include <fstream>
 
38
 
37
39
eTimer *se_mainGameTimer=NULL;
38
40
 
39
41
// from nNetwork.C; used to sync time with the server
116
118
    }
117
119
}
118
120
 
119
 
static REAL se_timerStartFudge = 0.0;
120
 
static tSettingItem<REAL> se_timerStartFudgeConf("TIMER_SYNC_START_FUDGE",se_timerStartFudge);
121
 
static REAL se_timerStartFudgeStop = 2.0;
122
 
static tSettingItem<REAL> se_timerStartFudgeStopConf("TIMER_SYNC_START_FUDGE_STOP",se_timerStartFudgeStop);
123
 
 
124
121
void eTimer::ReadSync(nMessage &m){
125
122
    nNetObject::ReadSync(m);
126
123
 
 
124
    if( sn_GetNetState() != nCLIENT || m.SenderID() != 0 )
 
125
    {
 
126
        return;
 
127
    }
 
128
 
 
129
    m >> remoteCurrentTime_; // read in the remote time
 
130
    m >> remoteSpeed_;
 
131
    sync_ = true;
 
132
 
 
133
    //std::cerr << "Got sync:" << remote_currentTime << ":" << speed << '\n';
 
134
}
 
135
 
 
136
static REAL se_cullDelayEnd=3.0;        // end of extra delay cull
 
137
static REAL se_cullDelayPerSecond=3.0;  // delay cull drop per second
 
138
static REAL se_cullDelayMin=10.0;       // plateau of delay cull after extra 
 
139
 
 
140
static tSettingItem< REAL > se_cullDelayEndConf( "CULL_DELAY_END", se_cullDelayEnd );
 
141
static tSettingItem< REAL > se_cullDelayPerSecondConf( "CULL_DELAY_PER_SECOND", se_cullDelayPerSecond );
 
142
static tSettingItem< REAL > se_cullDelayMinConf( "CULL_DELAY_MIN", se_cullDelayMin );
 
143
 
 
144
void eTimer::ProcessSync()
 
145
{
 
146
    sync_ = false;
 
147
 
127
148
    bool checkDrift = true;
128
149
 
129
 
    //std::cerr << "Got sync:" << remote_currentTime << ":" << speed << '\n';
130
 
 
131
150
    // determine the best estimate of the start time offset that reproduces the sent remote
132
151
    // time and its expected quality.
133
152
    REAL remoteStartTimeOffset = 0;
134
153
    REAL remoteTimeNonQuality = 0;
 
154
 
 
155
    // determine ping
 
156
    nPingAverager & pingAverager = sn_Connections[0].ping;
 
157
    REAL ping = pingAverager.GetPing();
 
158
    REAL pingVariance = pingAverager.GetFastAverager().GetAverageVariance();
 
159
 
135
160
    {
136
 
        //REAL oldTime=currentTime;
137
 
        REAL remote_currentTime, remoteSpeed;
138
 
        m >> remote_currentTime; // read in the remote time
139
 
        m >> remoteSpeed;
140
 
 
 
161
        // adapt remote time a little, we're processing syncs with a frame delay
 
162
        REAL remote_currentTime = remoteCurrentTime_ + averageSpf_.GetAverage();
 
163
        REAL remoteSpeed = remoteSpeed_;
 
164
 
141
165
        // forget about earlier syncs if the speed changed
142
166
        if ( fabs( speed - remoteSpeed ) > 10 * EPS )
143
167
        {
148
172
 
149
173
        speed = remoteSpeed;
150
174
 
151
 
        // determine ping
152
 
        nPingAverager & averager = sn_Connections[m.SenderID()].ping;
153
 
        // pingAverager_.Add( rawAverager.GetPing(), remote_currentTime > .01 ? remote_currentTime : .01 );
154
 
        REAL ping = averager.GetPing();
155
 
 
156
175
        // add half our ping (see Einsteins SRT on clock syncronisation)
157
176
        REAL real_remoteTime=remote_currentTime+ping*speed*.5;
158
177
 
165
184
        else
166
185
            remote_currentTime=real_remoteTime;
167
186
 
168
 
        // HACK: warp time into the future at the beginning of the round.
169
 
        // I can't explain why this is required; without it, the timer is late.
170
 
        if ( remote_currentTime < se_timerStartFudgeStop )
171
 
        {
172
 
            remote_currentTime += ping * ( se_timerStartFudgeStop - remote_currentTime ) * se_timerStartFudge;
173
 
            checkDrift = false;
174
 
        }
175
 
 
176
187
        // determine quality from ping variance
177
 
        remoteTimeNonQuality = averager.GetFastAverager().GetAverageVariance();
 
188
        remoteTimeNonQuality = pingVariance;
178
189
 
179
190
        // determine start time
180
191
        remoteStartTimeOffset = smoothedSystemTime_ - startTime_ - remote_currentTime;
214
225
    // add the variance to the non-quality, along with an offset to avoid division by zero
215
226
    remoteTimeNonQuality += 0.00001 + 4 * qualityTester_.GetAverageVariance();
216
227
 
 
228
#ifdef DEBUG_X
 
229
    con << "T=" << smoothedSystemTime_ << " " << lastRemoteTime_ << ", Q= " << remoteTimeNonQuality << ", P= " << ping << " +/- " << sqrt(pingVariance) << " Time offset: " << remoteStartTimeOffset << " : " << startTimeOffset_.GetAverage() << "\n";
 
230
 
 
231
    std::ofstream plot("timesync.txt",std::ios_base::app);
 
232
    plot << smoothedSystemTime_ << " " << remoteStartTimeOffset << " " << startTimeOffset_.GetAverage() << "\n";
 
233
#endif
 
234
 
 
235
    // check for unusually delayed packets, give them lower weight
 
236
    REAL delay =  remoteStartTimeOffset - startTimeOffset_.GetAverage();
 
237
    if( delay > 0 )
 
238
    {
 
239
        // fluctuations up to the ping variance are acceptable,
 
240
        // (plus some extra factors, like a 1 ms offset and 10% of the current ping)
 
241
        // severity will be < 1 for those
 
242
        REAL severity = delay*delay/(.000001 + pingVariance + .01*ping*ping);
 
243
        // but it is culled above 1
 
244
        if( severity > 1 )
 
245
        {
 
246
            severity = pow(severity,.25);
 
247
        }
 
248
 
 
249
        REAL cullFactor = (se_cullDelayEnd-lastRemoteTime_)*se_cullDelayPerSecond;
 
250
        if( cullFactor < 0 )
 
251
        {
 
252
            cullFactor = 0;
 
253
        }
 
254
        cullFactor += se_cullDelayMin;
 
255
 
 
256
#ifdef DEBUG_X
 
257
        con << "severity=" << severity << ", cull= " << cullFactor << "\n";
 
258
#endif
 
259
        remoteTimeNonQuality *= 1+(cullFactor-1)*severity;
 
260
    }
 
261
 
217
262
    // add the offset to the statistics, weighted by the quality
218
263
    startTimeOffset_.Add( remoteStartTimeOffset, 1/remoteTimeNonQuality );
219
264
}
248
293
}
249
294
 
250
295
void eTimer::SyncTime(){
251
 
    // get current system time
252
296
    {
 
297
        // get current system time and store it
253
298
        double newTime=tSysTimeFloat();
254
299
 
255
300
        static bool smooth = se_SmoothTime();
293
338
 
294
339
    // store and average frame times
295
340
    spf_ = timeStep;
 
341
 
 
342
    // process sync now before an unusually large timestep messes up averageSpf_.
 
343
    if( sync_ )
 
344
    {
 
345
        ProcessSync();
 
346
    }
 
347
 
296
348
    if ( timeStep > 0 && speed > 0 )
297
349
    {
298
350
        averageSpf_.Add( timeStep );
355
407
    startTimeOffset_.Add(100,EPS);
356
408
    startTimeOffset_.Add(-100,EPS);
357
409
 
 
410
    sync_ = false;
 
411
 
358
412
    qualityTester_.Reset();
359
413
    static const REAL qual = sqrt(1/EPS);
360
414
    qualityTester_.Add(qual,EPS);