From 755ae037a94c42e2463d3014a2cd11b025fdda8a Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Sat, 2 Oct 2021 19:17:59 +0200 Subject: [PATCH] Add autosave, make saving a bit less weird --- src/shark/SaveHandler.ts | 40 ++++++++++++++++++++++++++++++---------- src/shark/Settings.ts | 19 +++++++++---------- src/shark/SharkGame.ts | 8 ++++++-- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/shark/SaveHandler.ts b/src/shark/SaveHandler.ts index 462eb4d..4c4d4a2 100644 --- a/src/shark/SaveHandler.ts +++ b/src/shark/SaveHandler.ts @@ -3,6 +3,7 @@ import type { SharkGame } from "./SharkGame"; import { StaticClass } from "./StaticClass"; import type { TabHandler } from "./TabHandler"; import { LZString } from "./LZString"; +import { Settings } from "./Settings"; const __EMPTY_OBJECT = {}; type Version0Save = typeof __EMPTY_OBJECT; @@ -13,7 +14,7 @@ type Version1Save = Version0Save & { type: MessageType; }[]; selectedTab: keyof typeof TabHandler["AllTabs"]; - settings: Record<`${string};${string}`, unknown>; + settings: Record>; }; type CurrentVersionSave = Version1Save; @@ -22,7 +23,22 @@ type Save = Version0Save | Version1Save; export class SaveHandler extends StaticClass { static readonly saveName = "sharg-save"; + static #saveInterval: ReturnType | undefined = undefined; + + static init(game: typeof SharkGame): void { + Settings.settings.subscribe((settings) => { + if (SaveHandler.#saveInterval !== undefined) { + clearInterval(SaveHandler.#saveInterval); + } + if (settings.behavior.autoSave.current !== "Off") { + SaveHandler.#saveInterval = setInterval(() => game.save(), settings.behavior.autoSave.current * 1000); + } + }); + } + static async save(game: typeof SharkGame): Promise { + console.debug("Saving"); + console.time("Done saving"); const messages = await new Promise((resolve) => { game.Log.messages.subscribe((messages) => { resolve(messages); @@ -36,14 +52,17 @@ export class SaveHandler extends StaticClass { const selectedTabIndex = allTabsEntries.findIndex(([, tab]) => tab === game.TabHandler.currentTab); const selectedTabName = allTabsEntries[selectedTabIndex][0]; - const currentSettings = game.Settings.getSaveable(); + const currentSettings = game.Settings.getSettings(); const saveSettings: CurrentVersionSave["settings"] = {}; - for (const [settingId, setting] of Object.entries(currentSettings) as [ - keyof typeof currentSettings, - typeof currentSettings[keyof typeof currentSettings] - ][]) { - if (setting.current !== setting.default) { - saveSettings[settingId] = setting.current; + for (const [categoryId, categorySettings] of Object.entries(currentSettings)) { + const categorySave: CurrentVersionSave["settings"][string] = {}; + for (const [settingId, setting] of Object.entries(categorySettings)) { + if (setting.current !== setting.default) { + categorySave[settingId] = setting.current; + } + } + if (Object.keys(categorySave).length > 0) { + saveSettings[categoryId] = categorySave; } } @@ -65,6 +84,7 @@ export class SaveHandler extends StaticClass { Math.round((encodedSave.length / stringifiedSave.length) * 100 * 100) / 100 }% size` ); + console.timeEnd("Done saving"); localStorage.setItem(SaveHandler.saveName, encodedSave); } @@ -90,8 +110,8 @@ export class SaveHandler extends StaticClass { game.Settings.settings.update((settings) => { Object.entries(settings).forEach(([categoryName, categorySettings]) => { - Object.entries(categorySettings).forEach(([settingName, setting]) => { - setting.current = fullSave.settings[`${categoryName};${settingName}`] ?? setting.default; + Object.entries(categorySettings).forEach(([settingId, setting]) => { + setting.current = fullSave.settings[categoryName]?.[settingId] ?? setting.default; }); }); return settings; diff --git a/src/shark/Settings.ts b/src/shark/Settings.ts index f9be57d..c1eae52 100644 --- a/src/shark/Settings.ts +++ b/src/shark/Settings.ts @@ -38,22 +38,21 @@ export class Settings extends StaticClass { options: [true, false] as const, }, }, + behavior: { + autoSave: { + current: 1 as "Off" | number, + default: 1 as const, + name: "Autosave" as const, + description: "How many seconds to wait between each autosave" as const, + options: ["Off", 1, 5, 15, 60] as const, + }, + }, }; static readonly settings = writable(Settings.#settings); static getSettings(): SettingsRecord { return Object.seal(Object.assign({}, Settings.#settings)); } - static getSaveable(): Record<`${string};${string}`, Setting> { - const current = this.getSettings(); - const result: Record<`${string};${string}`, Setting> = {}; - for (const [categoryName, category] of Object.entries(current)) { - for (const [settingName, setting] of Object.entries(category)) { - result[`${categoryName};${settingName}`] = setting; - } - } - return result; - } } export type Setting = { diff --git a/src/shark/SharkGame.ts b/src/shark/SharkGame.ts index 6a383d4..3206ecc 100644 --- a/src/shark/SharkGame.ts +++ b/src/shark/SharkGame.ts @@ -68,12 +68,16 @@ export class SharkGame extends StaticClass { }); static init(): void { - Log.init(); - SaveHandler.load(this); + Log.init(); + SaveHandler.init(this); + SharkGame.title = SharkGame.#GAME_NAMES[Math.floor(Math.random() * SharkGame.#GAME_NAMES.length)]; } + static save(): void { + SaveHandler.save(this); + } } window.SharkGame = SharkGame;