diff --git a/code/server/server.h b/code/server/server.h index 6cfbc24..9dbdf93 100644 --- a/code/server/server.h +++ b/code/server/server.h @@ -357,7 +357,6 @@ void SVD_Stop_f( void ); qboolean SVD_PlaybackFrame( void ); qboolean SVD_IsRecording( void ); qboolean SVD_IsPlaying( void ); -int SVD_SpectatorClientNum( void ); //============================================================ // diff --git a/code/server/sv_netdemo.c b/code/server/sv_netdemo.c index a6d0371..745ffe9 100644 --- a/code/server/sv_netdemo.c +++ b/code/server/sv_netdemo.c @@ -102,7 +102,8 @@ typedef struct { int playFps; // original sv_fps char *savedConfigstrings[MAX_CONFIGSTRINGS]; // from demo header, re-applied after map load char playMapName[SVDEMO_MAX_MAPNAME]; - int spectatorClientNum; // which client slot is the demo spectator + // spectatorClientNum removed — zombie slots handle reservation, + // and G_RunFrame recreates the spectator entity each frame. int nextFrameTime; // serverTime of next frame to read qboolean endOfDemo; qboolean needConfigstrings; // apply saved configstrings on first frame @@ -686,11 +687,8 @@ static qboolean SVD_ReadFrame( fileHandle_t f ) { MSG_Init( &msg, msgBuf, sizeof(msgBuf) ); msg.cursize = blockLen; - // clear all non-spectator entities + // clear all entities (spectator's entity is recreated by ClientThink_real) for ( i = 0; i < sv.num_entities; i++ ) { - if ( i == demo.spectatorClientNum ) { - continue; - } ent = SV_GentityNum( i ); if ( ent->r.linked ) { SV_UnlinkEntity( ent ); @@ -750,11 +748,6 @@ static qboolean SVD_ReadFrame( fileHandle_t f ) { demo.playPrevEntities[entNum].es = newEs; demo.playPrevEntities[entNum].active = qtrue; - // skip the spectator's slot - if ( entNum == demo.spectatorClientNum ) { - continue; - } - // apply to server entity ent = SV_GentityNum( entNum ); ent->s = newEs; @@ -774,11 +767,6 @@ static qboolean SVD_ReadFrame( fileHandle_t f ) { } } - // ensure spectator slot is counted - if ( demo.spectatorClientNum + 1 > sv.num_entities ) { - sv.num_entities = demo.spectatorClientNum + 1; - } - // read player states (delta compressed) { msg_t psmsg; @@ -818,14 +806,14 @@ static qboolean SVD_ReadFrame( fileHandle_t f ) { demo.playPrevPlayers[clientNum].active = qtrue; // inject into game module's client state - if ( clientNum != demo.spectatorClientNum ) { + { playerState_t *gamePs = SV_GameClientNum( clientNum ); *gamePs = newPs; } } else { demo.playPrevPlayers[clientNum].active = qfalse; // clear game playerState so G_RunFrame sees commandTime=0 - if ( clientNum != demo.spectatorClientNum ) { + { playerState_t *gamePs = SV_GameClientNum( clientNum ); Com_Memset( gamePs, 0, sizeof(*gamePs) ); } @@ -906,9 +894,6 @@ void SVD_Play_f( void ) { demo.playing = qtrue; demo.endOfDemo = qfalse; - // The spectator gets the highest slot: MAX_CLIENTS - 1 - demo.spectatorClientNum = MAX_CLIENTS - 1; - Com_Printf( "Playing server demo: map=%s maxclients=%d fps=%d\n", demo.playMapName, demo.playMaxClients, demo.playFps ); @@ -1032,6 +1017,3 @@ qboolean SVD_IsPlaying( void ) { return demo.playing; } -int SVD_SpectatorClientNum( void ) { - return demo.spectatorClientNum; -}