Something went wrong. Try again.
A Social Deduction / Deception Game
Something went wrong. Try again.
2.9 kB · 88 lines
TypeScript
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889// The action (event) union the reducer applies. Mirrors the `town.deception.defs` lexicon that// will travel on the subscription stream (§5.2). Every action carries `serverTime`; any random// outcome is baked into the action so replay is exact (§3.7).
import type { Did, GameConfig, Facing, ActivityKind, NavGrid, Outcome, ResourceId, Role, StationSeed, Vec,} from './types.js'
/** Random outcomes resolved by the server and recorded into an `actionResolved`. */export interface ResolveRng { /** collect at a sabotaged station: did the failure dice hit this time? */ sabotageTriggered?: boolean /** fakeRepair: how many extra collections of grace before the dice can trigger (1–3) */ fakeRepairExtra?: number}
interface Base { serverTime: number}
export type Action = | (Base & { type: 'gameCreated' code: string config: GameConfig stations: StationSeed[] /** the level's navigation grid; omitted when pathfinding isn't needed (e.g. tests) */ nav?: NavGrid }) | (Base & { type: 'playerJoined' did: Did handle: string spriteRef: string | null pos: Vec }) | (Base & { type: 'playerDisconnected'; did: Did }) | (Base & { type: 'playerReconnected'; did: Did }) | (Base & { type: 'roundStarted' roles: Record<Did, Role> spawns: Record<Did, Vec> endsAt: number /** optionally finalize balancing for the actual participant count (e.g. after a grace * period the world was created with a roster-sized config); replaces config when present */ config?: GameConfig }) | (Base & { type: 'playerMoved' did: Did pos: Vec facing: Facing /** Remaining waypoints from the post-tick state, carried only so the per-viewer projector can * emit a short forward stub (truncated for others; see wire/adapt.ts). The reducer ignores it * — playerMoved stays a teleport that clears the server-side path. */ path?: Vec[] }) | (Base & { type: 'setDestination'; did: Did; target: Vec }) | (Base & { type: 'actionStarted' did: Did stationId: string slot: number kind: ActivityKind endsAt: number /** which resource this action concerns — set for collect / pretendCollect / deposit */ resourceId?: ResourceId }) | (Base & { type: 'actionCancelled'; did: Did }) | (Base & { type: 'actionResolved'; did: Did; rng?: ResolveRng }) | (Base & { type: 'itemDropped'; did: Did; debrisId: string; pos: Vec }) | (Base & { type: 'debrisInspected'; did: Did; debrisId: string }) | (Base & { type: 'debrisExpired'; debrisId: string }) | (Base & { type: 'voteCast'; voterDid: Did; targetDid: Did }) | (Base & { type: 'voteEnded'; kickedDid: Did | null }) | (Base & { type: 'roundEnded'; outcome: Outcome }) | (Base & { type: 'tick' })
export type ActionType = Action['type']