Skip to content

Commit 5bc55f3

Browse files
committed
Split shared/types.ts into domain, protocol, and scenario modules
Phase 3 of the maintenance plan. The monolithic types.ts (365 LOC) is replaced by src/shared/types/ with focused modules: - domain.ts: game entities, actions, map, combat, movement - protocol.ts: C2S/S2C wire messages - scenario.ts: scenario configuration types - index.ts: barrel re-export preserving all existing import paths
1 parent 6ab6596 commit 5bc55f3

File tree

5 files changed

+120
-94
lines changed

5 files changed

+120
-94
lines changed

docs/BACKLOG.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ These are acceptable for the current standalone/experimental
6262
scope. Address lifecycle gaps before wiring into core UI
6363
state (PlanningState, HUD).
6464

65-
### Phase 3. Shared model boundaries
65+
### ~~Phase 3. Shared model boundaries~~ *(done)*
6666

67-
- Split `src/shared/types.ts` into separate domain, protocol,
68-
and scenario type modules.
69-
- Reduce the number of unrelated changes that currently collide
70-
in a single cross-layer file.
67+
Split `src/shared/types.ts` into `src/shared/types/` directory:
68+
`domain.ts` (entities, actions, map, combat, movement),
69+
`protocol.ts` (C2S/S2C), `scenario.ts` (ScenarioDefinition,
70+
ScenarioPlayer). Barrel `index.ts` preserves all existing
71+
import paths.
7172

7273
### Phase 4. Rules consolidation
7374

@@ -90,7 +91,7 @@ state (PlanningState, HUD).
9091
1. ~~Reliability fixes.~~
9192
2. ~~`main.ts` coordinator extraction.~~
9293
3. ~~`ui.ts` view extraction.~~
93-
4. Shared type/module split.
94+
4. ~~Shared type/module split.~~
9495
5. Rules consolidation.
9596
6. Optional stronger state-model refactors.
9697

Lines changed: 14 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { GameEvent } from './events';
2-
import type { HexCoord, HexVec } from './hex';
1+
import type { HexCoord, HexVec } from '../hex';
32

43
// --- Game state ---
54

@@ -234,7 +233,7 @@ export interface MovementEvent {
234233
capturedBy?: string;
235234
}
236235

237-
// --- Network messages ---
236+
// --- Actions ---
238237

