2026-03-20 08:11:31 +00:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-24 08:08:05 +00:00
|
|
|
const ACTION_LOG_SIZE = 15
|
|
|
|
|
|
2026-03-20 08:11:31 +00:00
|
|
|
/** Singleplayer: apply actions immediately and synchronously */
|
|
|
|
|
export class LocalAdapter implements NetworkAdapter {
|
|
|
|
|
onAction?: (action: GameAction) => void
|
|
|
|
|
|
2026-03-24 08:08:05 +00:00
|
|
|
/** Ring-buffer of the last ACTION_LOG_SIZE dispatched action summaries. */
|
|
|
|
|
private _actionLog: string[] = []
|
|
|
|
|
|
2026-03-20 08:11:31 +00:00
|
|
|
send(action: GameAction): void {
|
|
|
|
|
stateManager.apply(action)
|
2026-03-24 08:08:05 +00:00
|
|
|
this._recordAction(action)
|
2026-03-20 08:11:31 +00:00
|
|
|
this.onAction?.(action)
|
|
|
|
|
}
|
2026-03-24 08:08:05 +00:00
|
|
|
|
|
|
|
|
/** 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)
|
|
|
|
|
}
|
2026-03-20 08:11:31 +00:00
|
|
|
}
|