ui/phase-17: ship-class CRUD without calc

Phase 17 lights up the ship-class table and designer active views,
extends the order-draft pipeline with createShipClass and
removeShipClass commands, and projects pending Save/Delete actions
through applyOrderOverlay so the table reflects the player's
intent before auto-sync lands. The plan is corrected in the same
patch: per game/rules.txt, ship classes are designed once and
cannot be edited — the engine has no Update command, so the UI
exposes only Create + Delete.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-09 21:44:21 +02:00
parent 8a236bef14
commit 785c3483f8
23 changed files with 2456 additions and 99 deletions
+43 -1
View File
@@ -16,6 +16,8 @@ import {
CommandPlanetRename,
CommandPlanetRouteRemove,
CommandPlanetRouteSet,
CommandShipClassCreate,
CommandShipClassRemove,
PlanetProduction,
PlanetRouteLoadType,
UserGamesOrder,
@@ -65,11 +67,28 @@ export interface RemoveCargoRouteResultFixture
loadType: "COL" | "CAP" | "MAT" | "EMP";
}
export interface CreateShipClassResultFixture extends CommandResultFixtureBase {
kind: "createShipClass";
name: string;
drive: number;
armament: number;
weapons: number;
shields: number;
cargo: number;
}
export interface RemoveShipClassResultFixture extends CommandResultFixtureBase {
kind: "removeShipClass";
name: string;
}
export type CommandResultFixture =
| PlanetRenameResultFixture
| SetProductionTypeResultFixture
| SetCargoRouteResultFixture
| RemoveCargoRouteResultFixture;
| RemoveCargoRouteResultFixture
| CreateShipClassResultFixture
| RemoveShipClassResultFixture;
export function buildOrderResponsePayload(
gameId: string,
@@ -173,6 +192,29 @@ function encodeItem(builder: Builder, c: CommandResultFixture): number {
payloadType = CommandPayload.CommandPlanetRouteRemove;
break;
}
case "createShipClass": {
const nameOffset = builder.createString(c.name);
inner = CommandShipClassCreate.createCommandShipClassCreate(
builder,
nameOffset,
c.drive,
BigInt(c.armament),
c.weapons,
c.shields,
c.cargo,
);
payloadType = CommandPayload.CommandShipClassCreate;
break;
}
case "removeShipClass": {
const nameOffset = builder.createString(c.name);
inner = CommandShipClassRemove.createCommandShipClassRemove(
builder,
nameOffset,
);
payloadType = CommandPayload.CommandShipClassRemove;
break;
}
}
CommandItem.startCommandItem(builder);
CommandItem.addCmdId(builder, cmdIdOffset);
@@ -53,6 +53,11 @@ export interface OtherPlanetFixture extends InhabitedFixture {
export interface ShipClassFixture {
name: string;
drive?: number;
armament?: number;
weapons?: number;
shields?: number;
cargo?: number;
}
export interface PlayerFixture {
@@ -165,6 +170,11 @@ export function buildReportPayload(fixture: ReportFixture): Uint8Array {
const name = builder.createString(cls.name);
ShipClass.startShipClass(builder);
ShipClass.addName(builder, name);
ShipClass.addDrive(builder, cls.drive ?? 0);
ShipClass.addArmament(builder, BigInt(cls.armament ?? 0));
ShipClass.addWeapons(builder, cls.weapons ?? 0);
ShipClass.addShields(builder, cls.shields ?? 0);
ShipClass.addCargo(builder, cls.cargo ?? 0);
return ShipClass.endShipClass(builder);
});