import type { GameAction } from './types' import { stateManager } from './StateManager' /** All state mutations go through an adapter. * Swap LocalAdapter for WebSocketAdapter to enable multiplayer. */ export interface NetworkAdapter { send(action: GameAction): void onAction?: (action: GameAction) => void } const ACTION_LOG_SIZE = 15 /** Singleplayer: apply actions immediately and synchronously */ export class LocalAdapter implements NetworkAdapter { onAction?: (action: GameAction) => void /** Ring-buffer of the last ACTION_LOG_SIZE dispatched action summaries. */ private _actionLog: string[] = [] send(action: GameAction): void { stateManager.apply(action) this._recordAction(action) this.onAction?.(action) } /** Returns a copy of the recent action log (oldest first). */ getActionLog(): readonly string[] { return this._actionLog } /** * Appends a short summary of the action to the ring-buffer. * @param action - The dispatched game action */ private _recordAction(action: GameAction): void { let entry = action.type if ('tileX' in action && 'tileY' in action) entry += ` (${(action as any).tileX},${(action as any).tileY})` else if ('villagerId' in action) entry += ` v=…${(action as any).villagerId.slice(-4)}` else if ('resourceId' in action) entry += ` r=…${(action as any).resourceId.slice(-4)}` else if ('cropId' in action) entry += ` c=…${(action as any).cropId.slice(-4)}` else if ('seedlingId' in action) entry += ` s=…${(action as any).seedlingId.slice(-4)}` if (this._actionLog.length >= ACTION_LOG_SIZE) this._actionLog.shift() this._actionLog.push(entry) } }