import { sys } from 'cc'; import { IStorage, MemoryStorage } from './IStorage'; /** * The one file in the save module that touches the engine. * * `sys.localStorage` is backed by the browser store on web and by a native file * on Android and iOS, so one implementation covers every target. It can still * fail — private browsing, a full quota, a locked profile — so every call is * guarded and falls back to an in-memory store, which keeps the session * consistent even when nothing can be persisted. */ export class CocosStorage implements IStorage { private readonly _fallback = new MemoryStorage(); private _usingFallback = false; /** True once a storage call has failed and the session went in-memory. */ get degraded(): boolean { return this._usingFallback; } getItem(key: string): string | null { if (this._usingFallback) { return this._fallback.getItem(key); } try { return sys.localStorage.getItem(key); } catch (error) { this._degrade(error); return this._fallback.getItem(key); } } setItem(key: string, value: string): void { if (!this._usingFallback) { try { sys.localStorage.setItem(key, value); return; } catch (error) { this._degrade(error); } } this._fallback.setItem(key, value); } removeItem(key: string): void { if (!this._usingFallback) { try { sys.localStorage.removeItem(key); return; } catch (error) { this._degrade(error); } } this._fallback.removeItem(key); } private _degrade(error: unknown): void { if (this._usingFallback) return; this._usingFallback = true; const message = error instanceof Error ? error.message : String(error); console.warn(`[save] device storage is unavailable, progress will not persist: ${message}`); } }