// Salvataggio nel browser: ogni accesso può fallire (navigazione privata, spazio pieno), e allora si gioca senza. const KEY = 'leggenda-regolo-save'; export function readSave(storage) { try { const raw = storage.getItem(KEY); return raw ? JSON.parse(raw) : null; } catch { return null; } } export function writeSave(storage, data) { try { storage.setItem(KEY, JSON.stringify(data)); return true; } catch { return false; } } export function clearSave(storage) { try { storage.removeItem(KEY); return true; } catch { return false; } } // File di salvataggio da portare su un altro dispositivo: la partita dentro una busta che dice di che gioco è. const FILE_GAME = 'la-leggenda-del-regolo'; export function saveFile(data, date = new Date()) { return JSON.stringify({ game: FILE_GAME, version: FILE_VERSION, saved: date.toISOString(), state: data }, null, 1); } export function saveFileName(date = new Date()) { const p = n => String(n).padStart(2, '0'); return `regolo-${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())}-${p(date.getHours())}${p(date.getMinutes())}.json`; } const FILE_VERSION = 1; // La partita contenuta nel file: { state } se è un salvataggio di questo gioco in una versione che si sa leggere, // altrimenti { error: 'not-save' | 'newer' }. Che la partita torni con la storia lo controlla checkSave (game.js). export function readSaveFile(text) { let f; try { f = JSON.parse(text); } catch { return { error: 'not-save' }; } if (!f || f.game !== FILE_GAME || !f.state || typeof f.state !== 'object' || Array.isArray(f.state)) return { error: 'not-save' }; if (!Number.isInteger(f.version) || f.version < 1) return { error: 'not-save' }; if (f.version > FILE_VERSION) return { error: 'newer' }; return { state: f.state }; } // Volume della musica, volume delle voci e muto: si ricordano anche senza una partita salvata. const AUDIO_KEY = 'leggenda-regolo-audio'; export function readAudio(storage) { try { const a = JSON.parse(storage.getItem(AUDIO_KEY)); if (!a || typeof a.volume !== 'number') return null; return { volume: a.volume, muted: !!a.muted, ...(typeof a.voices === 'number' && { voices: a.voices }), ...(typeof a.effects === 'number' && Number.isFinite(a.effects) && { effects: Math.max(0, Math.min(1, a.effects)) }) }; } catch { return null; } } export function writeAudio(storage, settings) { try { storage.setItem(AUDIO_KEY, JSON.stringify(settings)); return true; } catch { return false; } }