diff --git a/packages/mnswpr/core/session/session.d.ts b/packages/mnswpr/core/session/session.d.ts index 8dff90f..1a62f76 100644 --- a/packages/mnswpr/core/session/session.d.ts +++ b/packages/mnswpr/core/session/session.d.ts @@ -6,6 +6,7 @@ * Future home: @cozy-games/game-session. * * @typedef {{ init: Function, apply: Function, status: Function, project: Function, serialize?: Function, deserialize?: Function, toMoveEvent?: Function }} Rules + * @typedef {import('../minesweeper/rules.js').MoveEvent} MoveEvent */ export class GameSession { /** @@ -56,8 +57,8 @@ export class GameSession { }>; _t0: number; _tEnd: number; - /** @type {Set<(event: object) => void>} */ - _moveHandlers: Set<(event: object) => void>; + /** @type {Set<(event: MoveEvent) => void>} */ + _moveHandlers: Set<(event: MoveEvent) => void>; _seq: number; /** * Subscribe to typed move-events — one per effective move (reveal / flag / @@ -65,10 +66,10 @@ export class GameSession { * unsubscribe function. Pure in-process pub/sub: no DOM, no rendering. Requires * the rules to implement `toMoveEvent`. * - * @param {(event: object) => void} handler + * @param {(event: MoveEvent) => void} handler * @returns {() => void} unsubscribe */ - onMove(handler: (event: object) => void): () => void; + onMove(handler: (event: MoveEvent) => void): () => void; /** * Apply a move: stamp it, fold it through the rules, and return the projected * view + events + authoritative elapsed time. @@ -79,8 +80,8 @@ export class GameSession { view: any; time: number; }; - /** @param {object} event */ - _emitMove(event: object): void; + /** @param {MoveEvent} event */ + _emitMove(event: MoveEvent): void; status(): any; view(): any; log(): { @@ -136,3 +137,11 @@ export type Rules = { deserialize?: Function; toMoveEvent?: Function; }; +/** + * Layer 1 — owns lifecycle, the (injected) clock, and the move log; delegates all + * game meaning to an injected `rules` object. This is where timing authority + * lives: on the client `clock` is `Date.now` (cosmetic); on a server it is the + * server's clock (authoritative). The session never calls a wall clock itself. + * Future home: + */ +export type MoveEvent = import("../minesweeper/rules.js").MoveEvent; diff --git a/packages/mnswpr/core/session/session.js b/packages/mnswpr/core/session/session.js index c4ee5f0..13c7b44 100644 --- a/packages/mnswpr/core/session/session.js +++ b/packages/mnswpr/core/session/session.js @@ -8,6 +8,7 @@ * Future home: @cozy-games/game-session. * * @typedef {{ init: Function, apply: Function, status: Function, project: Function, serialize?: Function, deserialize?: Function, toMoveEvent?: Function }} Rules + * @typedef {import('../minesweeper/rules.js').MoveEvent} MoveEvent */ export class GameSession { /** @@ -30,7 +31,7 @@ export class GameSession { // Move-event emission: subscribers + a monotonic sequence counter (last seq // assigned; 0 = none yet). Seq is part of the snapshot so it keeps rising // across a resume rather than restarting. - /** @type {Set<(event: object) => void>} */ + /** @type {Set<(event: MoveEvent) => void>} */ this._moveHandlers = new Set() this._seq = 0 } @@ -41,7 +42,7 @@ export class GameSession { * unsubscribe function. Pure in-process pub/sub: no DOM, no rendering. Requires * the rules to implement `toMoveEvent`. * - * @param {(event: object) => void} handler + * @param {(event: MoveEvent) => void} handler * @returns {() => void} unsubscribe */ onMove(handler) { @@ -75,7 +76,7 @@ export class GameSession { return { events, view: this.rules.project(state), time: this.elapsed() } } - /** @param {object} event */ + /** @param {MoveEvent} event */ _emitMove(event) { for (const handler of this._moveHandlers) handler(event) } diff --git a/packages/mnswpr/package.json b/packages/mnswpr/package.json index ae3fb34..5900ff8 100644 --- a/packages/mnswpr/package.json +++ b/packages/mnswpr/package.json @@ -1,6 +1,6 @@ { "name": "@cozy-games/mnswpr", - "version": "0.5.3", + "version": "0.5.4", "description": "Classic Minesweeper browser game", "author": "Ayo", "type": "module",