import * as defaultSaveStateData from './DefaultSaveStates.json' ; export type SettingCallback = ( saveManager : SaveManager , key : string ) => void ; export type SaveStateCallback = ( saveManager : SaveManager ) => void ; interface SaveStateMap { [ k ] : string ; } export const enum SaveStateLocation { LocalStorage , SessionStorage , Defaults , None } interface SettingListener { callback : SettingCallback ; key : string ; } export class SaveManager { private settingListeners : SettingListener [ ] = [ ] ; private saveStateListeners : SaveStateCallback [ ] = [ ] ; constructor ( ) { this . cleanOldKeys ( ) ; } private cleanOldKeys ( ) { window . localStorage . removeItem ( 'CameraStates' ) ; window . localStorage . removeItem ( 'SaveStates' ) ; for ( let i = window . localStorage . length - 1 ; i >= 0 ; i -- ) { const key = window . localStorage . key ( i ) ! ; if ( key . startsWith ( 'SaveState_' ) && key . endsWith ( '/0' ) ) window . localStorage . removeItem ( key ) ; } } private getSettingKey ( key ) { return `Setting_${ key }` ; } public loadSetting < T > ( key , defaultValue ) { const valueStr = window . localStorage . getItem ( this . getSettingKey ( key ) ) ; if ( valueStr !== null ) return JSON . parse ( valueStr ) ; else return defaultValue ; } public saveSetting < T > ( key , value , force = false ) { if ( ! force && this . loadSetting < T | null > ( key , null ) === value ) return ; window . localStorage . setItem ( this . getSettingKey ( key ) , JSON . stringify ( value ) ) ; for ( let i = 0 ; i < this . settingListeners . length ; i ++ ) if ( this . settingListeners [ i ] . key === key ) this . settingListeners [ i ] . callback ( this , key ) ; } public addSettingListener ( key , callback , triggerNow = true ) { this . settingListeners . push ( { callback , key } ) ; if ( triggerNow ) callback ( this , key ) ; } public getSaveStateSlotKey ( sceneDescId , slotIndex ) { return `SaveState_${ sceneDescId }/${ slotIndex }` ; } public getCurrentSceneDescId ( ) { return window . sessionStorage . getItem ( 'CurrentSceneDescId' ) || null ; } public setCurrentSceneDescId ( id ) { window . sessionStorage . setItem ( 'CurrentSceneDescId' , id ) ; } public addSaveStateListener ( callback ) { this . saveStateListeners . push ( callback ) ; } private callSaveStateListeners ( ) { for ( let i = 0 ; i < this . saveStateListeners . length ; i ++ ) this . saveStateListeners [ i ] ( this ) ; } public saveTemporaryState ( key , serializedState ) { window . localStorage . removeItem ( key ) ; window . sessionStorage . setItem ( key , serializedState ) ; } public saveState ( key , serializedState ) { window . localStorage . setItem ( key , serializedState ) ; this . callSaveStateListeners ( ) ; } public deleteState ( key ) { window . localStorage . removeItem ( key ) ; this . callSaveStateListeners ( ) ; } public hasStateInLocation ( key , location ) { if ( location === SaveStateLocation . LocalStorage ) return key in window . localStorage ; if ( location === SaveStateLocation . SessionStorage ) return key in window . sessionStorage ; if ( location === SaveStateLocation . Defaults ) return key in defaultSaveStateData ; return false ; } public loadStateFromLocation ( key , location ) { if ( location === SaveStateLocation . LocalStorage ) return window . localStorage . getItem ( key ) ; if ( location === SaveStateLocation . SessionStorage ) return window . sessionStorage . getItem ( key ) ; if ( location === SaveStateLocation . Defaults && key in defaultSaveStateData ) return ( defaultSaveStateData as SaveStateMap ) [ key ] || null ; return null ; } public loadState ( key ) { let state = null ; state = window . localStorage . getItem ( key ) ; if ( state ) return state ; state = window . sessionStorage . getItem ( key ) ; if ( state ) return state ; state = ( defaultSaveStateData as SaveStateMap ) [ key ] ; if ( state ) return state ; return null ; } public export ( ) { return JSON . stringify ( Object . assign ( { } , window . localStorage ) , null , 4 ) ; } } export const GlobalSaveManager = new SaveManager ( ) ;