Add autosave, make saving a bit less weird

This commit is contained in:
Tobias Berger 2021-10-02 19:17:59 +02:00
parent 53aebd4c50
commit 755ae037a9
3 changed files with 45 additions and 22 deletions

View file

@ -3,6 +3,7 @@ import type { SharkGame } from "./SharkGame";
import { StaticClass } from "./StaticClass"; import { StaticClass } from "./StaticClass";
import type { TabHandler } from "./TabHandler"; import type { TabHandler } from "./TabHandler";
import { LZString } from "./LZString"; import { LZString } from "./LZString";
import { Settings } from "./Settings";
const __EMPTY_OBJECT = {}; const __EMPTY_OBJECT = {};
type Version0Save = typeof __EMPTY_OBJECT; type Version0Save = typeof __EMPTY_OBJECT;
@ -13,7 +14,7 @@ type Version1Save = Version0Save & {
type: MessageType; type: MessageType;
}[]; }[];
selectedTab: keyof typeof TabHandler["AllTabs"]; selectedTab: keyof typeof TabHandler["AllTabs"];
settings: Record<`${string};${string}`, unknown>; settings: Record<string, Record<string, unknown>>;
}; };
type CurrentVersionSave = Version1Save; type CurrentVersionSave = Version1Save;
@ -22,7 +23,22 @@ type Save = Version0Save | Version1Save;
export class SaveHandler extends StaticClass { export class SaveHandler extends StaticClass {
static readonly saveName = "sharg-save"; static readonly saveName = "sharg-save";
static #saveInterval: ReturnType<typeof setInterval> | 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<void> { static async save(game: typeof SharkGame): Promise<void> {
console.debug("Saving");
console.time("Done saving");
const messages = await new Promise<Message[]>((resolve) => { const messages = await new Promise<Message[]>((resolve) => {
game.Log.messages.subscribe((messages) => { game.Log.messages.subscribe((messages) => {
resolve(messages); resolve(messages);
@ -36,14 +52,17 @@ export class SaveHandler extends StaticClass {
const selectedTabIndex = allTabsEntries.findIndex(([, tab]) => tab === game.TabHandler.currentTab); const selectedTabIndex = allTabsEntries.findIndex(([, tab]) => tab === game.TabHandler.currentTab);
const selectedTabName = allTabsEntries[selectedTabIndex][0]; const selectedTabName = allTabsEntries[selectedTabIndex][0];
const currentSettings = game.Settings.getSaveable(); const currentSettings = game.Settings.getSettings();
const saveSettings: CurrentVersionSave["settings"] = {}; const saveSettings: CurrentVersionSave["settings"] = {};
for (const [settingId, setting] of Object.entries(currentSettings) as [ for (const [categoryId, categorySettings] of Object.entries(currentSettings)) {
keyof typeof currentSettings, const categorySave: CurrentVersionSave["settings"][string] = {};
typeof currentSettings[keyof typeof currentSettings] for (const [settingId, setting] of Object.entries(categorySettings)) {
][]) { if (setting.current !== setting.default) {
if (setting.current !== setting.default) { categorySave[settingId] = setting.current;
saveSettings[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 Math.round((encodedSave.length / stringifiedSave.length) * 100 * 100) / 100
}% size` }% size`
); );
console.timeEnd("Done saving");
localStorage.setItem(SaveHandler.saveName, encodedSave); localStorage.setItem(SaveHandler.saveName, encodedSave);
} }
@ -90,8 +110,8 @@ export class SaveHandler extends StaticClass {
game.Settings.settings.update((settings) => { game.Settings.settings.update((settings) => {
Object.entries(settings).forEach(([categoryName, categorySettings]) => { Object.entries(settings).forEach(([categoryName, categorySettings]) => {
Object.entries(categorySettings).forEach(([settingName, setting]) => { Object.entries(categorySettings).forEach(([settingId, setting]) => {
setting.current = fullSave.settings[`${categoryName};${settingName}`] ?? setting.default; setting.current = fullSave.settings[categoryName]?.[settingId] ?? setting.default;
}); });
}); });
return settings; return settings;

View file

@ -38,22 +38,21 @@ export class Settings extends StaticClass {
options: [true, false] as const, 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 readonly settings = writable(Settings.#settings);
static getSettings(): SettingsRecord { static getSettings(): SettingsRecord {
return Object.seal(Object.assign({}, Settings.#settings)); 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 = { export type Setting = {

View file

@ -68,12 +68,16 @@ export class SharkGame extends StaticClass {
}); });
static init(): void { static init(): void {
Log.init();
SaveHandler.load(this); SaveHandler.load(this);
Log.init();
SaveHandler.init(this);
SharkGame.title = SharkGame.#GAME_NAMES[Math.floor(Math.random() * SharkGame.#GAME_NAMES.length)]; SharkGame.title = SharkGame.#GAME_NAMES[Math.floor(Math.random() * SharkGame.#GAME_NAMES.length)];
} }
static save(): void {
SaveHandler.save(this);
}
} }
window.SharkGame = SharkGame; window.SharkGame = SharkGame;