Network multiplayer optimization (reconnect)#9708
Merged
tool4ever merged 10 commits intoCard-Forge:masterfrom Feb 11, 2026
Merged
Network multiplayer optimization (reconnect)#9708tool4ever merged 10 commits intoCard-Forge:masterfrom
tool4ever merged 10 commits intoCard-Forge:masterfrom
Conversation
…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>
tool4ever
approved these changes
Feb 11, 2026
MostCromulent
added a commit
to MostCromulent/forge
that referenced
this pull request
Feb 12, 2026
Incorporate 18 master commits including PR Card-Forge#9708 (reconnection), card/game updates, adventure content, and bug fixes. ## Conflict resolution (4 files) **FServerManager.java** — Accepted master's full reconnection system (disconnectedClients, reconnectTimers, pause/resume, AI conversion, /skipreconnect and /skiptimeout commands). Kept NP/main's playerGuis caching in getGui() to preserve DeltaSyncManager state across games. Added NP/main's cancelPendingReplies() before reconnection check in channelInactive(). Converted all reconnection System.out.println to NetworkDebugLogger.log(). Added logging to pause, resume, resync, channel swap, AI conversion, slash commands, and prompt replay. **NetGuiGame.java** — Kept NP/main's delta sync architecture as base. Added master's pause/resume mechanism (volatile boolean paused, no-op send when paused, null-safe dialog returns). Added getSlotIndex() as alias for clientIndex. Added resetForReconnect() to clear delta sync state for reconnecting clients. Fixed resync ordering: use updateGameView() (sends setGameView protocol) not sendFullState() (sends fullStateSync protocol) — client needs gameView set before openView arrives. **RemoteClient.java** — Accepted all from both sides (complementary). Made channel and replies volatile (master). Added swapChannel() for reconnection (master). Kept cancelPendingReplies() (NP/main). **GameClientHandler.java** — Kept NP/main's version. Master's pendingGameView fix addresses a race condition in old client-side Match creation that NP/main already eliminated. ## Auto-merged with fixup (1 file) **GameLobby.java** — Removed duplicate getHostedMatch() from auto-merge (both sides added identical method). ## Additional changes (1 file) **DeltaSyncManager.java** — Added reset() method to clear all delta sync tracking state, needed by NetGuiGame.resetForReconnect(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Feb 12, 2026
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
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.