-
Notifications
You must be signed in to change notification settings - Fork 707
Add warship patrol area indicator #2543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add warship patrol area indicator #2543
Conversation
- Show patrol area circle when warship is selected (solid line) - Show preview circle at cursor when selecting new patrol location (dashed line) - ESC key deselects warship - Expose patrolTile to client via UnitUpdate for visualization
WalkthroughAdds a new WarshipRadiusLayer that renders selected and placement patrol indicators, wires it into the renderer layer stack, subscribes selection/mouse events, and propagates a new optional Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
There was a problem hiding this 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
📒 Files selected for processing (6)
src/client/graphics/GameRenderer.ts(3 hunks)src/client/graphics/layers/UnitLayer.ts(3 hunks)src/client/graphics/layers/WarshipRadiusLayer.ts(1 hunks)src/core/game/GameUpdates.ts(1 hunks)src/core/game/GameView.ts(1 hunks)src/core/game/UnitImpl.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-26T20:49:29.110Z
Learnt from: scamiv
Repo: openfrontio/OpenFrontIO PR: 2519
File: src/core/game/GameView.ts:516-525
Timestamp: 2025-11-26T20:49:29.110Z
Learning: In GameView.ts, when usesSharedTileState is true (SAB mode), packedTileUpdates contains unpacked tile references as BigInt(tileRef) only, because all tile state lives in the shared Uint16Array. In non-SAB mode, packedTileUpdates contains packed TileUpdate bigints in the format (tileRef << 16n | state), which must be decoded via updateTile(tu). Therefore, Number(tu) is correct in SAB mode and shifting right by 16 bits would be wrong.
Applied to files:
src/core/game/GameView.tssrc/core/game/UnitImpl.tssrc/core/game/GameUpdates.ts
📚 Learning: 2025-10-18T11:00:57.142Z
Learnt from: NewYearNewPhil
Repo: openfrontio/OpenFrontIO PR: 2230
File: src/client/graphics/GameRenderer.ts:269-277
Timestamp: 2025-10-18T11:00:57.142Z
Learning: In src/client/graphics/GameRenderer.ts, the GameRecapCapture implementation does not use setCaptureRenderEnabled on layers. Instead, it uses RecapCaptureSurface.capture() to render capture layers (TerrainLayer, TerritoryLayer, RailroadLayer, StructureIconsLayer, UnitLayer) directly to an off-screen canvas without requiring layer-level capture mode methods.
Applied to files:
src/client/graphics/layers/WarshipRadiusLayer.tssrc/client/graphics/GameRenderer.ts
🧬 Code graph analysis (5)
src/core/game/GameView.ts (1)
src/core/game/GameMap.ts (1)
TileRef(3-3)
src/client/graphics/layers/UnitLayer.ts (1)
src/client/InputHandler.ts (2)
CloseViewEvent(78-78)UnitSelectionEvent(31-36)
src/client/graphics/layers/WarshipRadiusLayer.ts (6)
src/core/game/GameView.ts (5)
UnitView(44-182)GameView(462-788)patrolTile(133-135)x(685-687)y(688-690)src/server/GameManager.ts (1)
game(24-26)src/client/graphics/TransformHandler.ts (1)
TransformHandler(15-333)src/client/graphics/UIState.ts (1)
UIState(3-6)src/client/InputHandler.ts (2)
UnitSelectionEvent(31-36)MouseMoveEvent(45-50)src/core/game/UnitImpl.ts (1)
patrolTile(97-99)
src/core/game/GameUpdates.ts (1)
src/core/game/GameMap.ts (1)
TileRef(3-3)
src/client/graphics/GameRenderer.ts (1)
src/client/graphics/layers/WarshipRadiusLayer.ts (1)
WarshipRadiusLayer(15-189)
🔇 Additional comments (8)
src/client/graphics/GameRenderer.ts (1)
214-219: LGTM! Consistent with existing layer patterns.The
WarshipRadiusLayeris instantiated and inserted in the correct position, following the same pattern asSAMRadiusLayer. The layer ordering (radius layers before unit layer) makes sense for visual layering.Also applies to: 252-252
src/core/game/GameView.ts (1)
133-135: LGTM! Clean accessor following existing patterns.The
patrolTile()accessor matches the style oftargetTile()directly above it.src/core/game/UnitImpl.ts (1)
143-143: LGTM! Proper serialization of patrol tile.The
patrolTilefield is correctly added to the update payload, matching the pattern of other optional fields liketargetTile.src/core/game/GameUpdates.ts (1)
137-137: LGTM! Clear interface extension with good documentation.The
patrolTilefield follows the existing pattern of optional unit-specific fields with a helpful comment.src/client/graphics/layers/UnitLayer.ts (1)
194-201: LGTM! Simple and effective ESC deselection handler.The
onCloseViewmethod cleanly handles ESC key deselection by emitting aUnitSelectionEvent. The existingonUnitSelectionChangehandler will update the state correctly.src/client/graphics/layers/WarshipRadiusLayer.ts (3)
1-57: Good layer setup following existing patterns.Clean imports with proper
typeannotations. Canvas setup and event subscriptions follow the established layer patterns (similar toSAMRadiusLayer).
59-94: Tick and animation logic is well-structured.The animation timing, ghost mode detection, and destroyed warship cleanup are all handled correctly. The modulo guard on
dashOffsetprevents numeric overflow over long sessions.
133-188: Clean drawing implementation.The
redraw(),drawCurrentPatrol(), anddrawPreviewPatrol()methods are straightforward and follow canvas best practices with propersave()/restore()pairs.
|
Good idea. I thought warships patrol square areas instead of circle ones though? |
Warships patrol in a square area (random x/y within ±range/2), not a circular one. Updated the visual indicator to match the actual behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/client/graphics/layers/WarshipRadiusLayer.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-10-18T11:00:57.142Z
Learnt from: NewYearNewPhil
Repo: openfrontio/OpenFrontIO PR: 2230
File: src/client/graphics/GameRenderer.ts:269-277
Timestamp: 2025-10-18T11:00:57.142Z
Learning: In src/client/graphics/GameRenderer.ts, the GameRecapCapture implementation does not use setCaptureRenderEnabled on layers. Instead, it uses RecapCaptureSurface.capture() to render capture layers (TerrainLayer, TerritoryLayer, RailroadLayer, StructureIconsLayer, UnitLayer) directly to an off-screen canvas without requiring layer-level capture mode methods.
Applied to files:
src/client/graphics/layers/WarshipRadiusLayer.ts
📚 Learning: 2025-06-16T03:03:59.778Z
Learnt from: VariableVince
Repo: openfrontio/OpenFrontIO PR: 1192
File: src/client/graphics/layers/RadialMenuElements.ts:312-314
Timestamp: 2025-06-16T03:03:59.778Z
Learning: In RadialMenuElements.ts, when fixing undefined params errors in subMenu functions, use explicit checks like `if (params === undefined || params.selected === null)` rather than optional chaining, as it makes the intent clearer and matches the specific error scenarios where params can be undefined during spawn phase operations.
Applied to files:
src/client/graphics/layers/WarshipRadiusLayer.ts
📚 Learning: 2025-10-27T09:47:26.395Z
Learnt from: sambokai
Repo: openfrontio/OpenFrontIO PR: 2225
File: src/core/execution/FakeHumanExecution.ts:770-795
Timestamp: 2025-10-27T09:47:26.395Z
Learning: In src/core/execution/FakeHumanExecution.ts, the selectSteamrollStopTarget() method intentionally allows MIRV targeting when secondHighest city count is 0 (e.g., nuclear endgame scenarios where structures are destroyed). This is valid game design—"if you can afford it, you're good to go"—and should not be flagged as requiring a guard condition.
Applied to files:
src/client/graphics/layers/WarshipRadiusLayer.ts
📚 Learning: 2025-06-22T21:51:14.990Z
Learnt from: devalnor
Repo: openfrontio/OpenFrontIO PR: 1248
File: src/client/graphics/layers/TerritoryInfoLayer.ts:20-20
Timestamp: 2025-06-22T21:51:14.990Z
Learning: In TerritoryInfoLayer.ts, the highlightedTerritory field uses both null and undefined intentionally: undefined represents initial state or inactive layer (Ctrl released), while null represents active layer with no territory being highlighted at cursor position. This distinction is important for proper state change detection.
Applied to files:
src/client/graphics/layers/WarshipRadiusLayer.ts
🧬 Code graph analysis (1)
src/client/graphics/layers/WarshipRadiusLayer.ts (1)
src/client/graphics/UIState.ts (1)
UIState(3-6)
🔇 Additional comments (8)
src/client/graphics/layers/WarshipRadiusLayer.ts (8)
1-7: LGTM!Imports are clean and necessary for the layer implementation.
9-31: LGTM!Field declarations are well-organized with clear state tracking, animation, and cursor management. The note about matching SAMRadiusLayer's animation speed is helpful for consistency.
33-47: LGTM!Constructor properly initializes canvas and context with good error handling.
49-57: LGTM!Standard layer initialization with proper event subscriptions and initial redraw.
96-104: LGTM!Standard layer rendering implementation with correct centered coordinate offset.
117-131: LGTM!Mouse handling logic is correct with proper early returns and coordinate conversion.
133-150: LGTM!Redraw logic correctly handles both solid patrol area and dashed preview with proper conditional rendering and defensive checks.
59-94: Verify thatisActive()method exists on UnitView.The tick method calls
this.selectedWarship.isActive()on line 71. Ensure this method exists on the UnitView interface/class and returns a boolean indicating whether the unit is still active.
Description:
Screencast_20251130_101359.webm
Please complete the following:
Please put your Discord username so you can be contacted if a bug or regression is found:
bcnelson