Auto-record demos with svdemo_autorecord cvar
Set svdemo_autorecord 1 to automatically record a demo on every map load. Demo files are named <mapname>_YYYYMMDD_HHMMSS.svdm in the svdemos/ directory. Refactored SVD_Record_f to use SVD_StartRecording helper so both manual and auto recording share the same code path. Also fixed prevPlayers delta state not being cleared on recording start. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6fc96e7070
commit
e58414f564
3 changed files with 63 additions and 14 deletions
|
|
@ -348,6 +348,7 @@ void SVD_Record_f( void );
|
||||||
void SVD_StopRecord_f( void );
|
void SVD_StopRecord_f( void );
|
||||||
void SVD_RecordFrame( void );
|
void SVD_RecordFrame( void );
|
||||||
void SVD_ResetDeltaState( void );
|
void SVD_ResetDeltaState( void );
|
||||||
|
void SVD_AutoRecord( void );
|
||||||
void SVD_Play_f( void );
|
void SVD_Play_f( void );
|
||||||
void SVD_StopPlay_f( void );
|
void SVD_StopPlay_f( void );
|
||||||
void SVD_Stop_f( void );
|
void SVD_Stop_f( void );
|
||||||
|
|
|
||||||
|
|
@ -552,6 +552,9 @@ void SV_SpawnServer( char *server, qboolean killBots ) {
|
||||||
Hunk_SetMark();
|
Hunk_SetMark();
|
||||||
|
|
||||||
Com_Printf ("-----------------------------------\n");
|
Com_Printf ("-----------------------------------\n");
|
||||||
|
|
||||||
|
// auto-record demo if enabled
|
||||||
|
SVD_AutoRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -618,6 +621,9 @@ void SV_Init (void) {
|
||||||
sv_lanForceRate = Cvar_Get ("sv_lanForceRate", "1", CVAR_ARCHIVE );
|
sv_lanForceRate = Cvar_Get ("sv_lanForceRate", "1", CVAR_ARCHIVE );
|
||||||
sv_strictAuth = Cvar_Get ("sv_strictAuth", "1", CVAR_ARCHIVE );
|
sv_strictAuth = Cvar_Get ("sv_strictAuth", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
|
// server-side demo auto-recording
|
||||||
|
Cvar_Get ("svdemo_autorecord", "0", CVAR_ARCHIVE);
|
||||||
|
|
||||||
// initialize bot cvars so they are listed and can be set before loading the botlib
|
// initialize bot cvars so they are listed and can be set before loading the botlib
|
||||||
SV_BotInitCvars();
|
SV_BotInitCvars();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,41 +321,83 @@ static void SVD_WriteFrame( fileHandle_t f ) {
|
||||||
// Recording commands
|
// Recording commands
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
void SVD_Record_f( void ) {
|
/*
|
||||||
char name[MAX_OSPATH];
|
Start recording a demo with the given name.
|
||||||
char *s;
|
Returns qtrue on success.
|
||||||
|
*/
|
||||||
|
static qboolean SVD_StartRecording( const char *demoname ) {
|
||||||
|
char path[MAX_OSPATH];
|
||||||
|
|
||||||
if ( demo.recording ) {
|
if ( demo.recording ) {
|
||||||
Com_Printf( "Already recording a server demo.\n" );
|
Com_Printf( "Already recording a server demo.\n" );
|
||||||
return;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sv.state != SS_GAME ) {
|
if ( sv.state != SS_GAME ) {
|
||||||
Com_Printf( "Not running a server.\n" );
|
Com_Printf( "Not running a server.\n" );
|
||||||
return;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Com_sprintf( path, sizeof(path), "svdemos/%s.svdm", demoname );
|
||||||
|
|
||||||
|
demo.recordFile = FS_FOpenFileWrite( path );
|
||||||
|
if ( !demo.recordFile ) {
|
||||||
|
Com_Printf( "ERROR: couldn't open %s for writing.\n", path );
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Printf( "Recording server demo to %s\n", path );
|
||||||
|
demo.recording = qtrue;
|
||||||
|
|
||||||
|
// clear delta state for fresh recording
|
||||||
|
Com_Memset( demo.prevEntities, 0, sizeof(demo.prevEntities) );
|
||||||
|
Com_Memset( demo.prevPlayers, 0, sizeof(demo.prevPlayers) );
|
||||||
|
|
||||||
|
SVD_WriteHeader( demo.recordFile );
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVD_Record_f( void ) {
|
||||||
|
char *s;
|
||||||
|
|
||||||
s = Cmd_Argv(1);
|
s = Cmd_Argv(1);
|
||||||
if ( !s[0] ) {
|
if ( !s[0] ) {
|
||||||
Com_Printf( "Usage: svdemo_record <demoname>\n" );
|
Com_Printf( "Usage: svdemo_record <demoname>\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Com_sprintf( name, sizeof(name), "svdemos/%s.svdm", s );
|
SVD_StartRecording( s );
|
||||||
|
}
|
||||||
|
|
||||||
demo.recordFile = FS_FOpenFileWrite( name );
|
/*
|
||||||
if ( !demo.recordFile ) {
|
Auto-record: called from SV_SpawnServer after the map is fully loaded.
|
||||||
Com_Printf( "ERROR: couldn't open %s for writing.\n", name );
|
Generates a name from map name + timestamp.
|
||||||
|
*/
|
||||||
|
void SVD_AutoRecord( void ) {
|
||||||
|
char demoname[MAX_OSPATH];
|
||||||
|
const char *mapname;
|
||||||
|
qtime_t now;
|
||||||
|
|
||||||
|
if ( demo.recording || demo.playing ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Com_Printf( "Recording server demo to %s\n", name );
|
if ( !Cvar_VariableIntegerValue( "svdemo_autorecord" ) ) {
|
||||||
demo.recording = qtrue;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// clear delta state for fresh recording
|
if ( sv.state != SS_GAME ) {
|
||||||
Com_Memset( demo.prevEntities, 0, sizeof(demo.prevEntities) );
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SVD_WriteHeader( demo.recordFile );
|
mapname = Cvar_VariableString( "mapname" );
|
||||||
|
Com_RealTime( &now );
|
||||||
|
Com_sprintf( demoname, sizeof(demoname), "%s_%04d%02d%02d_%02d%02d%02d",
|
||||||
|
mapname,
|
||||||
|
1900 + now.tm_year, 1 + now.tm_mon, now.tm_mday,
|
||||||
|
now.tm_hour, now.tm_min, now.tm_sec );
|
||||||
|
|
||||||
|
SVD_StartRecording( demoname );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVD_StopRecord_f( void ) {
|
void SVD_StopRecord_f( void ) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue