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