-
Notifications
You must be signed in to change notification settings - Fork 839
Network multiplayer optimization (reconnect) #9708
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MostCromulent
wants to merge
9
commits into
Card-Forge:master
Choose a base branch
from
MostCromulent:NetworkPlay/reconnect
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Network multiplayer optimization (reconnect) #9708
MostCromulent
wants to merge
9
commits into
Card-Forge:master
from
MostCromulent:NetworkPlay/reconnect
+383
−39
Conversation
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
…Client slot tracking) Port changes from NetworkPlay/main that prevent server deadlock on client disconnect: - ReplyPool.cancelAll(): completes all pending futures with null - RemoteClient.cancelPendingReplies(): calls cancelAll on disconnect - RemoteClient.UNASSIGNED_SLOT / hasValidSlot(): slot assignment tracking These are correctness fixes for the existing disconnect path, not reconnection-specific. Already in use on main via DeregisterClientHandler.channelInactive(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… takeover) When a remote client disconnects mid-game, the server now pauses the game and waits up to 120 seconds for the player to rejoin. If the same username reconnects, the channel is swapped on the original RemoteClient, game state is resynced, and the current prompt is replayed. If the timeout expires, the player is converted to AI and the game continues. Key changes: - RemoteClient: volatile channel/replies, swapChannel() for reconnection - NetGuiGame: pause/resume (sends become no-ops), null-safe primitive returns to prevent NPE from cancelAll()/timeout null values - FServerManager: reconnection flow in DeregisterClientHandler/LobbyInputHandler, helper methods for pause/resume/resync/AI conversion, ConcurrentHashMap for thread-safe client tracking - GameLobby: getHostedMatch() accessor for server reconnection logic Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GameClientHandler: capture GameView synchronously in beforeCall(setGameView) as pendingGameView fallback for when gui.getGameView() is null during createMatch() (EDT hasn't processed setGameView yet when openView arrives) - FServerManager.resumeAndResync: send updateGameView() before openView() to match normal HostedMatch.startGame() message ordering - FServerManager: fix same-username loop in resumeAndResync/pauseNetGuiGame — continue searching when name matches but GUI is CMatchUI (host), not NetGuiGame - HostedMatch: add getGuiForPlayer() and dumpGuis() for authoritative GUI lookup - Add diagnostic logging to trace guis map contents during reconnect Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The game engine deduplicates identical player names (e.g. "2nd MostCromulent") so name-based matching in pauseNetGuiGame/resumeAndResync never finds the remote player. Store slotIndex on NetGuiGame and match by that instead. - NetGuiGame: add slotIndex field and getter - pauseNetGuiGame/resumeAndResync: match by netGui.getSlotIndex() == slotIndex - Remove unused findGuiForPlayer() and dumpGuis() diagnostic methods Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ommands Replace single-fire 300s timer with periodic 30s countdown that broadcasts M:SS formatted messages. Add /skipreconnect (force AI takeover) and /skiptimeout (disable timer, wait indefinitely) host commands. Suppress slash commands from remote clients. Fix convertToAI to match by slot index instead of player name. Intercept host commands in NetConnectUtil before broadcasting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Integrate upstream changes: version exchange warning (Card-Forge#9698), host/client differentiated lobby messages, and (Host) chat indicator. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unused disconnected flag from RemoteClient (pause on NetGuiGame handles send suppression, clients map removal prevents broadcasts). Fix inline comments: remove session-specific labels and case-specific examples per comment durability guideline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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
THIS PR HAS BEEN SPLIT FROM #9642.
Network reconnection support: when a remote client disconnects mid-game, the server pauses the game and waits for them to reconnect. If they don't return in time, AI takes over their seat. Host can skip reconnect and pass to AI immediately, or skip timeout and give indefinite time for client to reconnect.
Details
Features
Dependency
This branch targets master and is independent from #9642 (delta sync). Both branches modify FServerManager, NetGuiGame, and RemoteClient, so depending on merge order there will be merge conflicts in the other — but the features are architecturally separate and either can merge first.
Technical Implementation
The reconnection flow has three phases:
Username is used only for reconnection identity (matching a new connection to a previously disconnected client). All game-state operations (pausing, resuming, AI conversion) use slot index via NetGuiGame.getSlotIndex(). This is theoretically fragile to multiple clients with identical usernames, but unlikely to emerge in real play.
GameClientHandler captures the GameView synchronously on the IO thread (pendingGameView) to handle the EDT timing race where setGameView is queued but hasn't executed when openView arrives.
Slash commands are host-only — remote client messages starting with / are suppressed at the server.
Files Changed
FServerManager.javaNetGuiGame.javaRemoteClient.javaReplyPool.javaGameClientHandler.javaHostedMatch.javaGameLobby.javaNetConnectUtil.javaTesting
🤖 Code authored by Claude (Opus 4.6) under human direction.