Server-side simulation runtime: SimulationRunner owns one real WASM engine and its 20 Hz tick loop, applying commands (loadScenario, play/pause/reset, actuators, environment) and producing snapshots. attachRunnerToPort bridges it to a worker_thread port; the thread entrypoint lives in simulation-worker.entry.ts. Adds vitest to apps/api. Task: task_03. Tests: 12 passing (real engine + MessageChannel bridge), coverage 98.6% stmts / 89.5% branches. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
29 lines
975 B
TypeScript
29 lines
975 B
TypeScript
import type { SimulationStateDTO, VesselConfigDTO, ScenarioDraftVesselDTO } from '@ymir/types'
|
|
|
|
/**
|
|
* Internal message protocol between the main thread (SimulationManager) and a
|
|
* SimulationWorker running in a worker_thread. Distinct from the network
|
|
* ClientMessage/ServerMessage: these carry no sim_id (the worker IS one sim).
|
|
*/
|
|
export type WorkerCommand =
|
|
| { type: 'loadScenario'; vessels: ScenarioDraftVesselDTO[] }
|
|
| { type: 'play'; dt?: number }
|
|
| { type: 'pause' }
|
|
| { type: 'reset' }
|
|
| {
|
|
type: 'setActuator'
|
|
vesselId: number
|
|
deviceType: 'rudder' | 'thruster'
|
|
deviceId: number
|
|
value: number
|
|
value2?: number
|
|
}
|
|
| { type: 'loadEnvironment'; json: string }
|
|
|
|
export type WorkerEvent =
|
|
| { type: 'ready' }
|
|
| { type: 'state'; payload: SimulationStateDTO }
|
|
| { type: 'status'; status: 'running' | 'paused' | 'ended' }
|
|
| { type: 'vesselConfig'; payload: VesselConfigDTO }
|
|
| { type: 'error'; message: string }
|