Add autosave, make saving a bit less weird
This commit is contained in:
parent
53aebd4c50
commit
755ae037a9
3 changed files with 45 additions and 22 deletions
|
@ -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) {
|
||||||
saveSettings[settingId] = setting.current;
|
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
|
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;
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in a new issue