Client-side automatic reconnect for in-game disconnects#10466
Open
MostCromulent wants to merge 1 commit intoCard-Forge:masterfrom
Open
Client-side automatic reconnect for in-game disconnects#10466MostCromulent wants to merge 1 commit intoCard-Forge:masterfrom
MostCromulent wants to merge 1 commit intoCard-Forge:masterfrom
Conversation
On channelInactive the client now enters a RECONNECTING state and retries on a fixed backoff (1s, 5s, 15s, 45s, 60s) with a live modal. On successful resume the server replays the match; on exhausted backoff the modal switches to FAILED (manual rejoin). The server emits a new SeatLostEvent when a reconnect LoginEvent finds no matching slot, replacing the prior "infer from any LobbyUpdateEvent" heuristic. Also adds: - Reconnect modals for desktop and mobile (cancel / rejoin / return- to-main), with proper lobby-state teardown on both platforms - /simulatedisconnect test hook (OUTBOUND/INBOUND) to exercise both detection paths - Server echoes HeartbeatEvent to keep the client's READER_IDLE alive Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
22 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Previously, any mid-match client disconnect forced the player to exit back to the main menu and manually rejoin the server. This PR adds automatic rejoin on disconnect: the client attempts to reconnect in the background for a short window, and the match resumes where it left off if the connection comes back.
Architecture
Symmetric heartbeat
The client already sent a
HeartbeatEventafter 15 seconds of no outbound traffic, so the server could tell it was still alive. This PR makes that symmetrical: the server now echoes the heartbeat back. Both sides treat 45 seconds without any inbound traffic as "connection dead," so a network drop is detected whether the client→server or server→client direction has broken.Client reconnect loop (
FGameClient)When the connection dies (either side's 45s timer fires, or the OS delivers a FIN), the client enters a
RECONNECTINGstate and attempts to reconnect on a fixed backoff schedule (1s, 5s, 15s, 45s, 60s — five attempts) in the background. On a successful reconnect the server replays the game-start protocol plus the current prompt and the match continues. If all five attempts fail the state moves toFAILED; if the server explicitly says the seat is gone, it moves toSEAT_LOST.Server side (
FServerManager.LobbyInputHandler)A
LoginEventfor a user on thedisconnectedClientslist swaps the channel into the existingRemoteClientand callsresumeAndResync— the same path that used to run when a player manually reconnected.A
LoginEventduring an active match for a user not on the disconnected list (window expired or never in this match) gets a newSeatLostEventand a close. This replaces the prior heuristic of inferring seat-loss from anyLobbyUpdateEventduringRECONNECTING, which fired spuriously on the lobby update that normally accompanies a successful resume.Proactive old-channel close
When the client detects the dead connection, it closes its own channel before scheduling the first reconnect attempt, so a FIN reaches the server ASAP. Without this, the reconnect
LoginEventcan arrive before the server has cleaned up the dying session and get rejected as a duplicate login.Player experience (
ReconnectModals, both platforms)When the connection drops, a dialog appears over the match showing a live countdown to the next reconnect attempt. The player can either wait — if reconnect succeeds the dialog closes automatically and the match resumes — or click View Battlefield to dismiss the dialog and let the reconnect loop continue in the background, or Return to Main Menu to give up.
If all five attempts fail the dialog changes to a Connection Lost state with Attempt Rejoin (which restarts the backoff from attempt 1) and Return to Main Menu. If the server tells the client its seat is gone, the dialog changes to Seat Lost with only Return to Main Menu. Return-to-Main fully tears down the network session so the player lands on a clean home screen rather than a stale lobby.
Test hook
The existing client-side
/simulatedisconnectchat command (intercepted inFNetOverlaywhen the sender is anFGameClient) is updated to take a<mode>argument so both detection paths are exercisable:OUTBOUND— drops outbound writes and disables the client's own idle timer, so only the server's 45s timer fires. Simulates a hung client / client→server break.INBOUND— drops inbound reads but lets idle events through, so the client's own 45s timer fires. Simulates a hung server / server→client break.🤖 Generated with Claude Code