ui/phase-20: ship-group inspector actions

Eight ship-group operations land on the inspector behind a single
inline-form panel: split, send, load, unload, modernize, dismantle,
transfer, join fleet. Each action either appends a typed command to
the local order draft or surfaces a tooltip explaining the
disabled state. Partial-ship operations emit an implicit
breakShipGroup command before the targeted action so the engine
sees a clean (Break, Action) pair on the wire.

`pkg/calc.BlockUpgradeCost` migrates from
`game/internal/controller/ship_group_upgrade.go` so the calc
bridge can wrap a pure pkg/calc formula; the controller now
imports it. The bridge surfaces the function as
`core.blockUpgradeCost`, which the inspector calls once per ship
block to render the modernize cost preview.

`GameReport.otherRaces` is decoded from the report's player block
(non-extinct, ≠ self) and feeds the transfer-to-race picker. The
planet inspector's stationed-ship rows become clickable for own
groups so the actions panel is reachable from the standard click
flow (the renderer continues to hide on-planet groups).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-10 16:27:55 +02:00
parent f7109af55c
commit 3626998a33
36 changed files with 4033 additions and 89 deletions
+17
View File
@@ -73,6 +73,12 @@ export interface CarryingMassInput {
cargoTech: number;
}
export interface BlockUpgradeCostInput {
blockMass: number;
currentTech: number;
targetTech: number;
}
export interface Core {
/**
* signRequest returns the canonical signing input bytes for a v1
@@ -157,6 +163,17 @@ export interface Core {
* cargoCapacity.
*/
carryingMass(input: CarryingMassInput): number;
/**
* blockUpgradeCost wraps `pkg/calc/ship.go.BlockUpgradeCost`:
* production cost of moving one ship block from currentTech to
* targetTech, scaled by the block mass and a constant 10. Returns
* 0 when blockMass is zero or targetTech is not above currentTech.
* Phase 20's ship-group inspector calls this once per block
* (drive, weapons, shields, cargo) to render the modernize cost
* preview.
*/
blockUpgradeCost(input: BlockUpgradeCostInput): number;
}
export type CoreLoader = () => Promise<Core>;
+5
View File
@@ -9,6 +9,7 @@
// served from `static/core.wasm`.
import type {
BlockUpgradeCostInput,
CargoCapacityInput,
CarryingMassInput,
Core,
@@ -50,6 +51,7 @@ interface GalaxyCoreBridge {
speed(input: SpeedInput): number;
cargoCapacity(input: CargoCapacityInput): number;
carryingMass(input: CarryingMassInput): number;
blockUpgradeCost(input: BlockUpgradeCostInput): number;
}
interface BridgeRequestFields {
@@ -210,6 +212,9 @@ export function adaptBridge(bridge: GalaxyCoreBridge): Core {
carryingMass(input: CarryingMassInput): number {
return bridge.carryingMass(input);
},
blockUpgradeCost(input: BlockUpgradeCostInput): number {
return bridge.blockUpgradeCost(input);
},
};
}