feat(persist): salva stato su .segnapunti/state.json ad ogni azione
All'avvio il server carica lo stato dal file se esiste; ad ogni azione lo riscrive. Il riavvio del server riprende dall'ultimo punto salvato.
This commit is contained in:
@@ -14,6 +14,7 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
dev-dist
|
dev-dist
|
||||||
|
.segnapunti
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'url'
|
|||||||
import { dirname, join } from 'path'
|
import { dirname, join } from 'path'
|
||||||
import { setupWebSocketHandler } from './src/websocket-handler.js'
|
import { setupWebSocketHandler } from './src/websocket-handler.js'
|
||||||
import { printServerInfo } from './src/server-utils.js'
|
import { printServerInfo } from './src/server-utils.js'
|
||||||
|
import { loadState, saveState } from './src/persist.js'
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url)
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
const __dirname = dirname(__filename)
|
const __dirname = dirname(__filename)
|
||||||
@@ -26,7 +27,7 @@ app.get(['/controller', '/controller/*splat'], (_req, res) => {
|
|||||||
|
|
||||||
const server = createServer(app)
|
const server = createServer(app)
|
||||||
const wss = new WebSocketServer({ noServer: true })
|
const wss = new WebSocketServer({ noServer: true })
|
||||||
setupWebSocketHandler(wss)
|
setupWebSocketHandler(wss, { initialState: loadState(), onStateChange: saveState })
|
||||||
|
|
||||||
server.on('upgrade', (request, socket, head) => {
|
server.on('upgrade', (request, socket, head) => {
|
||||||
const pathname = new URL(request.url, `http://${request.headers.host}`).pathname
|
const pathname = new URL(request.url, `http://${request.headers.host}`).pathname
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'
|
||||||
|
import { join, dirname } from 'path'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
import { createInitialState } from './gameState.js'
|
||||||
|
|
||||||
|
const STATE_PATH = join(dirname(fileURLToPath(import.meta.url)), '..', '.segnapunti', 'state.json')
|
||||||
|
|
||||||
|
export function loadState() {
|
||||||
|
try {
|
||||||
|
if (existsSync(STATE_PATH)) {
|
||||||
|
return JSON.parse(readFileSync(STATE_PATH, 'utf8'))
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('[Persist] Stato non leggibile, si riparte da zero:', err.message)
|
||||||
|
}
|
||||||
|
return createInitialState()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveState(state) {
|
||||||
|
try {
|
||||||
|
mkdirSync(dirname(STATE_PATH), { recursive: true })
|
||||||
|
writeFileSync(STATE_PATH, JSON.stringify(state), 'utf8')
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[Persist] Salvataggio fallito:', err.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,9 @@ import { createInitialState, applyAction } from './gameState.js'
|
|||||||
* @param {WebSocketServer} wss - Istanza del server WebSocket.
|
* @param {WebSocketServer} wss - Istanza del server WebSocket.
|
||||||
* @returns {Object} Oggetto con metodi di gestione dello stato.
|
* @returns {Object} Oggetto con metodi di gestione dello stato.
|
||||||
*/
|
*/
|
||||||
export function setupWebSocketHandler(wss) {
|
export function setupWebSocketHandler(wss, options = {}) {
|
||||||
// Stato globale della partita.
|
// Stato globale della partita.
|
||||||
let gameState = createInitialState()
|
let gameState = options.initialState ?? createInitialState()
|
||||||
|
|
||||||
// Mappa dei ruoli associati ai client connessi.
|
// Mappa dei ruoli associati ai client connessi.
|
||||||
const clients = new Map() // ws -> { role: 'display' | 'controller' }
|
const clients = new Map() // ws -> { role: 'display' | 'controller' }
|
||||||
@@ -100,6 +100,7 @@ export function setupWebSocketHandler(wss) {
|
|||||||
|
|
||||||
// Propaga il nuovo stato a tutti i client connessi.
|
// Propaga il nuovo stato a tutti i client connessi.
|
||||||
broadcastState()
|
broadcastState()
|
||||||
|
options.onStateChange?.(gameState)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user