Serialize commander bracket to fix network client game-start crash#11164
Open
MostCromulent wants to merge 2 commits into
Open
Serialize commander bracket to fix network client game-start crash#11164MostCromulent wants to merge 2 commits into
MostCromulent wants to merge 2 commits into
Conversation
The commander-bracket tooltip called GameView.getDeck(), which dereferences the server-only transient match field and NPEs on network clients — crashing during openView and freezing the client in the lobby. Compute the bracket host-side and serialize it as a PlayerView property instead of reaching through the deck, so clients get the value directly. Addresses <!-- -->Card-Forge#11135. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
|
looks like the same crash happens if remote client calls can't we better access GameLobby since both sides should already be able to reach decks this way? |
Hanmac
previously approved these changes
Jul 6, 2026
Clients already receive every player's deck in the lobby broadcast, so resolve decks from ClientGameLobby instead of the server-only match (getMatch() is transient and null after deserialization). This fixes both the commander bracket tooltip and the Game Menu deck list, which shared the same getDeck NPE on clients. The tooltip stayed hidden for a second reason: it is gated on the maximum-bracket preference, but that control lives only in the host's lobby start panel. A client never sets it, so its local copy stays at the default of 5 (off - the gate wants 1-4) and never passes. The host's value now travels in the lobby state, so clients gate the tooltip on the host's setting and both sides display identically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Closes #11135.
Summary
Fixes a crash that stranded non-host players on the lobby screen when a network Commander game started.
Bug report
The host started the game, but the client stayed in the lobby while the match ran on the server (card sounds audible, no board). The client log showed a
NullPointerExceptionduringopenView:Root cause
The commander-bracket tooltip added in #10803 calls
GameView.getDeck(player), which dereferencesGameView'stransient, server-onlymatchfield — null on every network client by design (registered decks live only on the host). The tooltip NPEs as the client builds itsVFields, aborting match-screen setup. It only triggers when the client'sDECKGEN_MAXIMUM_COMMANDER_BRACKETis 1–4; the default short-circuits before the deck is touched.Fix
The host computes each player's bracket at game start and publishes it as a serialized
PlayerViewproperty, which the tooltip reads instead of the deck.VFieldno longer callsgetDeck, so the crash is gone and the bracket displays on clients in parity with the host.Why this is architecturally consistent
GameViewalready serializes its other match-derived data (title, games-played, match-over) asTrackablePropertyvalues, instead of reaching through the transientmatchfield.CommanderBracketCalculator(aforge-guiclassforge-gamecan't depend on) lives.🤖 Generated with Claude Code