From 3dadde6fd179ed2bbfed8101f73a46c04b153b7d Mon Sep 17 00:00:00 2001 From: serge_shubin Date: Tue, 24 Mar 2026 17:43:10 +0800 Subject: [PATCH] Fix explosions: link entities in SVD_ReadFrame with trBase origin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Entities must be linked immediately when injected, not deferred to G_RunFrame. When multiple server frames execute per SV_Frame cycle, the clearing loop in the next iteration unlinks entities before the snapshot is built — one-frame entities (explosions, temp effects) are lost. G_RunFrame still runs BG_EvaluateTrajectory + trap_LinkEntity to refine origins for moving entities (rockets with TR_LINEAR). Also restore SNAPFLAG_RESET_ENTITIES on unpause so fast-moving entities snap instead of interpolating through the pause gap. Co-Authored-By: Claude Opus 4.6 (1M context) --- code/server/sv_netdemo.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/code/server/sv_netdemo.c b/code/server/sv_netdemo.c index 037d5a7..aa8362a 100644 --- a/code/server/sv_netdemo.c +++ b/code/server/sv_netdemo.c @@ -663,12 +663,16 @@ static qboolean SVD_ReadFrame( fileHandle_t f ) { demo.playPrevEntities[entNum].es = newEs; demo.playPrevEntities[entNum].active = qtrue; - // apply to server entity (entity linking done in G_RunFrame - // which has BG_EvaluateTrajectory for computing currentOrigin) + // apply to server entity and link for PVS. + // use trBase as initial origin — G_RunFrame will refine with + // BG_EvaluateTrajectory for moving entities (rockets etc). ent = SV_GentityNum( entNum ); ent->s = newEs; ent->s.number = entNum; ent->r.svFlags = demo.playPrevEntities[entNum].svFlags; + VectorCopy( newEs.pos.trBase, ent->r.currentOrigin ); + ent->r.linked = qtrue; + SV_LinkEntity( ent ); if ( entNum + 1 > sv.num_entities ) { sv.num_entities = entNum + 1; @@ -908,7 +912,10 @@ void SVD_Pause_f( void ) { if ( !demo.paused ) { // resuming — toggle SERVERCOUNT to reset client snapshot timing // (drifted during pause from identical serverTimes). + // also reset entities so fast-moving objects (rockets) snap to + // position instead of interpolating through the pause gap. svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; + svs.snapFlagServerBit |= SNAPFLAG_RESET_ENTITIES; } Com_Printf( "Demo playback %s.\n", demo.paused ? "paused" : "resumed" ); }