Skip to content

fix ordered Lua packet timestamp comparison - #7877

Open
Goober5000 wants to merge 1 commit into
scp-fs2open:masterfrom
Goober5000:fix/multi_lua_packet_order
Open

Goober5000 wants to merge 1 commit into
scp-fs2open:masterfrom
Goober5000:fix/multi_lua_packet_order

Conversation

@Goober5000

@Goober5000 Goober5000 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Ordered Lua packets carry a 16-bit millisecond timestamp, and the receiver tossed packets it judged older than the last one accepted on the same channel. That check was broken in several ways: the ushort subtraction was promoted to int, so a delayed packet produced a negative difference and was always accepted; the 10% margin check had its multiplier on the wrong side, tossing genuinely newer packets sent more than a second apart; and even when corrected, the margin compared the sender's gap against the receive gap, so ordinary network jitter tossed newer packets.

Replace the heuristic with serial number arithmetic: a packet is stale when the wrapped 16-bit difference falls in the upper half of the range. Once more than ~16 seconds of local time have passed since the last accepted packet the remote difference is ambiguous, so the packet is accepted as new. The comparison is exposed as multi_lua_packet_is_stale() and covered by unit tests.

The per-channel state was also never cleared, and player ids restart at 0 each game, so a previous game's timestamps could cause packets in the next game to be tossed. Reset it in multi_level_init() and drop a player's channels in delete_player().

Fixes #7872.

@Goober5000 Goober5000 added fix A fix for bugs, not-a-bugs, and/or regressions. multi A feature or issue related to the multiplayer code. scripting A feature or issue related to LUA scripting labels Oct 16, 2026
@Goober5000
Goober5000 force-pushed the fix/multi_lua_packet_order branch 2 times, most recently from 2108567 to c7f22eb Compare October 16, 2026 08:09
Ordered Lua packets carry a 16-bit millisecond timestamp, and the
receiver tossed packets it judged older than the last one accepted on
the same channel.  That check was broken in several ways: the ushort
subtraction was promoted to int, so a delayed packet produced a
negative difference and was always accepted; the 10% margin check had
its multiplier on the wrong side, tossing genuinely newer packets sent
more than a second apart; and even when corrected, the margin compared
the sender's gap against the receive gap, so ordinary network jitter
tossed newer packets.

Replace the heuristic with serial number arithmetic: a packet is stale
when the wrapped 16-bit difference falls in the upper half of the
range.  Once more than ~16 seconds of local time have passed since the
last accepted packet the remote difference is ambiguous, so the packet
is accepted as new.  The comparison is exposed as
multi_lua_packet_is_stale() and covered by unit tests.

The per-channel state was also never cleared, and player ids restart
at 0 each game, so a previous game's timestamps could in principle
cause packets to be tossed if the next game started within the window.
Reset it in multi_level_init() and drop a player's channels in
delete_player(), which also keeps the map bounded.

Fixes scp-fs2open#7872.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Goober5000
Goober5000 force-pushed the fix/multi_lua_packet_order branch from c7f22eb to ad2b69d Compare October 16, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix A fix for bugs, not-a-bugs, and/or regressions. multi A feature or issue related to the multiplayer code. scripting A feature or issue related to LUA scripting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

multi_lua.cpp suspect code

1 participant