Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
157 commits
Select commit Hold shift + click to select a range
910e1d4
Network play optimization: delta sync and reconnection support
MostCromulent Jan 20, 2026
157d254
Delta sync improvements: new object handling, compact serialization
MostCromulent Jan 20, 2026
84f7b41
Delta sync debugging infrastructure (untested)
MostCromulent Jan 20, 2026
f06d2da
Fix network play: client can now see hand before mulligan
MostCromulent Jan 20, 2026
696e561
Configurable network debug logging (untested)
MostCromulent Jan 20, 2026
d687008
Improve network play chat notifications with enhanced visibility
claude Jan 20, 2026
92558c5
Document enhanced chat notifications as third major feature
claude Jan 20, 2026
d60bb10
Merge pull request #1 from MostCromulent/claude/improve-chat-notifica…
MostCromulent Jan 20, 2026
c71375d
Streamline BRANCH_DOCUMENTATION.md by removing historical details
claude Jan 20, 2026
ba808d3
Fix errant '2' in documentation header
claude Jan 20, 2026
490dc35
Add hyperlinks from Overview to feature sections
claude Jan 20, 2026
ec33efd
Merge pull request #2 from MostCromulent/claude/improve-chat-notifica…
MostCromulent Jan 21, 2026
58c9494
Implement AI takeover for timed-out players with host override command
claude Jan 21, 2026
9a31137
Update documentation with AI takeover and /skipreconnect command details
claude Jan 21, 2026
181573a
Reorganize documentation: move AI takeover to logical section
claude Jan 21, 2026
56c919b
Add AI-assisted debugging section to documentation
claude Jan 21, 2026
4d0d6e0
Update overview with AI takeover mention and debugging link
claude Jan 21, 2026
52cb8c9
Remove AI-assisted debugging references from documentation
claude Jan 21, 2026
102fa18
Update Future Improvements section
claude Jan 21, 2026
bd7960d
Merge pull request #3 from MostCromulent/claude/networkplay-ai-takeov…
MostCromulent Jan 21, 2026
440764f
Fix critical concurrency and data integrity issues
claude Jan 21, 2026
73ee055
Implement high-priority performance and safety optimizations
claude Jan 21, 2026
e83da27
Add NetworkCompressionUtil (WIP - evaluating compression options)
claude Jan 21, 2026
f209346
Document existing LZ4 compression and remove from future improvements
claude Jan 21, 2026
8f3fe64
Remove NetworkCompressionUtil - LZ4 compression already exists
claude Jan 21, 2026
f226f4c
Merge pull request #4 from MostCromulent/claude/critical-fixes-Yzrli
MostCromulent Jan 21, 2026
94a84fb
Merge pull request #5 from MostCromulent/claude/document-lz4-compress…
MostCromulent Jan 21, 2026
df12b62
Add standalone delta sync effectiveness demonstration
claude Jan 21, 2026
9baf0d2
Add bandwidth savings summary to Overview section
claude Jan 21, 2026
e493da7
Merge pull request #6 from MostCromulent/claude/update-overview-compr…
MostCromulent Jan 21, 2026
63fc28a
Add client-side checksum validation with automatic desync recovery
claude Jan 21, 2026
8ea8979
Merge pull request #7 from MostCromulent/claude/checksum-validation-Y…
MostCromulent Jan 21, 2026
77afb25
Add architectural review of NetworkPlay vs Main branch
claude Jan 21, 2026
7d10f62
Add comprehensive refactoring plan for network isolation
claude Jan 21, 2026
fda581f
Consolidate architectural analysis into single comprehensive document
claude Jan 21, 2026
59eccd0
Remove conflict probabilities and prescriptive recommendations from a…
claude Jan 21, 2026
836671d
Remove Testing section from BRANCH_DOCUMENTATION
claude Jan 21, 2026
1d03b9c
Remove mobile-specific references from BRANCH_DOCUMENTATION
claude Jan 21, 2026
f5f0daf
Merge pull request #8 from MostCromulent/claude/architectural-review-…
MostCromulent Jan 21, 2026
5480004
Add validation tests for delta sync size comparison accuracy
claude Jan 21, 2026
cb267d5
Add actual network byte tracking for delta sync comparison
claude Jan 21, 2026
7d44b41
Make network debugger opt-in via system property
claude Jan 21, 2026
dcd7f47
Update BRANCH_DOCUMENTATION.md for network byte tracking
claude Jan 21, 2026
d03973c
Revert "Update BRANCH_DOCUMENTATION.md for network byte tracking"
claude Jan 21, 2026
760d4ce
Change network byte tracking to enabled by default
claude Jan 21, 2026
34b0c0b
Replace system property with NetworkDebug.config file
claude Jan 21, 2026
5f99b21
Update BRANCH_DOCUMENTATION.md for NetworkDebug.config
claude Jan 21, 2026
c4e28f8
Update bandwidth reduction claim to reflect actual network measurements
claude Jan 21, 2026
8e56ba5
Fix internal consistency issues in BRANCH_DOCUMENTATION.md
claude Jan 21, 2026
a206dd9
Reorganize Debugging section and remove Runtime API
claude Jan 21, 2026
81f7ee5
Merge pull request #9 from MostCromulent/claude/validate-sync-compari…
MostCromulent Jan 21, 2026
2e36031
Fix build errors from merged code
MostCromulent Jan 21, 2026
ea637e5
Fix phase marker not updating on client and improve logging
MostCromulent Jan 21, 2026
3945a2a
Fix client hand not visible during mulligan (ID collision)
MostCromulent Jan 21, 2026
8089849
Add debug logging for /skipreconnect AI takeover investigation
MostCromulent Jan 21, 2026
a28ed6d
Update BUGS.md: /skipreconnect AI takeover tentatively resolved
MostCromulent Jan 21, 2026
b08c745
Add BUGS.md reference to BRANCH_DOCUMENTATION.md
MostCromulent Jan 21, 2026
ea49b69
Fix AI takeover race condition and improve lobby chat messages
MostCromulent Jan 21, 2026
86df128
Remove temporary debug logging from PhaseHandler and PlayerControllerAi
MostCromulent Jan 21, 2026
6c60c2b
Fix delta sync checksum race condition and reduce log noise
MostCromulent Jan 21, 2026
19ee9d4
Add collection lookup bug to BUGS.md and increase checksum interval
MostCromulent Jan 21, 2026
527f67d
Update BRANCH_DOCUMENTATION.md
MostCromulent Jan 21, 2026
1719977
Fix collection deserialization ID collision (bug #4)
claude Jan 22, 2026
b6d36ed
Improve bug #4 fix with comprehensive composite key solution
claude Jan 22, 2026
097d77d
Merge pull request #11 from MostCromulent/claude/fix-bugs-md-issue-bSdaN
MostCromulent Jan 22, 2026
702a96e
Add log retention and management features to Network Debugger
MostCromulent Jan 22, 2026
f90c9b2
Improve network debug logging for easier analysis
MostCromulent Jan 22, 2026
e5fdce0
Fix ID collision in sentObjectIds and newObjects tracking
MostCromulent Jan 22, 2026
1d564ab
Fix client-side ID collision: use type-specific lookup in createObjec…
MostCromulent Jan 22, 2026
12aecca
Fix checksum mismatch: use ordinal() instead of hashCode() for PhaseType
MostCromulent Jan 22, 2026
e975417
Add comprehensive network code isolation refactor strategy
claude Jan 23, 2026
e7598df
Extract network code from AbstractGuiGame into NetworkGuiGame subclass
claude Jan 23, 2026
86a3068
Add documentation for critical execution order in GameLobby
claude Jan 23, 2026
47a8041
Remove branch documentation reference from production code comment
claude Jan 23, 2026
89c291b
Update documentation to reflect NetworkGuiGame refactor
claude Jan 23, 2026
077f213
Clarify AbstractGuiGame still has minor network-related changes
claude Jan 23, 2026
d355f5e
Incorporate headless testing infrastructure from claude/headless-netw…
claude Jan 23, 2026
a59df2d
Remove refactor planning documents (refactor now complete)
claude Jan 23, 2026
a21d431
Fix integration issues from refactor branch merge
MostCromulent Jan 23, 2026
a19ad0e
Fix duplicate game event logging in test infrastructure
MostCromulent Jan 23, 2026
1f8acfb
Phase 9: Enable full game completion with remote client
MostCromulent Jan 23, 2026
72f4e33
Fix HeadlessNetworkClient game controller capture and add logging
MostCromulent Jan 23, 2026
0afb1ad
Phase 9 complete: Fix headless testing for full game completion
MostCromulent Jan 23, 2026
5c25fd1
Phase 10: Parallel/sequential network game execution
MostCromulent Jan 23, 2026
a2d9db7
Simplify Phase 10: Remove parallel execution, keep sequential only
MostCromulent Jan 23, 2026
47bb0fb
Phase 10: Add multi-process parallel game execution
MostCromulent Jan 23, 2026
585479f
Phase 10: Comprehensive 3-4 player network test infrastructure
MostCromulent Jan 24, 2026
6af176e
Sanitize user paths in network debug logs for privacy
MostCromulent Jan 24, 2026
9870ac3
Update TESTING_DOCUMENTATION.md with multiplayer network test results
MostCromulent Jan 24, 2026
2b93e29
Comprehensive 100-game delta sync validation complete
MostCromulent Jan 24, 2026
65c7167
Network play UI improvements
MostCromulent Jan 24, 2026
ea714fd
Final comprehensive test: 100% success rate, 99.5% bandwidth savings
MostCromulent Jan 24, 2026
8173076
Use human-readable units in Bandwidth by Player Count table
MostCromulent Jan 24, 2026
964a504
Merge NetworkGUIFix: UI improvements for network play
MostCromulent Jan 24, 2026
0ea1a7c
Document Feature 4: Network Play UI Improvements
MostCromulent Jan 24, 2026
293bf39
Merge remote-tracking branch 'upstream/master' into NetworkPlay
MostCromulent Jan 24, 2026
74ef915
Fix duplicate logging and improve test output formatting
MostCromulent Jan 24, 2026
769f182
Fix duplicate chat messages in multiplayer lobby
MostCromulent Jan 24, 2026
30e4f24
Disable audio in headless testing mode
MostCromulent Jan 24, 2026
9e49bb7
Fix parallel game execution in comprehensive testing
MostCromulent Jan 24, 2026
c3cd37d
Show player name in multiplayer waiting prompts
MostCromulent Jan 24, 2026
03f0a83
Add elapsed time display to network waiting prompts and document mult…
MostCromulent Jan 24, 2026
715cc4d
Fix multiplayer delta sync regression and add per-client property tra…
MostCromulent Jan 24, 2026
b3f505a
Update BUGS.md with comprehensive test status summary
MostCromulent Jan 24, 2026
c294de6
Add authorship section to BRANCH_DOCUMENTATION.md
MostCromulent Jan 24, 2026
acef30a
Update BRANCH_DOCUMENTATION.md: consolidate testing section, fix TOC
MostCromulent Jan 24, 2026
2aad2f9
Fix HeadlessNetworkClient auto-response race condition causing test t…
MostCromulent Jan 24, 2026
78d5ffa
Update documentation with comprehensive test results (96% success rate)
MostCromulent Jan 25, 2026
1997430
Improve batch test log naming and analysis reporting
MostCromulent Jan 25, 2026
2fe5ef4
Update documentation with comprehensive test results (98% success rate)
MostCromulent Jan 25, 2026
4b0ea81
Add [Server]/[Client] log prefixes to distinguish network log sources
MostCromulent Jan 25, 2026
ebc9a88
Fix port bind failures and document desync root cause
MostCromulent Jan 25, 2026
a6e6bb2
Improve batch test log naming with unique batch identifiers
MostCromulent Jan 27, 2026
f6e5604
Add .gitattributes to prevent merging branch-specific files
MostCromulent Jan 27, 2026
fceebb3
Reorganize documentation and fix test infrastructure issues
MostCromulent Jan 27, 2026
43d2bb7
Update .gitattributes for .documentation folder
MostCromulent Jan 27, 2026
fb47e13
Consolidate test infrastructure: merge batch tests, remove unused files
MostCromulent Jan 27, 2026
7f4dfe5
Add feature breakdown section to NetworkPlay.md, rename StagedPR.md
MostCromulent Jan 27, 2026
ab10f73
Streamline documentation: remove redundant PR planning sections
MostCromulent Jan 27, 2026
d53f96a
Enhance batch test analyzer with failure analysis and pattern detection
MostCromulent Jan 27, 2026
1245c2d
Add .gitattributes to merge=ours list
MostCromulent Jan 27, 2026
5090ef8
Fix multiplayer desync bugs #12 and #13
MostCromulent Jan 27, 2026
8d8066d
Fix missing Sideboard/Command zone sync, enhance analyzer output
MostCromulent Jan 27, 2026
3d9f635
Add error context extraction for test failure debugging
MostCromulent Jan 27, 2026
1f231a8
Add server-side AI for remote players in network tests
MostCromulent Jan 28, 2026
1e6ff11
Organize network debug logs and enhance cleanup logic
claude Jan 30, 2026
ad48a59
Migrate network debug config to PreferencesStore pattern
claude Jan 30, 2026
2cc3bec
Remove unnecessary migration files
claude Jan 30, 2026
e322b90
Move network logs to user directory and remove test logs
MostCromulent Jan 30, 2026
d308c36
Restore pre-merge test logs
MostCromulent Jan 30, 2026
9808a34
Replace test logs with 20260129 comprehensive test run
MostCromulent Jan 30, 2026
8b068ef
Merge NetworkPlay/dev into main (code changes only)
MostCromulent Jan 30, 2026
a32524a
Add YieldRework PR documentation to .documentation folder
MostCromulent Feb 1, 2026
2d9c32e
Add PR-Review.md with PR #9642 feedback
MostCromulent Feb 1, 2026
a894318
Address PR 9642 review feedback - Phase 1 fixes
MostCromulent Feb 1, 2026
c3f97f1
Address PR 9642 review feedback - Phase 1 fixes
MostCromulent Feb 1, 2026
9a4643c
Fix GuiBase initialization order in BatchGameTest
MostCromulent Feb 1, 2026
406ade7
Merge NetworkPlay/dev: Fix GuiBase initialization order in BatchGameTest
MostCromulent Feb 1, 2026
576fce4
Skip stress tests by default in CI using TestNG SkipException
MostCromulent Feb 1, 2026
a339fdc
Merge branch 'NetworkPlay/dev' into NetworkPlay/main
MostCromulent Feb 1, 2026
58078cb
Delete .documentation directory
MostCromulent Feb 2, 2026
d0bfee7
Delete .claude directory
MostCromulent Feb 2, 2026
edc02ee
Address Copilot review feedback
MostCromulent Feb 2, 2026
4d0e4fd
Fix null safety for FSkin.getColor() calls
MostCromulent Feb 2, 2026
683857d
Skip AutomatedNetworkTest in CI unless stress tests enabled
MostCromulent Feb 2, 2026
9013887
Remove chat styling changes (now in NetworkPlay/chat branch)
MostCromulent Feb 2, 2026
55e1738
Consolidate network test infrastructure: 17 files removed, ~3100 line…
MostCromulent Feb 4, 2026
2bd6cbf
Add single-game analysis reports and unify output locations
MostCromulent Feb 4, 2026
530c235
Fix bandwidth comparison methodology and parallel test execution
MostCromulent Feb 4, 2026
d1834f2
Unify test results file naming with log file conventions
MostCromulent Feb 3, 2026
a3a72db
Run unit tests and testTrueNetworkTraffic in default CI
MostCromulent Feb 3, 2026
df848f0
Fast CI test with minimal decks, rename DeltaSyncUnitTest
MostCromulent Feb 4, 2026
542de52
Remove duplicate result logging from integration tests
MostCromulent Feb 3, 2026
2b7b141
Fix Bug 14 (NPE disconnect) and Bug 15 (TreeSet cast), sanitize paths
MostCromulent Feb 4, 2026
f37080d
Fix Bug 16 (checksum race condition) and Bug 17 (slot assignment)
MostCromulent Feb 4, 2026
6016296
Remove UI enhancements from delta sync branch
MostCromulent Feb 4, 2026
d6da942
Remove ~1700 lines of dead reconnection code (RECONNECT-REFACTOR)
MostCromulent Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
* text=auto
* text=auto

# Prevent merging of branch-specific files
# These files use "ours" merge strategy - local version is always kept during merges
.gitattributes merge=ours
testlogs/ merge=ours
testlogs/** merge=ours
.documentation/ merge=ours
.documentation/** merge=ours
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,8 @@ forge-gui/tools/PerSetTrackingResults
# Ignore python temporaries
__pycache__
*.pyc

# Ignore Claude configuration files
.claude
CLAUDE.md

8 changes: 8 additions & 0 deletions forge-game/src/main/java/forge/game/GameView.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,12 @@ public GameOutcome getOutcome() {
public AnteResult getAnteResult(PlayerView player) {
return getOutcome().getAnteResult(player);
}

@Override
public String toString() {
return String.format("GameView[id=%d, turn=%d, phase=%s, players=%d, gameOver=%b]",
getId(), getTurn(), getPhase(),
getPlayers() != null ? getPlayers().size() : 0,
isGameOver());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ public StackItemView(SpellAbilityStackInstance si) {
updateOptionalCost(si);
}

/**
* Constructor for network deserialization.
* Creates an empty StackItemView that will be populated via property deserialization.
*/
public StackItemView(final int id0, final forge.trackable.Tracker tracker) {
super(id0, tracker);
}

public String getKey() {
return get(TrackableProperty.Key);
}
Expand Down
43 changes: 42 additions & 1 deletion forge-game/src/main/java/forge/trackable/TrackableObject.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package forge.trackable;

import java.io.Serializable;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
Expand Down Expand Up @@ -64,7 +65,7 @@ protected final <T> T get(final TrackableProperty key) {
return value;
}

protected final <T> void set(final TrackableProperty key, final T value) {
public final <T> void set(final TrackableProperty key, final T value) {
if (tracker != null && tracker.isFrozen()) { //if trackable objects currently frozen, queue up delayed prop change
boolean respectsFreeze = false;
if (key.getFreezeMode() == TrackableProperty.FreezeMode.RespectsFreeze) {
Expand Down Expand Up @@ -130,4 +131,44 @@ public final void deserialize(final TrackableDeserializer td) {
}
changedProps.clear();
}

// Delta sync support methods
/**
* Check if this object has any changed properties that need to be synced.
* @return true if there are pending changes
*/
public final boolean hasChanges() {
return !changedProps.isEmpty();
}

/**
* Get an unmodifiable view of the changed properties.
* Changes are not cleared until clearChanges() is called.
* @return set of properties that have changed
*/
public final Set<TrackableProperty> getChangedProps() {
return Collections.unmodifiableSet(changedProps);
}

/**
* Clear the change tracking flags after changes have been acknowledged.
* Should be called after delta has been sent and acknowledged by client.
*/
public final void clearChanges() {
changedProps.clear();
}

/**
* Serialize only the changed properties (for delta sync).
* Does not clear the change flags - call clearChanges() separately after acknowledgment.
* @param ts the serializer to write to
*/
public final void serializeChangedOnly(final TrackableSerializer ts) {
ts.write(changedProps.size());
for (TrackableProperty key : changedProps) {
ts.write(TrackableProperty.serialize(key));
key.serialize(ts, props.get(key));
}
// Note: Does not clear changedProps - that's done on acknowledgment
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ private void join(final String url) {
});

final ChatMessage result = NetConnectUtil.join(url, VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
if(Objects.equals(result.getMessage(), ForgeConstants.CLOSE_CONN_COMMAND)) {
String message = result.getMessage();
if(Objects.equals(message, ForgeConstants.CLOSE_CONN_COMMAND)) {
FOptionPane.showErrorDialog(Localizer.getInstance().getMessage("UnableConnectToServer", url));
SOverlayUtils.hideOverlay();
} else if (Objects.equals(result.getMessage(), ForgeConstants.INVALID_HOST_COMMAND)) {
} else if (Objects.equals(message, ForgeConstants.INVALID_HOST_COMMAND)) {
FOptionPane.showErrorDialog(Localizer.getInstance().getMessage("lblDetectedInvalidHostAddress", url));
SOverlayUtils.hideOverlay();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,24 @@ public boolean onClosing(final FScreen screen) {

@Override
public void closeConn(String msg) {
// Clean up connection state
if (client != null) {
client.close();
client = null;
}
FServerManager server = FServerManager.getInstance();
if (server.isHosting()) {
server.stopServer();
}
FNetOverlay.SINGLETON_INSTANCE.reset();

// Clear lobby and repopulate
this.lobby = null;
populate();

// Show error message if provided
if (msg != null && !msg.isEmpty()) {
SOptionPane.showErrorDialog(msg, Localizer.getInstance().getMessage("lblConnectionError"));
}
}
}
39 changes: 36 additions & 3 deletions forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
import forge.game.spellability.StackItemView;
import forge.game.spellability.TargetChoices;
import forge.game.zone.ZoneType;
import forge.gamemodes.match.AbstractGuiGame;
import forge.gamemodes.net.NetworkDebugLogger;
import forge.gui.FNetOverlay;
import forge.gui.FThreads;
import forge.gui.GuiBase;
Expand Down Expand Up @@ -123,7 +123,9 @@
import forge.toolbox.imaging.FImageUtil;
import forge.toolbox.special.PhaseIndicator;
import forge.toolbox.special.PhaseLabel;
import forge.trackable.Tracker;
import forge.trackable.TrackableCollection;
import forge.trackable.TrackableTypes;
import forge.util.FSerializableFunction;
import forge.util.ITriggerEvent;
import forge.util.Localizer;
Expand All @@ -144,7 +146,7 @@
* <br><br><i>(C at beginning of class name denotes a control class.)</i>
*/
public final class CMatchUI
extends AbstractGuiGame
extends forge.gamemodes.net.NetworkGuiGame
implements ICDoc, IMenuProvider {

public static final EnumSet<ZoneType> FLOATING_ZONE_TYPES = EnumSet.of(ZoneType.Library, ZoneType.Graveyard, ZoneType.Exile,
Expand Down Expand Up @@ -293,6 +295,13 @@ private void initMatch(final FCollectionView<PlayerView> sortedPlayers, final Co
this.sortedPlayers = sortedPlayers;
allHands = sortedPlayers.size() == getLocalPlayerCount();

// Debug logging for network play
NetworkDebugLogger.debug("[CMatchUI.initMatch] sortedPlayers count=%d", sortedPlayers.size());
for (PlayerView p : sortedPlayers) {
NetworkDebugLogger.debug("[CMatchUI.initMatch] Player ID=%d, hash=%d, isLocal=%b",
p.getId(), System.identityHashCode(p), (myPlayers != null && myPlayers.contains(p)));
}

final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");

final List<VField> fields = new ArrayList<>();
Expand Down Expand Up @@ -435,6 +444,10 @@ public void updateZones(final Iterable<PlayerZoneUpdate> zonesToUpdate) {
for (final PlayerZoneUpdate update : zonesToUpdate) {
final PlayerView owner = update.getPlayer();

// Debug logging
NetworkDebugLogger.debug("[CMatchUI.updateZones] Processing update for player %d, zones=%s, ownerHash=%d",
owner.getId(), update.getZones(), System.identityHashCode(owner));

boolean setupPlayZone = false, updateHand = false, updateAnte = false, updateZones = false;
for (final ZoneType zone : update.getZones()) {
switch (zone) {
Expand All @@ -460,13 +473,19 @@ public void updateZones(final Iterable<PlayerZoneUpdate> zonesToUpdate) {
cAntes.update();
}
final VField vField = getFieldViewFor(owner);
if(vField == null)
if(vField == null) {
NetworkDebugLogger.error("[CMatchUI.updateZones] ERROR: vField is null for player %d, sortedPlayers.indexOf=%d",
owner.getId(), sortedPlayers.indexOf(owner));
return;
}
if (setupPlayZone) {
vField.getTabletop().update();
}
if (updateHand) {
final VHand vHand = getHandFor(owner);
NetworkDebugLogger.debug("[CMatchUI.updateZones] updateHand for player %d, vHand=%s, handSize=%s",
owner.getId(), (vHand != null ? "exists" : "NULL"),
(owner.getHand() != null ? String.valueOf(owner.getHand().size()) : "null"));
if (vHand != null) {
vHand.getLayoutControl().updateHand();
}
Expand Down Expand Up @@ -1025,11 +1044,25 @@ public Map<Object, Integer> assignGenericAmount(final CardView effectSource, fin

@Override
public void openView(final TrackableCollection<PlayerView> myPlayers) {
NetworkDebugLogger.log("[CMatchUI.openView] Called");
final GameView gameView = getGameView();
gameView.getGameLog().addObserver(cLog);

// Sort players
FCollectionView<PlayerView> players = gameView.getPlayers();

// Debug: Log PlayerView instances from gameView
NetworkDebugLogger.debug("[CMatchUI.openView] gameView.getPlayers() count=%d", players.size());
for (PlayerView pv : players) {
Tracker t = pv.getTracker();
PlayerView inTracker = t != null ? t.getObj(TrackableTypes.PlayerViewType, pv.getId()) : null;
NetworkDebugLogger.debug("[CMatchUI.openView] Player %d: hash=%d, tracker=%s, inTracker=%b, sameInstance=%b",
pv.getId(), System.identityHashCode(pv),
t != null ? "exists" : "null",
inTracker != null,
pv == inTracker);
}

if (players.size() == 2 && myPlayers != null && myPlayers.size() == 1 && myPlayers.get(0).equals(players.get(1))) {
players = new FCollection<>(new PlayerView[]{players.get(1), players.get(0)});
}
Expand Down
Loading