Bug Report
What Happened
In MoJhoSto network play, when a remote player activates the Jhoira of the Ghitu Avatar ability (pay 3, discard a card, choose 1 of 3 random instant/sorcery copies to cast for free), the remote player is never presented with the choice dialog. The ability proceeds as if nothing was chosen. The host/local player does not have this issue — they see the choice dialog normally.
Root Cause
When PlayEffect creates ephemeral card copies for the Jhoira choice, these Card objects are not in any game zone. Because they have no zone, PlayerControllerHuman.useSelectCardsInput() returns false, routing the choice through getGui().many() → getChoices().
For remote players, RemoteClientGuiGame.getChoices() sends the choice list over the network via ProtocolMethod.getChoices. During serialization, CompatibleObjectEncoder replaces TrackableObject references (including CardView) with lightweight IdRef markers containing only the object ID.
The problem: these ephemeral CardView objects were never synced to the client via delta sync or full game state — they exist only transiently on the server for the duration of the choice. When the client's TrackableSerializer.resolve() tries to look up the IdRef IDs in its Tracker, they don't exist, resolving to null. The client receives an empty choice list and the ability fizzles.
Fix
File: forge-gui/src/main/java/forge/gamemodes/net/TrackableSerializer.java
Modified TrackableSerializer.replace() to always serialize CardView objects as EventCardRef (which carries card name + image key) instead of bare IdRef. The existing resolve() method already handles EventCardRef by creating a detached CardView when the ID isn't in the tracker. PlayerView objects still use IdRef since they're always in the tracker.
This ensures any CardView — including ephemeral copies from PlayEffect — can be properly reconstructed on the client for display in choice dialogs.
Replace (in replace() method):
if (!eventMode || tag == TYPE_PLAYER_VIEW) {
return new IdRef(tag, trackable.getId());
}
With:
if (tag == TYPE_PLAYER_VIEW) {
return new IdRef(tag, trackable.getId());
}
boolean preserveSnapshot = false;
if (tracker != null) {
TrackableType<?> type = trackableTypeFor(tag);
if (type != null) {
Object tracked = tracker.getObj(type, trackable.getId());
if (tracked != null && tracked != trackable) {
preserveSnapshot = true;
}
}
}
CardView cv = (CardView) trackable;
String imgKey = cv.getCurrentState() != null
? cv.getCurrentState().getImageKey(null) : null;
return new EventCardRef(trackable.getId(), cv.getName(), imgKey, preserveSnapshot);
Testing
Fix verified working in local two-instance network play test. Remote player now sees the Jhoira choice dialog and can select a card to cast.
Related: #9861 (network multiplayer meta issue)
Bug Report
What Happened
In MoJhoSto network play, when a remote player activates the Jhoira of the Ghitu Avatar ability (pay 3, discard a card, choose 1 of 3 random instant/sorcery copies to cast for free), the remote player is never presented with the choice dialog. The ability proceeds as if nothing was chosen. The host/local player does not have this issue — they see the choice dialog normally.
Root Cause
When
PlayEffectcreates ephemeral card copies for the Jhoira choice, theseCardobjects are not in any game zone. Because they have no zone,PlayerControllerHuman.useSelectCardsInput()returnsfalse, routing the choice throughgetGui().many()→getChoices().For remote players,
RemoteClientGuiGame.getChoices()sends the choice list over the network viaProtocolMethod.getChoices. During serialization,CompatibleObjectEncoderreplacesTrackableObjectreferences (includingCardView) with lightweightIdRefmarkers containing only the object ID.The problem: these ephemeral
CardViewobjects were never synced to the client via delta sync or full game state — they exist only transiently on the server for the duration of the choice. When the client'sTrackableSerializer.resolve()tries to look up theIdRefIDs in itsTracker, they don't exist, resolving tonull. The client receives an empty choice list and the ability fizzles.Fix
File:
forge-gui/src/main/java/forge/gamemodes/net/TrackableSerializer.javaModified
TrackableSerializer.replace()to always serializeCardViewobjects asEventCardRef(which carries card name + image key) instead of bareIdRef. The existingresolve()method already handlesEventCardRefby creating a detachedCardViewwhen the ID isn't in the tracker.PlayerViewobjects still useIdRefsince they're always in the tracker.This ensures any
CardView— including ephemeral copies fromPlayEffect— can be properly reconstructed on the client for display in choice dialogs.Replace (in
replace()method):With:
Testing
Fix verified working in local two-instance network play test. Remote player now sees the Jhoira choice dialog and can select a card to cast.
Related: #9861 (network multiplayer meta issue)