fuzzyworld

nuts / goo / files / src / persistence.ts

Branch goo · default branch · all branches

persistence.ts

Blame: the commit that last changed each line · file · history

f1262fd9 2026-04-12 Pavel Safronov1const DATA_VERSION = 2
2
3const KEYS = {
4 settings: 'nuts-settings-v2',
5 snapshot: 'nuts-snapshot-v2',
6} as const
7
8// ── Settings ───────────────────────────────────────────────────────────────
9
10export interface PersistedSettings {
11 v: number
12 nutRadius: number
937f9abc 2026-04-12 Pavel Safronov13 gravityMode?: string
14 vibrateEnabled?: boolean
98ba5504 2026-04-13 Pavel Safronov15 vibrateItems?: boolean
16 vibrateEdges?: boolean
74d506c6 2026-04-12 Pavel Safronov17 kind?: string
98ba5504 2026-04-13 Pavel Safronov18 randomPool?: string[]
f1262fd9 2026-04-12 Pavel Safronov19}
20
21export function loadSettings(): PersistedSettings | null {
22 try {
23 const raw = localStorage.getItem(KEYS.settings)
24 if (!raw) return null
25 const parsed = JSON.parse(raw) as PersistedSettings
26 if (parsed.v !== DATA_VERSION) return null
27 return parsed
28 } catch {
29 return null
30 }
31}
32
33export function saveSettings(s: Omit<PersistedSettings, 'v'>): void {
34 try {
35 localStorage.setItem(KEYS.settings, JSON.stringify({ v: DATA_VERSION, ...s }))
36 } catch { /* storage full – ignore */ }
37}
38
39// ── Nut snapshot ───────────────────────────────────────────────────────────
40
41export interface NutSnapshot {
42 x: number // normalised 0..1 (relative to screen size)
43 y: number
44 angle: number
45 radius: number // absolute px
46 colorIndex: number
cfe80f49 2026-04-13 Pavel Safronov47 kind: 'nut' | 'gem' | 'balloon' | 'metalnut' | 'rock' | 'stressball'
f1262fd9 2026-04-12 Pavel Safronov48 gemVariant: number
49}
50
51export interface SnapshotRecord {
52 v: number
53 screenW: number
54 screenH: number
55 nuts: NutSnapshot[]
56}
57
58export function saveSnapshot(
cfe80f49 2026-04-13 Pavel Safronov59 nuts: Array<{ body: { position: { x: number; y: number }; angle: number }; radius: number; colorIndex: number; kind: 'nut' | 'gem' | 'balloon' | 'metalnut' | 'rock' | 'stressball'; gemVariant: number }>,
f1262fd9 2026-04-12 Pavel Safronov60 screenW: number,
61 screenH: number,
62): void {
63 try {
64 const record: SnapshotRecord = {
65 v: DATA_VERSION,
66 screenW,
67 screenH,
68 nuts: nuts.map(n => ({
69 x: n.body.position.x / screenW,
70 y: n.body.position.y / screenH,
71 angle: n.body.angle,
72 radius: n.radius,
73 colorIndex: n.colorIndex,
74 kind: n.kind,
75 gemVariant: n.gemVariant,
76 })),
77 }
78 localStorage.setItem(KEYS.snapshot, JSON.stringify(record))
79 } catch { /* storage full – ignore */ }
80}
81
82export function loadSnapshot(): SnapshotRecord | null {
83 try {
84 const raw = localStorage.getItem(KEYS.snapshot)
85 if (!raw) return null
86 const record = JSON.parse(raw) as SnapshotRecord
87 if (record.v !== DATA_VERSION) return null
88 return record
89 } catch {
90 return null
91 }
92}
93
94export function clearSnapshot(): void {
95 localStorage.removeItem(KEYS.snapshot)
96}