Skip to content

feat(network): Repair datagram loss with adaptive redundancy - #659

Open
tintinhamans wants to merge 6 commits into
GeneralsOnlineDevelopmentTeam:mainfrom
tintinhamans:arctic/go/stack2/04-loss-repair
Open

tintinhamans wants to merge 6 commits into
GeneralsOnlineDevelopmentTeam:mainfrom
tintinhamans:arctic/go/stack2/04-loss-repair

Conversation

@tintinhamans

@tintinhamans tintinhamans commented Oct 25, 2026 •

Copy link
Copy Markdown

Merge after #658.

With reliable GNS delivery a lost packet holds up every packet behind it until GNS resends it, and the match stalls for that whole time. More input delay does not help, because the stalls come from the resend wait. send.mode can now be "datagram" (the default, "reliable" keeps the old behavior), which sends game packets as unreliable datagrams and lets the game layer repair loss.

With send.redundancy (true) a command that is not acked yet is repeated in the packets that go out anyway, as deep as the measured loss asks for. The depth is capped by send.redundancy_burst_ms (150) and decays when the loss stops, and send.redundancy_window_ms sets how long a command waits before it is repeated. A repeating connection sends every frame (send.frames_per_packet_lossy). When the round trip climbs to twice its low while packets are lost, the loss comes from a full queue and the depth steps down instead of up. With send.fast_resend (true) an unacked command is resent after the smoothed round trip plus 2 x jitter (at most 400 ms) instead of 4 x jitter (at most 1 s). Redundant copies are counted once and acked again.

All three are on by default, as in the tester build, and the service can turn each off. LAN uses the same defaults. Redundancy costs upload by design: it grows with the loss and is zero on a clean link. The traffic was not measured separately.

It also ports TheSuperHackers#3564. A repeat command in a packet with no command before it to repeat dereferenced a null pointer in release builds, and the last command stayed set after an unrecognized packet entry. The repeat is now skipped, and the last command is cleared after an unrecognized entry. No wire change.

Tested: builds x86 Release z_generals. The full stack had 0 CRC mismatches in 3 player rig runs, n=1.

@tintinhamans
tintinhamans force-pushed the arctic/go/stack2/04-loss-repair branch from 8a49653 to 6ecc67e Compare October 28, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant