Skip to content

Conversation

@Sheikah45
Copy link
Member

@Sheikah45 Sheikah45 commented Nov 12, 2025

Summary by CodeRabbit

Release Notes

  • Refactor

    • Improved veto/token management for team matchmaking with clearer behavior and reduced edge-case errors.
    • Streamlined internal data handling for applied vetoes for more predictable updates.
  • Bug Fixes

    • Safer null handling and stability improvements in map selection UI to reduce runtime glitches.
  • Tests

    • Updated tests to reflect the new token-veto workflow and ensure reliability.

@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Walkthrough

Refactors veto handling: adds a VetoKey factory, replaces incremental applied-veto updates with a full-map replacement, changes setTokensForMap signature and behavior, and updates controllers and tests to use the new APIs and improved null-safety.

Changes

Cohort / File(s) Summary
VetoKey Record Enhancement
src/main/java/com/faforever/client/preferences/VetoKey.java
Added import for MapPoolAssignment and a static factory method of(MapPoolAssignment assignment) that builds a VetoKey from assignment.mapPool().mapPool().id() and assignment.id().
UI Controller Refactor
src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileController.java
Improved null-safety and readability: cache local assignment values, use VetoKey.of(value) instead of nested getters, simplified bindings and thumbnail loading; no public API changes.
Service API & Logic Changes
src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingService.java
Removed subscription reacting to AppliedVetoes changes; changed setTokensForMap(VetoKey, Integer)setTokensForMap(VetoKey, int) with removal when 0 and conditional send on actual change; renamed setAllVetoesupdateVetoes and now replaces applied vetoes via building a temporary map and putAll.
Tests Updated
src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileControllerTest.java, src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingServiceTest.java
Removed an unused import; updated tests to use the new setTokensForMap(VetoKey, int) API and to verify emitted VetoData payloads instead of manipulating prefs directly.

Sequence Diagram(s)

sequenceDiagram
    participant UI as MapTileController
    participant Key as VetoKey
    participant Svc as TeamMatchmakingService
    participant Store as AppliedVetoes Map

    UI->>UI: compute local assignment (null-safe)
    UI->>Key: VetoKey.of(assignment)
    Key-->>UI: VetoKey
    UI->>Svc: setTokensForMap(vetoKey, tokens)
    activate Svc
    alt tokens > 0
        Svc->>Store: put(vetoKey, tokens)
    else tokens == 0
        Svc->>Store: remove(vetoKey)
    end
    Svc->>Svc: sendVetoes() if map changed
    deactivate Svc
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to:
    • TeamMatchmakingService#setTokensForMap signature/behavior change and all call sites.
    • updateVetoes replacing map via putAll and any removal semantics.
    • Controller null-checks where VetoKey.of(...) is now used.

Poem

🐰 I craft the key from pool and id,
I guard against the nulls they hid,
Whole maps now hop in, neat and bold,
Tokens shift — a tale retold. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main objective: changing the veto system to only send vetoes as a result of direct player actions rather than automatic triggers.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch maintenance/fix-vetoes-change

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1748148 and 508af08.

📒 Files selected for processing (1)
  • src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingServiceTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingServiceTest.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: checks
  • GitHub Check: checks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4865628 and 1748148.

📒 Files selected for processing (5)
  • src/main/java/com/faforever/client/preferences/VetoKey.java (1 hunks)
  • src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileController.java (7 hunks)
  • src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingService.java (5 hunks)
  • src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileControllerTest.java (0 hunks)
  • src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingServiceTest.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileControllerTest.java
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileController.java (1)
src/main/java/com/faforever/client/fx/NodeController.java (1)
  • NodeController (8-35)
🪛 GitHub Actions: Checks
src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingServiceTest.java

[error] 644-644: Mockito TooManyActualInvocations: fafServerAccessor.setPlayerVetoes(...) called 2 times, but expected to be called 1 time in testSendVetoesOnVetoesChange.

src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingService.java

[error] 269-269: TooManyActualInvocations: sendVetoes(...) called >1 times for setPlayerVetoes; expected 1, but was 2 (observed at TeamMatchmakingService.java:269 and FafServerAccessor.java:338).

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: checks
🔇 Additional comments (6)
src/main/java/com/faforever/client/preferences/VetoKey.java (1)

10-12: LGTM! Clean factory method.

The static factory method centralizes VetoKey creation from MapPoolAssignment, improving consistency across the codebase.

src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingMapTileController.java (2)

