added NDP server pause tracking and improved command sequence handling

This commit is contained in:
myT 2023-08-08 02:05:42 +02:00
parent db25062b05
commit 23ce3e0982
3 changed files with 34 additions and 9 deletions

View File

@ -1031,11 +1031,11 @@ qbool CL_CGNDP_IsConfigStringNeeded( int csIndex )
}
void CL_CGNDP_AnalyzeSnapshot( int progress )
qbool CL_CGNDP_AnalyzeSnapshot( int progress )
{
Q_assert(cls.cgameNewDemoPlayer);
Q_assert(progress >= 0 && progress < 100);
VM_Call(cgvm, cls.cgvmCalls[CGVM_NDP_ANALYZE_SNAPSHOT], progress);
return (qbool)VM_Call(cgvm, cls.cgvmCalls[CGVM_NDP_ANALYZE_SNAPSHOT], progress);
}

View File

@ -104,7 +104,7 @@ There's no need to make the player more complex for such an edge case.
#define FULL_SNAPSHOT_INTERVAL_MS (8 * 1000)
#define MAX_COMMANDS ARRAY_LEN(demo.commands)
#define MAX_COMMANDS 256
#define VERBOSE_DEBUGGING 0
@ -155,6 +155,7 @@ struct ndpSnapshot_t {
int snapFlags;
int ping;
qbool isFullSnap;
qbool isServerPaused;
};
struct parser_t {
@ -198,7 +199,7 @@ struct command_t {
struct demo_t {
ndpSnapshot_t snapshots[2]; // current one and next one for CGame requests
demoIndex_t indices[4096];
command_t commands[256];
command_t commands[MAX_COMMANDS];
memoryBuffer_t buffer;
ndpSnapshot_t* currSnap;
ndpSnapshot_t* nextSnap;
@ -213,6 +214,9 @@ struct demo_t {
struct newDemoPlayer_t {
jmp_buf abortLoad;
qbool trackServerPause;
qbool isServerPaused;
int serverPauseDelay; // total duration in server pause since the full snapshot
};
@ -307,13 +311,14 @@ static void MB_Seek( memoryBuffer_t* mb, int position )
}
static void WriteNDPSnapshot( msg_t* outMsg, const ndpSnapshot_t* prevSnap, ndpSnapshot_t* currSnap )
static void WriteNDPSnapshot( msg_t* outMsg, const ndpSnapshot_t* prevSnap, ndpSnapshot_t* currSnap, qbool isServerPaused )
{
const qbool isFullSnap = prevSnap == NULL;
// header
MSG_WriteBits(outMsg, isFullSnap, 1);
MSG_WriteLong(outMsg, currSnap->serverTime);
MSG_WriteBits(outMsg, !!isServerPaused, 1);
// player state
const playerState_t* const oldPS = !prevSnap ? &nullPlayerState : &prevSnap->ps;
@ -660,7 +665,7 @@ static void ParseSnapshot()
// let CGame analyze the snapshot so it can do cool stuff
// e.g. store events of interest for the timeline overlay
demo.currSnap = currNDPSnap;
CL_CGNDP_AnalyzeSnapshot(parser.progress);
const qbool isServerPaused = CL_CGNDP_AnalyzeSnapshot(parser.progress);
// draw the current progress once in a while...
static int lastRefreshTime = Sys_Milliseconds();
@ -676,7 +681,7 @@ static void ParseSnapshot()
MSG_Clear(&writeMsg);
MSG_Bitstream(&writeMsg);
ndpSnapshot_t* const prevNDPSnap = parser.prevSnap;
WriteNDPSnapshot(&writeMsg, isFullSnap ? NULL : prevNDPSnap, currNDPSnap);
WriteNDPSnapshot(&writeMsg, isFullSnap ? NULL : prevNDPSnap, currNDPSnap, isServerPaused);
MB_Write(&demo.buffer, &writeMsg.cursize, 4);
MB_Write(&demo.buffer, writeMsg.data, writeMsg.cursize);
@ -835,6 +840,7 @@ static void ReadNextSnapshot()
}
currSnap->isFullSnap = isFullSnap;
currSnap->serverTime = MSG_ReadLong(&inMsg);
currSnap->isServerPaused = MSG_ReadBits(&inMsg, 1);
// player state
MSG_ReadDeltaPlayerstate(&inMsg, prevSnap ? &prevSnap->ps : &nullPlayerState, &currSnap->ps);
@ -925,6 +931,14 @@ static void ReadNextSnapshot()
}
}
if (ndp.trackServerPause) {
if (currSnap->isServerPaused && ndp.isServerPaused && prevSnap != NULL) {
const int delta = currSnap->serverTime - prevSnap->serverTime;
ndp.serverPauseDelay += delta;
}
ndp.isServerPaused = currSnap->isServerPaused;
}
demo.snapshotIndex++;
}
@ -1056,7 +1070,9 @@ after_parse:
CL_CGNDP_EndAnalysis(clc.demoName, demo.firstServerTime, demo.lastServerTime, videoRestart);
// make sure we don't execute commands from the end of the demo when starting up
demo.numCommands = 0;
demo.commands[0].command[0] = '\0';
demo.commands[1].command[0] = '\0';
demo.numCommands = 1;
const int duration = Sys_Milliseconds() - startTime;
Com_Printf("New Demo Player: loaded demo in %d.%03d seconds\n", duration / 1000, duration % 1000);
@ -1200,6 +1216,10 @@ int CL_NDP_Seek( int serverTime )
demo.commands[i].command[0] = '\0';
}
ndp.trackServerPause = qtrue;
ndp.isServerPaused = qfalse;
ndp.serverPauseDelay = 0;
SeekToIndex(index);
// read more snapshots until we're close to the target time for more precise jumps
@ -1218,6 +1238,11 @@ int CL_NDP_Seek( int serverTime )
numSnapshotsRead++;
}
if (ndp.serverPauseDelay > 0) {
AddCommand(va("server_pause_delay %d", ndp.serverPauseDelay));
}
ndp.trackServerPause = qfalse;
Com_DPrintf("New Demo Player: sought and read %d snaps in %d ms\n",
numSnapshotsRead, Sys_Milliseconds() - seekStartTime);

View File

@ -522,7 +522,7 @@ void CL_CGameRendering( stereoFrame_t stereo );
void CL_SetCGameTime();
void CL_ConfigstringModified();
void CL_CGNDP_EndAnalysis( const char* filePath, int firstServerTime, int lastServerTime, qbool videoRestart );
void CL_CGNDP_AnalyzeSnapshot( int progress );
qbool CL_CGNDP_AnalyzeSnapshot( int progress ); // qtrue when a server pause is active
void CL_CGNDP_AnalyzeCommand( int serverTime );
void CL_CGNDP_GenerateCommands( const char** commands, int* numCommandBytes );
qbool CL_CGNDP_IsConfigStringNeeded( int csIndex );