239238
export interface OrbitalBaseEmplacement {
240239
shipId: string;
@@ -244,6 +243,15 @@ export interface FleetPurchase {
244243
shipType: string;
245244
}
246245

246+
export interface TransferOrder {
247+
sourceShipId: string;
248+
targetShipId: string;
249+
transferType: 'fuel' | 'cargo';
250+
amount: number;
251+
}
252+
253+
// --- Scenario rules (embedded in GameState) ---
254+
247255
export interface Reinforcement {
248256
turn: number;
249257
playerId: number;
@@ -270,95 +278,13 @@ export interface ScenarioRules {
270278
fleetConversion?: FleetConversion;
271279
}
272280

273-
export interface TransferOrder {
274-
sourceShipId: string;
275-
targetShipId: string;
276-
transferType: 'fuel' | 'cargo';
277-
amount: number;
278-
}
279-
280-
export type C2S =
281-
| { type: 'fleetReady'; purchases: FleetPurchase[] }
282-
| { type: 'astrogation'; orders: AstrogationOrder[] }
283-
| { type: 'surrender'; shipIds: string[] }
284-
| { type: 'ordnance'; launches: OrdnanceLaunch[] }
285-
| {
286-
type: 'emplaceBase';
287-
emplacements: OrbitalBaseEmplacement[];
288-
}
289-
| { type: 'skipOrdnance' }
290-
| { type: 'beginCombat' }
291-
| { type: 'combat'; attacks: CombatAttack[] }
292-
| { type: 'skipCombat' }
293-
| { type: 'logistics'; transfers: TransferOrder[] }
294-
| { type: 'skipLogistics' }
295-
| { type: 'rematch' }
296-
| { type: 'chat'; text: string }
297-
| { type: 'ping'; t: number };
298-
299-
export type S2C =
300-
| {
301-
type: 'welcome';
302-
playerId: number;
303-
code: string;
304-
playerToken: string;
305-
}
306-
| { type: 'matchFound' }
307-
| {
308-
type: 'gameStart';
309-
state: GameState;
310-
eventLog?: GameEvent[];
311-
}
312-
| {
313-
type: 'movementResult';
314-
movements: ShipMovement[];
315-
ordnanceMovements: OrdnanceMovement[];
316-
events: MovementEvent[];
317-
state: GameState;
318-
}
319-
| {
320-
type: 'combatResult';
321-
results: CombatResult[];
322-
state: GameState;
323-
}
324-
| { type: 'stateUpdate'; state: GameState }
325-
| { type: 'gameOver'; winner: number; reason: string }
326-
| { type: 'rematchPending' }
327-
| { type: 'opponentDisconnected' }
328-
| {
329-
type: 'chat';
330-
playerId: number;
331-
text: string;
332-
}
333-
| { type: 'error'; message: string }
334-
| { type: 'pong'; t: number };
335-
336-
// --- Scenario ---
337-
281+
// ScenarioShip is needed here because Reinforcement
282+
// references it. The full scenario config types
283+
// (ScenarioDefinition, ScenarioPlayer) live in scenario.ts.
338284
export interface ScenarioShip {
339285
type: string;
340286
position: HexCoord;
341287
velocity: HexVec;
342288
startLanded?: boolean;
343289
startInOrbit?: boolean;
344290
}
345-
346-
export interface ScenarioPlayer {
347-
ships: ScenarioShip[];
348-
targetBody: string;
349-
homeBody: string;
350-
bases?: HexCoord[];
351-
escapeWins: boolean;
352-
hiddenIdentity?: boolean;
353-
}
354-
355-
export interface ScenarioDefinition {
356-
name: string;
357-
description: string;
358-
tags?: string[];
359-
players: ScenarioPlayer[];
360-
rules?: ScenarioRules;
361-
startingPlayer?: 0 | 1;
362-
startingCredits?: number | [number, number];
363-
availableShipTypes?: string[];
364-
}

src/shared/types/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './domain';
2+
export * from './protocol';
3+
export * from './scenario';

src/shared/types/protocol.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import type { GameEvent } from '../events';
2+
import type {
3+
AstrogationOrder,
4+
CombatAttack,
5+
CombatResult,
6+
FleetPurchase,
7+
GameState,
8+
MovementEvent,
9+
OrbitalBaseEmplacement,
10+
OrdnanceLaunch,
11+
OrdnanceMovement,
12+
ShipMovement,
13+
TransferOrder,
14+
} from './domain';
15+
16+
// --- Network messages ---
17+
18+
export type C2S =
19+
| { type: 'fleetReady'; purchases: FleetPurchase[] }
20+
| { type: 'astrogation'; orders: AstrogationOrder[] }
21+
| { type: 'surrender'; shipIds: string[] }
22+
| { type: 'ordnance'; launches: OrdnanceLaunch[] }
23+
| {
24+
type: 'emplaceBase';
25+
emplacements: OrbitalBaseEmplacement[];
26+
}
27+
| { type: 'skipOrdnance' }
28+
| { type: 'beginCombat' }
29+
| { type: 'combat'; attacks: CombatAttack[] }
30+
| { type: 'skipCombat' }
31+
| { type: 'logistics'; transfers: TransferOrder[] }
32+
| { type: 'skipLogistics' }
33+
| { type: 'rematch' }
34+
| { type: 'chat'; text: string }
35+
| { type: 'ping'; t: number };
36+
37+
export type S2C =
38+
| {
39+
type: 'welcome';
40+
playerId: number;
41+
code: string;
42+
playerToken: string;
43+
}
44+
| { type: 'matchFound' }
45+
| {
46+
type: 'gameStart';
47+
state: GameState;
48+
eventLog?: GameEvent[];
49+
}
50+
| {
51+
type: 'movementResult';
52+
movements: ShipMovement[];
53+
ordnanceMovements: OrdnanceMovement[];
54+
events: MovementEvent[];
55+
state: GameState;
56+
}
57+
| {
58+
type: 'combatResult';
59+
results: CombatResult[];
60+
state: GameState;
61+
}
62+
| { type: 'stateUpdate'; state: GameState }
63+
| { type: 'gameOver'; winner: number; reason: string }
64+
| { type: 'rematchPending' }
65+
| { type: 'opponentDisconnected' }
66+
| {
67+
type: 'chat';
68+
playerId: number;
69+
text: string;
70+
}
71+
| { type: 'error'; message: string }
72+
| { type: 'pong'; t: number };

src/shared/types/scenario.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type { HexCoord } from '../hex';
2+
import type { ScenarioRules, ScenarioShip } from './domain';
3+
4+
// --- Scenario configuration ---
5+
6+
export interface ScenarioPlayer {
7+
ships: ScenarioShip[];
8+
targetBody: string;
9+
homeBody: string;
10+
bases?: HexCoord[];
11+
escapeWins: boolean;
12+
hiddenIdentity?: boolean;
13+
}
14+
15+
export interface ScenarioDefinition {
16+
name: string;
17+
description: string;
18+
tags?: string[];
19+
players: ScenarioPlayer[];
20+
rules?: ScenarioRules;
21+
startingPlayer?: 0 | 1;
22+
startingCredits?: number | [number, number];
23+
availableShipTypes?: string[];
24+
}

0 commit comments

Comments
 (0)