00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "cg_local.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035 static void CG_ResetEntity( centity_t *cent ) {
00036
00037
00038 if ( cent->snapShotTime < cg.time - EVENT_VALID_MSEC ) {
00039 cent->previousEvent = 0;
00040 }
00041
00042 cent->trailTime = cg.snap->serverTime;
00043
00044 VectorCopy (cent->currentState.origin, cent->lerpOrigin);
00045 VectorCopy (cent->currentState.angles, cent->lerpAngles);
00046 if ( cent->currentState.eType == ET_PLAYER ) {
00047 CG_ResetPlayerEntity( cent );
00048 }
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058 static void CG_TransitionEntity( centity_t *cent ) {
00059 cent->currentState = cent->nextState;
00060 cent->currentValid = qtrue;
00061
00062
00063 if ( !cent->interpolate ) {
00064 CG_ResetEntity( cent );
00065 }
00066
00067
00068 cent->interpolate = qfalse;
00069
00070
00071 CG_CheckEvents( cent );
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 void CG_SetInitialSnapshot( snapshot_t *snap ) {
00087 int i;
00088 centity_t *cent;
00089 entityState_t *state;
00090
00091 cg.snap = snap;
00092
00093 BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse );
00094
00095
00096 CG_BuildSolidList();
00097
00098 CG_ExecuteNewServerCommands( snap->serverCommandSequence );
00099
00100
00101
00102 CG_Respawn();
00103
00104 for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
00105 state = &cg.snap->entities[ i ];
00106 cent = &cg_entities[ state->number ];
00107
00108 memcpy(¢->currentState, state, sizeof(entityState_t));
00109
00110 cent->interpolate = qfalse;
00111 cent->currentValid = qtrue;
00112
00113 CG_ResetEntity( cent );
00114
00115
00116 CG_CheckEvents( cent );
00117 }
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 static void CG_TransitionSnapshot( void ) {
00129 centity_t *cent;
00130 snapshot_t *oldFrame;
00131 int i;
00132
00133 if ( !cg.snap ) {
00134 CG_Error( "CG_TransitionSnapshot: NULL cg.snap" );
00135 }
00136 if ( !cg.nextSnap ) {
00137 CG_Error( "CG_TransitionSnapshot: NULL cg.nextSnap" );
00138 }
00139
00140
00141 CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence );
00142
00143
00144 if ( !cg.snap ) {
00145 }
00146
00147
00148 for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
00149 cent = &cg_entities[ cg.snap->entities[ i ].number ];
00150 cent->currentValid = qfalse;
00151 }
00152
00153
00154 oldFrame = cg.snap;
00155 cg.snap = cg.nextSnap;
00156
00157 BG_PlayerStateToEntityState( &cg.snap->ps, &cg_entities[ cg.snap->ps.clientNum ].currentState, qfalse );
00158 cg_entities[ cg.snap->ps.clientNum ].interpolate = qfalse;
00159
00160 for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
00161 cent = &cg_entities[ cg.snap->entities[ i ].number ];
00162 CG_TransitionEntity( cent );
00163
00164
00165 cent->snapShotTime = cg.snap->serverTime;
00166 }
00167
00168 cg.nextSnap = NULL;
00169
00170
00171 if ( oldFrame ) {
00172 playerState_t *ops, *ps;
00173
00174 ops = &oldFrame->ps;
00175 ps = &cg.snap->ps;
00176
00177 if ( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT ) {
00178 cg.thisFrameTeleport = qtrue;
00179 }
00180
00181
00182
00183 if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)
00184 || cg_nopredict.integer || cg_synchronousClients.integer ) {
00185 CG_TransitionPlayerState( ps, ops );
00186 }
00187 }
00188
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 static void CG_SetNextSnap( snapshot_t *snap ) {
00200 int num;
00201 entityState_t *es;
00202 centity_t *cent;
00203
00204 cg.nextSnap = snap;
00205
00206 BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].nextState, qfalse );
00207 cg_entities[ cg.snap->ps.clientNum ].interpolate = qtrue;
00208
00209
00210 for ( num = 0 ; num < snap->numEntities ; num++ ) {
00211 es = &snap->entities[num];
00212 cent = &cg_entities[ es->number ];
00213
00214 memcpy(¢->nextState, es, sizeof(entityState_t));
00215
00216
00217
00218
00219 if ( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT ) ) {
00220 cent->interpolate = qfalse;
00221 } else {
00222 cent->interpolate = qtrue;
00223 }
00224 }
00225
00226
00227
00228 if ( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) ) {
00229 cg.nextFrameTeleport = qtrue;
00230 } else {
00231 cg.nextFrameTeleport = qfalse;
00232 }
00233
00234
00235 if ( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum ) {
00236 cg.nextFrameTeleport = qtrue;
00237 }
00238
00239
00240 if ( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT ) {
00241 cg.nextFrameTeleport = qtrue;
00242 }
00243
00244
00245 CG_BuildSolidList();
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 static snapshot_t *CG_ReadNextSnapshot( void ) {
00260 qboolean r;
00261 snapshot_t *dest;
00262
00263 if ( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) {
00264 CG_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i",
00265 cg.latestSnapshotNum, cgs.processedSnapshotNum );
00266 }
00267
00268 while ( cgs.processedSnapshotNum < cg.latestSnapshotNum ) {
00269
00270 if ( cg.snap == &cg.activeSnapshots[0] ) {
00271 dest = &cg.activeSnapshots[1];
00272 } else {
00273 dest = &cg.activeSnapshots[0];
00274 }
00275
00276
00277 cgs.processedSnapshotNum++;
00278 r = trap_GetSnapshot( cgs.processedSnapshotNum, dest );
00279
00280
00281 if ( cg.snap && r && dest->serverTime == cg.snap->serverTime ) {
00282
00283 }
00284
00285
00286 if ( r ) {
00287 CG_AddLagometerSnapshotInfo( dest );
00288 return dest;
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 CG_AddLagometerSnapshotInfo( NULL );
00298
00299
00300
00301 }
00302
00303
00304 return NULL;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 void CG_ProcessSnapshots( void ) {
00328 snapshot_t *snap;
00329 int n;
00330
00331
00332 trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime );
00333 if ( n != cg.latestSnapshotNum ) {
00334 if ( n < cg.latestSnapshotNum ) {
00335
00336 CG_Error( "CG_ProcessSnapshots: n < cg.latestSnapshotNum" );
00337 }
00338 cg.latestSnapshotNum = n;
00339 }
00340
00341
00342
00343
00344 while ( !cg.snap ) {
00345 snap = CG_ReadNextSnapshot();
00346 if ( !snap ) {
00347
00348 return;
00349 }
00350
00351
00352
00353 if ( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
00354 CG_SetInitialSnapshot( snap );
00355 }
00356 }
00357
00358
00359
00360
00361 do {
00362
00363 if ( !cg.nextSnap ) {
00364 snap = CG_ReadNextSnapshot();
00365
00366
00367
00368 if ( !snap ) {
00369 break;
00370 }
00371
00372 CG_SetNextSnap( snap );
00373
00374
00375
00376 if ( cg.nextSnap->serverTime < cg.snap->serverTime ) {
00377 CG_Error( "CG_ProcessSnapshots: Server time went backwards" );
00378 }
00379 }
00380
00381
00382 if ( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime ) {
00383 break;
00384 }
00385
00386
00387 CG_TransitionSnapshot();
00388 } while ( 1 );
00389
00390
00391 if ( cg.snap == NULL ) {
00392 CG_Error( "CG_ProcessSnapshots: cg.snap == NULL" );
00393 }
00394 if ( cg.time < cg.snap->serverTime ) {
00395
00396 cg.time = cg.snap->serverTime;
00397 }
00398 if ( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time ) {
00399 CG_Error( "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" );
00400 }
00401
00402 }
00403