Route libgdx-port checks through the target GUI#10615
Merged
tool4ever merged 1 commit intoMay 6, 2026
Merged
Conversation
PlayerControllerHuman and several input/event handlers branch UI flavor on GuiBase.getInterface().isLibgdxPort() — a process-global check that answers "is this JVM libgdx?" rather than "is the player whose UI will render this libgdx?". On any cross-platform netplay configuration the host steers dialogs, pickers, and notifications down the wrong code path for the receiving client. The visible symptom is Card-Forge/forge<!-- -->Card-Forge#10613: a desktop host serving a mobile client routes tutors through InputSelectEntitiesFromList → tempShowZones, but mobile's tempShowZones is an unimplemented stub, so the library cards never render. Add isLibgdxPort() to IGuiGame. Local GUIs return their process flavor; RemoteClientGuiGame returns the value learned at lobby handshake (LoginEvent gains a libgdx field, stored on RemoteClient at login). Convert every UI-flavor decision that calls getGui() afterwards, and drop arrangeForScry's !isNetPlay workaround for the same defect class. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tool4ever
approved these changes
May 6, 2026
Contributor
tool4ever
left a comment
There was a problem hiding this comment.
nice find + breakdown!
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.
Bug report
Resolves #10613 — On the mobile client against a desktop host, search-your-library effects (Demonic Tutor, Solemn Simulacrum's basic-land trigger, fetch lands) present prompt but no cards are visible.
The general issue
Several UI decision points read
GuiBase.getInterface().isLibgdxPort()to determine whether to route to desktop or mobile rendering paths.This is a process-global static answering "is this JVM libgdx?" — when the right question is "is the player whose UI will render this libgdx?". The two answers agree in single-player and same-platform netplay, but diverge in cross-platform netplay: a desktop host serving a mobile client returns
falseand steers the choice down a desktop-renderer code path the mobile client cannot honor.How it manifests in the tutor case
Desktop host → check returns false → PATH A → host serializes
tempShowZonesover the wire to the mobile client. Mobile'sMatchScreen.tempShowZonesis an unimplemented stub (// pfps needs to actually do something), so cards never render. The same anti-pattern wrong-routes confirm dialogs, scry reorder, end-step discard, AI-skip reveals, and stack notifications.The fix
Add
boolean isLibgdxPort()toIGuiGame. Local GUIs return their process flavor;RemoteClientGuiGamereturns the value the remote sent at lobby handshake (LoginEventgains alibgdxfield, populated byGameClientHandlerand stored onRemoteClientat login). Every UI-flavor decision that callsgetGui()afterwards is converted to the per-GUI check:PlayerControllerHuman.javaPlayerControllerHuman.java!isNetPlay(getGui())workaround for the same defect classPlayerControllerHuman.javaPlayerControllerHuman.javaPlayerControllerHuman.javaPlayerControllerHuman.javaHumanCostDecision.javaInputConfirm.javaInputPayMana.javaFControlGameEventHandler.javaWhy it's safe
Semantically a no-op except where it fixes a bug:
FControlGameEventHandleris only ever bound to a local GUI (HostedMatch.java:237routes remotes toGameEventForwarder) — pure consistency cleanup.LoginEventgains one boolean field; the existing version-mismatch warning catches any wire-format incompatibility between divergent builds.Testing
Original bug can be easily recreated on master by casting Solemn Simulacrum as mobile client with desktop host.
Fix verified on
NetworkPlay/libgdx-handshake: Solemn Simulacrum tutor (desktop host + mobile client, the original repro) now shows the library cards in the picker instead of an empty selection.Note: although the bug report describes a recent change in behaviour, none of the relevant code paths (
PlayerControllerHuman.java:459, theMatchScreen.tempShowZonesstub,useSelectCardsInput,InputSelectEntitiesFromList) appear to have been modified by any recent commit in a way that would introduce this issue. This appears to be a long-standing latent bug.🤖 Generated with Claude Code