the NDP now drops zombie snapshots and pre-time rewind snapshots

This commit is contained in:
myT 2024-01-21 03:11:24 +01:00
parent 9a66155d14
commit 03ba418296
2 changed files with 31 additions and 12 deletions

View file

@ -100,6 +100,9 @@ add: Cinematic Rendering Pipeline CVars
1 - 1/4 pixel count, 9 samples total 1 - 1/4 pixel count, 9 samples total
2 - 1/16 pixel count, 25 samples total 2 - 1/16 pixel count, 25 samples total
fix: the new demo player now drops zombie snapshots and snapshots from before a server time rewind
these problematic snapshots happen right before and after gamestate changes
chg: dropped 32-bit support chg: dropped 32-bit support
chg: dropped Linux/FreeBSD client chg: dropped Linux/FreeBSD client

View file

@ -1,6 +1,6 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 2022 Gian 'myT' Schellenbaum Copyright (C) 2022-2024 Gian 'myT' Schellenbaum
This file is part of Challenge Quake 3 (CNQ3). This file is part of Challenge Quake 3 (CNQ3).
@ -176,6 +176,7 @@ struct parser_t {
int nextFullSnapshotTime; // when server time is bigger, write a full snapshot int nextFullSnapshotTime; // when server time is bigger, write a full snapshot
int serverCommandSequence; // the command number of the latest command we decoded int serverCommandSequence; // the command number of the latest command we decoded
int progress; int progress;
int numGamestates;
}; };
struct demoIndex_t { struct demoIndex_t {
@ -435,7 +436,8 @@ static void ParseServerCommand()
const int commandNumber = MSG_ReadLong(inMsg); const int commandNumber = MSG_ReadLong(inMsg);
const char* const s = MSG_ReadString(inMsg); const char* const s = MSG_ReadString(inMsg);
if (commandNumber <= parser.serverCommandSequence) { if (commandNumber <= parser.serverCommandSequence ||
parser.numGamestates <= 0) {
return; return;
} }
parser.serverCommandSequence = commandNumber; parser.serverCommandSequence = commandNumber;
@ -468,7 +470,7 @@ static void ParseServerCommand()
static void ParseGamestate() static void ParseGamestate()
{ {
msg_t* const inMsg = &parser.inMsg; msg_t* const inMsg = &parser.inMsg;
MSG_ReadLong(inMsg); // skip message sequence parser.serverCommandSequence = MSG_ReadLong(inMsg);
ndpSnapshot_t* const currSnap = parser.currSnap; ndpSnapshot_t* const currSnap = parser.currSnap;
for (;;) { for (;;) {
@ -607,7 +609,7 @@ static void ParseSnapshot()
newSnap->numEntities++; newSnap->numEntities++;
} }
if (!newSnap->valid) { if (!newSnap->valid || parser.numGamestates <= 0) {
return; return;
} }
@ -620,7 +622,19 @@ static void ParseSnapshot()
} }
parser.lastMessageNum = newSnap->messageNum + 1; parser.lastMessageNum = newSnap->messageNum + 1;
if (currServerTime <= parser.prevServerTime) { // some servers reset the server time
// some snapshots are to be ignored entirely at the start of a demo
if (currServerTime < parser.prevServerTime ||
(newSnap->snapFlags & SNAPFLAG_NOT_ACTIVE) != 0) {
// ignore all previous snapshots and the current one too
parser.prevServerTime = currServerTime;
parser.lastMessageNum = newSnap->messageNum + 1;
demo.firstServerTime = INT_MAX;
demo.lastServerTime = INT_MIN;
demo.buffer.numBytes = 0;
demo.numCommands = 0;
demo.numSnapshots = 0;
demo.numIndices = 0;
return; return;
} }
@ -725,7 +739,6 @@ static void ParseDemo()
byte oldData[MAX_MSGLEN]; byte oldData[MAX_MSGLEN];
msg_t* const msg = &parser.inMsg; msg_t* const msg = &parser.inMsg;
const int fh = clc.demofile; const int fh = clc.demofile;
int numGamestates = 0;
Com_Memset(&parser, 0, sizeof(parser)); Com_Memset(&parser, 0, sizeof(parser));
parser.currSnap = &parser.ndpSnapshots[0]; parser.currSnap = &parser.ndpSnapshots[0];
@ -791,8 +804,8 @@ static void ParseDemo()
break; break;
case svc_gamestate: case svc_gamestate:
++numGamestates; ++parser.numGamestates;
if (numGamestates >= 2) { if (parser.numGamestates >= 2) {
Warning("More than 1 gamestate found, only the first one was loaded"); Warning("More than 1 gamestate found, only the first one was loaded");
return; return;
} }
@ -1065,15 +1078,18 @@ after_parse:
demo.nextSnap = &demo.snapshots[1]; demo.nextSnap = &demo.snapshots[1];
MB_InitRead(&demo.buffer); MB_InitRead(&demo.buffer);
// finalize CGame load and set any extra info needed now
// CGame will also restore previous state when videoRestart is qtrue
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 // make sure we don't execute commands from the end of the demo when starting up
demo.commands[0].command[0] = '\0'; demo.commands[0].command[0] = '\0';
demo.commands[1].command[0] = '\0'; demo.commands[1].command[0] = '\0';
demo.numCommands = 1; demo.numCommands = 1;
// finalize CGame load and set any extra info needed now
// CGame will also restore previous state when videoRestart is qtrue
CL_CGNDP_EndAnalysis(clc.demoName, demo.firstServerTime, demo.lastServerTime, videoRestart);
// seek to make sure we're synchronized as if the user had manually asked for said time
CL_NDP_Seek(videoRestart ? demo.currSnap->serverTime : demo.firstServerTime);
const int duration = Sys_Milliseconds() - startTime; const int duration = Sys_Milliseconds() - startTime;
Com_Printf("New Demo Player: loaded demo in %d.%03d seconds\n", duration / 1000, duration % 1000); Com_Printf("New Demo Player: loaded demo in %d.%03d seconds\n", duration / 1000, duration % 1000);
Com_DPrintf("New Demo Player: I-frame delay %d ms, %s -> %s (%.2fx)\n", Com_DPrintf("New Demo Player: I-frame delay %d ms, %s -> %s (%.2fx)\n",