Skip to content

feat(server): add onesync_minFrameRetention - #4400

Open
OneEarJoe5 wants to merge 1 commit into
citizenfx:masterfrom
OneEarJoe5:fix/onesync-min-frame-retention
Open

OneEarJoe5 wants to merge 1 commit into
citizenfx:masterfrom
OneEarJoe5:fix/onesync-min-frame-retention

Conversation

@OneEarJoe5

Copy link
Copy Markdown

Goal of this PR

Since bd84727 (retain frames based on client silence) a client only gets the 60 s worst-case backlog after 5 s without any update from it. A client that stops receiving for a bit but keeps sending its own sync never hits that, so it keeps the default 650 frames. Once packets get through again it NAcks the frames it missed, those are already erased, and it's dropped with Timed out after 60 seconds (1, ...). Before that commit the check was always true, so every client kept ~60 s and recovered from short network hiccups. That's what #4394 is seeing.

How is this PR achieving the goal

Adds a convar onesync_minFrameRetention (seconds, default 0). When set, the frame backlog for every client is at least that long. The seconds are turned into frames with the current sync rate (effectiveTicksPerSecond, the frame index goes up once per sync tick) and capped at maxSavedClientFramesWorstCase. With 0 nothing changes, so the memory improvement from bd84727 stays for everyone who doesn't need it.

I went with a convar because in NAK mode the server has no way to tell that a client is behind until the NAck comes in, and by then the frames are gone. If you'd rather change the default (or have a better signal for "client is behind"), happy to adjust.

This PR applies to the following area(s)

Server

Successfully tested on

Game builds: 3889

Platforms: Windows (server)

Official client against a server built from current master (5412ed8), with and without this commit. To get a reproducible stall I used a local test-only hack that stops sending msgPackedClones to the client for N seconds while it keeps sending (not part of this PR). With one player the server runs at 40 sync ticks per second, so the default 650 frames is ~16 s here.

Setup Stall Result
master without this PR 25 s dropped, Timed out after 60 seconds (1, 985, 938)
this PR, set onesync_minFrameRetention 30 in the cfg 25 s stays connected, sync resumes
same 35 s dropped, (1, 1372, 144), so 30 s really is ~30 s (1200 frames)
set to 0 at runtime 25 s dropped, (1, 982, 63), same as without the convar
onesync_automaticResend true, convar 0 and 30 25 s stays connected both times (ARQ doesn't NAck old frames, so it isn't affected). Tested before I switched the seconds to the sync rate, that change doesn't touch this.

Added unit tests for the backlog limit next to the existing ones, they pass.

Not tested: Linux, real packet loss (only the stall hack above) and servers with many players.

Checklist

  • Code compiles and has been tested successfully.
  • Code explains itself well and/or is documented.
  • My commit message explains what the changes do and what they are for.
  • No extra compilation warnings are added by these changes.

Fixes issues

fixes #4394

Since frame retention is based on client silence, a client that stops
receiving for a while but keeps sending only gets the default backlog
of 650 frames. When packets come through again it NAcks frames that are
already gone and gets dropped with "Timed out after 60 seconds (1, ...)".
Before that change every client effectively kept the 60 s worst case.

Add onesync_minFrameRetention (seconds, 0 = off) so servers that see
these drops can keep frames longer for everyone. The seconds are turned
into frames with the current sync rate and capped at the worst-case
backlog. The default doesn't change anything.

Signed-off-by: OneEarJoe5 <212275319+OneEarJoe5@users.noreply.github.com>
@github-actions github-actions Bot added the invalid Requires changes before it's considered valid and can be (re)triaged label Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid Requires changes before it's considered valid and can be (re)triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OneSync: clients dropped with "Timed out after 60 seconds (2)" since frame retention change (38386+)

1 participant