SNAPFLAG_RESET_ENTITIES: no-interpolation reset without gamestate resend
Replace the gamestate resend approach for map_restart with a custom snapshot flag (SNAPFLAG_RESET_ENTITIES, bit 4 in snapFlags byte). Server side (sv_netdemo.c): - On restart frame, OR the flag into svs.snapFlagServerBit (one-shot) - Cleared at the start of the next playback frame Client side (cg_snapshot.c): - CG_SetNextSnap: clear currentValid for all entities when flag is set, making them all "new" — existing interpolation check at line 228 sets interpolate=qfalse, CG_TransitionEntity calls CG_ResetEntity - Also set cg.nextFrameTeleport=qtrue to prevent playerstate interpolation during follow mode No loading screen, no lost frames, no gamestate resend. Entities and playerstate both snap to correct positions on map_restart. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0b4eb7b69f
commit
c6af63ae42
4 changed files with 22 additions and 13 deletions
|
|
@ -203,6 +203,15 @@ static void CG_SetNextSnap( snapshot_t *snap ) {
|
|||
|
||||
cg.nextSnap = snap;
|
||||
|
||||
// SNAPFLAG_RESET_ENTITIES: invalidate all entities so they are
|
||||
// treated as new (no interpolation from old positions).
|
||||
// Must happen before the entity loop below.
|
||||
if ( snap->snapFlags & SNAPFLAG_RESET_ENTITIES ) {
|
||||
for ( num = 0 ; num < MAX_GENTITIES ; num++ ) {
|
||||
cg_entities[ num ].currentValid = qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].nextState, qfalse );
|
||||
cg_entities[ cg.snap->ps.clientNum ].interpolate = qtrue;
|
||||
|
||||
|
|
@ -241,6 +250,11 @@ static void CG_SetNextSnap( snapshot_t *snap ) {
|
|||
cg.nextFrameTeleport = qtrue;
|
||||
}
|
||||
|
||||
// entity reset also prevents playerstate interpolation
|
||||
if ( cg.nextSnap->snapFlags & SNAPFLAG_RESET_ENTITIES ) {
|
||||
cg.nextFrameTeleport = qtrue;
|
||||
}
|
||||
|
||||
// sort out solid entities
|
||||
CG_BuildSolidList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1085,6 +1085,7 @@ typedef enum {
|
|||
#define SNAPFLAG_RATE_DELAYED 1
|
||||
#define SNAPFLAG_NOT_ACTIVE 2 // snapshot used during connection and for zombies
|
||||
#define SNAPFLAG_SERVERCOUNT 4 // toggled every map_restart so transitions can be detected
|
||||
#define SNAPFLAG_RESET_ENTITIES 16 // snap all entities to current position, no interpolation
|
||||
|
||||
//
|
||||
// per-level limits
|
||||
|
|
|
|||
|
|
@ -289,7 +289,6 @@ void SV_AuthorizeIpPacket( netadr_t from );
|
|||
void SV_ExecuteClientMessage( client_t *cl, msg_t *msg );
|
||||
void SV_UserinfoChanged( client_t *cl );
|
||||
|
||||
void SV_SendClientGameState( client_t *client );
|
||||
void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd );
|
||||
void SV_DropClient( client_t *drop, const char *reason );
|
||||
|
||||
|
|
|
|||
|
|
@ -677,22 +677,14 @@ static qboolean SVD_ReadFrame( fileHandle_t f ) {
|
|||
byte frameFlags;
|
||||
FS_Read( &frameFlags, 1, f );
|
||||
if ( frameFlags & 1 ) {
|
||||
int j;
|
||||
// map was restarted — reset playback delta state to match
|
||||
// the recording's reset (both now decode from zero baseline).
|
||||
// Also toggle server bit and force non-delta snapshot so the
|
||||
// client clears old entity state and doesn't interpolate.
|
||||
Com_Memset( demo.playPrevEntities, 0, sizeof(demo.playPrevEntities) );
|
||||
Com_Memset( demo.playPrevPlayers, 0, sizeof(demo.playPrevPlayers) );
|
||||
svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;
|
||||
// send a full gamestate to all active clients — this makes
|
||||
// CL_ParseGamestate → CL_ClearState wipe all snapshot/entity
|
||||
// history, exactly like a real map_restart does.
|
||||
for ( j = 0; j < sv_maxclients->integer; j++ ) {
|
||||
if ( svs.clients[j].state >= CS_PRIMED ) {
|
||||
SV_SendClientGameState( &svs.clients[j] );
|
||||
}
|
||||
}
|
||||
// set one-shot SNAPFLAG_RESET_ENTITIES so cgame snaps all
|
||||
// entities to current position without interpolation.
|
||||
// OR'd into snapFlagServerBit, cleared after one frame.
|
||||
svs.snapFlagServerBit |= SNAPFLAG_RESET_ENTITIES;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1020,6 +1012,9 @@ qboolean SVD_PlaybackFrame( void ) {
|
|||
demo.needConfigstrings = qfalse;
|
||||
}
|
||||
|
||||
// clear one-shot reset flag from previous frame before reading new one
|
||||
svs.snapFlagServerBit &= ~SNAPFLAG_RESET_ENTITIES;
|
||||
|
||||
if ( !SVD_ReadFrame( demo.playFile ) ) {
|
||||
Com_Printf( "Server demo playback finished.\n" );
|
||||
SVD_CleanupPlayback();
|
||||
|
|
|
|||
Loading…
Reference in a new issue