168-171: LGTM! Improved null safety.

The added null checks prevent potential NPEs when assignment.getValue() returns null, which is appropriate for a property that may not always have a value.

Also applies to: 181-183, 215-220


175-175: LGTM! Consistent use of the factory method.

Using VetoKey.of(value) instead of manual construction improves consistency and reduces code duplication.

Also applies to: 187-187, 220-220

src/main/java/com/faforever/client/teammatchmaking/TeamMatchmakingService.java (3)

272-283: LGTM! Improved veto change detection.

The refactored setTokensForMap method correctly:

  • Removes entries when tokens are set to 0
  • Updates entries for non-zero values
  • Only calls sendVetoes() when the value actually changes (new entry added or existing entry modified)

The condition on line 280 properly detects actual changes by checking both new entries (previousValue == null && vetoTokensApplied > 0) and modified entries (previousValue != null && previousValue != vetoTokensApplied).


285-293: LGTM! Safer map replacement strategy.

The renamed updateVetoes method now builds a temporary map first, then replaces the entire appliedVetoes map using clear() + putAll(). This is safer than incremental updates when receiving the full veto state from the server.


242-247: Verify: Connection state listener may contradict PR intent.

The PR title is "Only send vetoes on player action," but the connection state listener at line 245 calls sendVetoes() on connection, which is not a player action. This is the root cause of the test failure in TeamMatchmakingServiceTest.java line 644.

Consider whether:

  1. This listener should remain for state synchronization on reconnection (in which case, fix the test as noted in the test file review)
  2. This listener should be removed to fully align with the PR title (send vetoes only on explicit player changes via setTokensForMap)

To verify the intended behavior, please clarify whether sending vetoes on connection is:

  • Intentional for state sync on reconnection
  • Should be removed per the PR title

If it's intentional, the test in TeamMatchmakingServiceTest.java needs to be fixed as indicated in the test file review.

Comment on lines 638 to 645
public void testSendVetoesOnVetoesChange() {
connectionState.set(ConnectionState.CONNECTED);
when(fafServerAccessor.getConnectionState()).thenReturn(ConnectionState.CONNECTED);
// Clear invocations from connection state change
org.mockito.Mockito.clearInvocations(fafServerAccessor);

matchmakerPrefs.getAppliedVetoes().put(new VetoKey(1, 1), 1);
instance.setTokensForMap(new VetoKey(1, 1), 1);

verify(fafServerAccessor, times(1)).setPlayerVetoes(anyList());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the test setup to avoid triggering sendVetoes twice.

The test fails because setPlayerVetoes is called twice:

  1. Line 639 sets connectionState to CONNECTED, triggering the connection state listener in TeamMatchmakingService (lines 242-247) which calls sendVetoes()
  2. Line 642 calls setTokensForMap, which also calls sendVetoes() when the value changes (line 281)

To test only the veto change behavior, clear mock invocations after setting up the connection state.

Apply this diff:

   @Test
   public void testSendVetoesOnVetoesChange() {
     connectionState.set(ConnectionState.CONNECTED);
     when(fafServerAccessor.getConnectionState()).thenReturn(ConnectionState.CONNECTED);
+    clearInvocations(fafServerAccessor);
 
     instance.setTokensForMap(new VetoKey(1, 1), 1);
 
     verify(fafServerAccessor, times(1)).setPlayerVetoes(anyList());
   }
🧰 Tools
🪛 GitHub Actions: Checks

[error] 644-644: Mockito TooManyActualInvocations: fafServerAccessor.setPlayerVetoes(...) called 2 times, but expected to be called 1 time in testSendVetoesOnVetoesChange.

🤖 Prompt for AI Agents
In
src/test/java/com/faforever/client/teammatchmaking/TeamMatchmakingServiceTest.java
around lines 638 to 645, the test setup triggers sendVetoes twice (once when
setting connection state to CONNECTED and again when calling setTokensForMap),
so clear the mock invocation history after initializing the connection state;
specifically, after setting connectionState and stubbing
fafServerAccessor.getConnectionState(), call
Mockito.clearInvocations(fafServerAccessor) (or reset/clearInvocations on the
relevant mock) before calling instance.setTokensForMap so that verify(...,
times(1)).setPlayerVetoes(...) only observes the veto change invocation.

@Sheikah45 Sheikah45 merged commit 0602c5c into develop Nov 12, 2025
4 checks passed
@Sheikah45 Sheikah45 deleted the maintenance/fix-vetoes-change branch November 12, 2025 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants