Skip to content

Conversation

@kerodkibatu
Copy link
Contributor

Description:

Fixes #2354 and #2353: display ship information in the unit details panel.

Used simple manhattan distance function for boat value estimate.

Please complete the following:

  • I have added screenshots for all UI updates
image image
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

kerverse

@kerodkibatu kerodkibatu requested a review from a team as a code owner November 1, 2025 08:54
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 1, 2025

Warning

Rate limit exceeded

@kerodkibatu has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 22 minutes and 49 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 69f361c and 578e970.

📒 Files selected for processing (4)
  • resources/lang/en.json (1 hunks)
  • src/client/graphics/layers/PlayerInfoOverlay.ts (2 hunks)
  • src/core/game/Game.ts (2 hunks)
  • src/core/game/UnitImpl.ts (4 hunks)

Walkthrough

Adds tracking of a TradeShip's source unit and distance traveled through simulation state and updates, surfaces distance-based trade gold via a new helper in the player UI, and adds a localized "(estimate)" label.

Changes

Cohort / File(s) Change Summary
Player UI
src/client/graphics/layers/PlayerInfoOverlay.ts
Added `calculateTradeShipGold(unit: UnitView): bigint
Localization
resources/lang/en.json
Added estimate key under player_info_overlay with value "(estimate)".
TradeShip execution / spawn
src/core/execution/TradeShipExecution.ts
Pass sourceUnit: this.srcPort when spawning TradeShip; remove internal tilesTraveled; update distance via setDistanceTraveled(distanceTraveled() + 1) during traversal; use tradeShip.distanceTraveled() on completion.
Core unit metadata & updates
src/core/game/Game.ts, src/core/game/GameUpdates.ts, src/core/game/GameView.ts, src/core/game/UnitImpl.ts
Add sourceUnit and optional distanceTraveled to TradeShip params; expose sourceUnit(), distanceTraveled(), and setDistanceTraveled() on Unit/UnitImpl; include sourceUnitId and distanceTraveled in UnitUpdate; add sourceUnitId() and distanceTraveled() accessors on UnitView.
Tests
tests/Warship.test.ts, tests/core/executions/TradeShipExecution.test.ts
Update tests to provide a srcPort as TradeShip sourceUnit; add mocks/state for distanceTraveled and setDistanceTraveled in TradeShipExecution tests.

Sequence Diagram(s)

sequenceDiagram
    participant UI as PlayerInfoOverlay
    participant Calc as calculateTradeShipGold()
    participant UV as UnitView
    participant CFG as config()

    UI->>Calc: request estimate for TradeShip unit
    activate Calc
    Calc->>UV: read distanceTraveled() and sourceUnitId()
    Calc->>UV: count owner's ports (totalUnitLevels Port)
    Calc->>CFG: tradeShipGold(distance, numPorts)
    CFG-->>Calc: return bigint | null
    deactivate Calc
    alt estimate present
        UI->>UI: render gold value + " (estimate)"
    else
        UI->>UI: no estimate shown
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review propagation of sourceUnit and distanceTraveled from spawn (TradeShipExecution) → UnitImpl → UnitUpdate → UnitView.
  • Verify setDistanceTraveled emits updates and is only used for TradeShip instances.
  • Check calculateTradeShipGold handles undefined distance or port counts safely and calls config().tradeShipGold correctly.

Possibly related PRs

  • update meta #1397 — Adjusts config().tradeShipGold signature and call sites to accept numPorts; directly related to the UI call and added port-count usage.
  • Unit count #1402 — Modifies TradeShip execution flow; likely overlaps with the spawn/traversal/completion changes in this PR.
  • Discourage trading with nearby ports #2381 — Changes tradeShipGold calculation (short-range debuff); affects the value rendered and computed by the new UI helper.

Suggested labels

Feature - Frontend, Feature - Simulation

Suggested reviewers

  • evanpelle

Poem

⚓ Trade ship counts the miles it roams,
Ports tally up the harbor homes,
A little gold estimate appears,
Marked (estimate) to calm the fears,
UI and engine hum with tiny poems.

Pre-merge checks

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Implement boat unit details' accurately summarizes the main change of adding ship information display to the unit details panel.
Description check ✅ Passed The description clearly relates to the changeset, explaining that it fixes issues #2354 and #2353 by displaying ship information and using Manhattan distance for value estimation.
Linked Issues check ✅ Passed The PR addresses issue #2354 by adding support for displaying transport ship troop counts and trade ship gold values in the unit details panel through new UI rendering logic and data tracking.
Out of Scope Changes check ✅ Passed All changes are focused on implementing boat unit details: adding sourceUnit and distanceTraveled tracking to TradeShips, creating UI rendering for trade ship gold and transport ship troops, and supporting infrastructure in Game.ts, GameView.ts, and UnitImpl.ts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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
Contributor

@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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daf3fee and a7a5b5c.

📒 Files selected for processing (1)
  • src/client/graphics/layers/PlayerInfoOverlay.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-12T00:31:50.144Z
Learnt from: scottanderson
Repo: openfrontio/OpenFrontIO PR: 1752
File: src/core/game/Game.ts:750-752
Timestamp: 2025-08-12T00:31:50.144Z
Learning: In the OpenFrontIO codebase, changes to the PlayerInteraction interface (like adding canDonateGold and canDonateTroops flags) do not require corresponding updates to src/core/Schemas.ts or server serialization code.

Applied to files:

  • src/client/graphics/layers/PlayerInfoOverlay.ts
📚 Learning: 2025-05-19T06:00:38.007Z
Learnt from: scottanderson
Repo: openfrontio/OpenFrontIO PR: 784
File: src/core/game/StatsImpl.ts:125-134
Timestamp: 2025-05-19T06:00:38.007Z
Learning: In StatsImpl.ts, unused parameters in boat/stats-related methods are intentionally kept for future use and shouldn't be removed.

Applied to files:

  • src/client/graphics/layers/PlayerInfoOverlay.ts
🧬 Code graph analysis (1)
src/client/graphics/layers/PlayerInfoOverlay.ts (3)
src/core/configuration/DefaultConfig.ts (1)
  • tradeShipGold (380-387)
src/core/game/GameView.ts (5)
  • unit (658-660)
  • UnitView (44-179)
  • targetUnitId (127-129)
  • owner (109-111)
  • owner (636-638)
src/client/Utils.ts (3)
  • translateText (92-147)
  • renderNumber (19-43)
  • renderTroops (15-17)
🔇 Additional comments (2)
src/client/graphics/layers/PlayerInfoOverlay.ts (2)

410-414: Clean conditional initialization.

The type-safe initialization and conditional calculation for TradeShip units is clear and correct.


448-457: LGTM!

The TransportShip troop display correctly uses translateText() and renderTroops(), following established patterns and meeting the i18n requirements.

Copy link
Contributor

@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 a7a5b5c and 9d419ce.

📒 Files selected for processing (2)
  • resources/lang/en.json (1 hunks)
  • src/client/graphics/layers/PlayerInfoOverlay.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/client/graphics/layers/PlayerInfoOverlay.ts

@TheGiraffe3 TheGiraffe3 linked an issue Nov 1, 2025 that may be closed by this pull request
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
tests/core/executions/TradeShipExecution.test.ts (1)

71-81: Add test cases to verify distance tracking behavior.

The mock scaffolding is in place, but no tests verify that distance is tracked correctly. Consider adding test cases that check:

  • setDistanceTraveled is called with the correct distance as the ship moves
  • distanceTraveled returns the expected value
  • Distance tracking affects gold calculation when trade completes

Example test case structure:

it("should track distance traveled", () => {
  // Set initial distance
  tradeShip.setDistanceTraveled(10);
  
  // Verify distance is tracked
  expect(tradeShip.distanceTraveled()).toBe(10);
  
  // Add more assertions for movement and gold calculation
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94cf0b1 and 02c73dc.

📒 Files selected for processing (5)
  • resources/lang/en.json (1 hunks)
  • src/client/graphics/layers/PlayerInfoOverlay.ts (2 hunks)
  • src/core/game/Game.ts (2 hunks)
  • src/core/game/GameUpdates.ts (1 hunks)
  • tests/core/executions/TradeShipExecution.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/core/game/GameUpdates.ts
  • resources/lang/en.json
  • src/client/graphics/layers/PlayerInfoOverlay.ts
  • src/core/game/Game.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-22T23:48:51.113Z
Learnt from: jrouillard
Repo: openfrontio/OpenFrontIO PR: 848
File: src/core/execution/TradeShipExecution.ts:125-127
Timestamp: 2025-05-22T23:48:51.113Z
Learning: In TradeShipExecution, the path length is already checked in the computeNewPath() function. If the path is empty, it returns PathFindResultType.PathNotFound instead of PathFindResultType.Completed, making additional empty path checks unnecessary when handling the Completed case.

Applied to files:

  • tests/core/executions/TradeShipExecution.test.ts
🔇 Additional comments (1)
tests/core/executions/TradeShipExecution.test.ts (1)

71-71: Mock scaffolding looks correct.

The distance tracking mock uses a closure to maintain state between setter and getter calls. This is a clean pattern for test mocks.

Also applies to: 78-81

Copy link
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/core/executions/TradeShipExecution.test.ts (1)

120-128: Enhance the trade completion test to verify distance-based gold calculation.

The test verifies that trade completion triggers cleanup and messages, but doesn't verify the core new functionality: that gold amount is calculated correctly based on distanceTraveled().

Enhance this test:

 it("should complete trade and award gold", () => {
+  // Set initial distance
+  tradeShip.setDistanceTraveled(5);
+  
   tradeShipExecution["pathFinder"] = {
     nextTile: jest.fn(() => ({ type: 2, node: 2001 })),
   } as any;
   tradeShipExecution.tick(1);
+  
+  // Verify distance was read during gold calculation
+  expect(tradeShip.distanceTraveled).toHaveBeenCalled();
+  
+  // Verify both players received gold
+  expect(origOwner.addGold).toHaveBeenCalled();
+  expect(dstOwner.addGold).toHaveBeenCalled();
+  
   expect(tradeShip.delete).toHaveBeenCalledWith(false);
   expect(tradeShipExecution.isActive()).toBe(false);
   expect(game.displayMessage).toHaveBeenCalled();
 });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02c73dc and cf79de0.

📒 Files selected for processing (3)
  • resources/lang/en.json (1 hunks)
  • src/core/execution/TradeShipExecution.ts (3 hunks)
  • tests/core/executions/TradeShipExecution.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/core/execution/TradeShipExecution.ts
  • resources/lang/en.json

Copy link
Contributor

@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

🧹 Nitpick comments (1)
src/core/game/Game.ts (1)

499-501: Add documentation for TradeShip-specific methods.

These methods lack documentation explaining their purpose and behavior. Since they're marked "Only for trade ships", clarify:

  • What happens when called on non-TradeShip units?
  • What does distanceTraveled() return when not set (given it's optional in params)?
  • What is the source unit (Port, City, etc.)?

Apply this diff to add documentation:

  // Trade Ships
  setSafeFromPirates(): void; // Only for trade ships
  isSafeFromPirates(): boolean; // Only for trade ships
- sourceUnit(): Unit | undefined; // Only for trade ships
- distanceTraveled(): number; // Only for trade ships
- setDistanceTraveled(distance: number): void; // Only for trade ships
+ sourceUnit(): Unit | undefined; // Only for trade ships - returns the Port or City that created this TradeShip
+ distanceTraveled(): number; // Only for trade ships - returns distance traveled for trade value calculation (0 if not set)
+ setDistanceTraveled(distance: number): void; // Only for trade ships - updates distance traveled
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf79de0 and 69f361c.

📒 Files selected for processing (1)
  • src/core/game/Game.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-12T00:31:50.144Z
Learnt from: scottanderson
Repo: openfrontio/OpenFrontIO PR: 1752
File: src/core/game/Game.ts:750-752
Timestamp: 2025-08-12T00:31:50.144Z
Learning: In the OpenFrontIO codebase, changes to the PlayerInteraction interface (like adding canDonateGold and canDonateTroops flags) do not require corresponding updates to src/core/Schemas.ts or server serialization code.

Applied to files:

  • src/core/game/Game.ts
📚 Learning: 2025-05-19T06:00:38.007Z
Learnt from: scottanderson
Repo: openfrontio/OpenFrontIO PR: 784
File: src/core/game/StatsImpl.ts:125-134
Timestamp: 2025-05-19T06:00:38.007Z
Learning: In StatsImpl.ts, unused parameters in boat/stats-related methods are intentionally kept for future use and shouldn't be removed.

Applied to files:

  • src/core/game/Game.ts

Comment on lines 254 to 259
[UnitType.TradeShip]: {
targetUnit: Unit;
sourceUnit: Unit;
lastSetSafeFromPirates?: number;
distanceTraveled?: number;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix type consistency between params and interface methods.

The param types don't match the interface method signatures:

  1. Line 256: sourceUnit: Unit (required) conflicts with line 499: sourceUnit(): Unit | undefined
  2. Line 258: distanceTraveled?: number (optional) conflicts with line 500: distanceTraveled(): number (non-optional)

Either:

  • Make sourceUnit optional in params: sourceUnit?: Unit, OR make the interface return non-optional: sourceUnit(): Unit
  • Make distanceTraveled required in params: distanceTraveled: number, OR make the interface return optional: distanceTraveled(): number | undefined

Based on the context that TradeShips are created with a source Port and track distance as they travel, the recommended fix is:

  [UnitType.TradeShip]: {
    targetUnit: Unit;
-   sourceUnit: Unit;
+   sourceUnit?: Unit;
    lastSetSafeFromPirates?: number;
    distanceTraveled?: number;
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[UnitType.TradeShip]: {
targetUnit: Unit;
sourceUnit: Unit;
lastSetSafeFromPirates?: number;
distanceTraveled?: number;
};
[UnitType.TradeShip]: {
targetUnit: Unit;
sourceUnit?: Unit;
lastSetSafeFromPirates?: number;
distanceTraveled?: number;
};
🤖 Prompt for AI Agents
In src/core/game/Game.ts around lines 254 to 259, the TradeShip param types are
inconsistent with the interface methods: make sourceUnit optional and
distanceTraveled required to match the method signatures; change the param
declaration to use sourceUnit?: Unit and distanceTraveled: number so
sourceUnit() can still return Unit | undefined while distanceTraveled()
continues to return a non-optional number.

Copy link
Collaborator

@evanpelle evanpelle left a comment

Choose a reason for hiding this comment

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

I'm just thinking this is actually much more complicated than I originally thought.

  1. Since gold is determined by number of ports, src & dst players will have a different amount of gold
  2. Capturing a trade ship changes the amount of gold, eg the captor has fewer ports than the original owner.

This could confuse players, seeing the number change like that...

What if we just show it from the view of "myPlayer". So the player sees how much gold they would get if it landed on their port. This keeps all the values consistent. They only change when the player builds or loses a port

kerodkibatu and others added 2 commits November 12, 2025 00:44
…. Updated logic to retrieve the number of ports based on the current player instead of the unit owner, ensuring accurate gold calculation for trade ships.
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.

Show how many troops in transport ship Show amount of gold in tradeship when hover over

3 participants