Profectus-Demo/src/util/save.ts

138 lines
4.2 KiB
TypeScript
Raw Normal View History

2022-03-04 03:39:48 +00:00
import projInfo from "data/projInfo.json";
import player, { Player, PlayerData, stringifySave } from "game/player";
import settings, { loadSettings } from "game/settings";
import { ProxyState } from "./proxies";
import LZString from "lz-string";
2022-01-25 04:25:34 +00:00
export function setupInitialStore(player: Partial<PlayerData> = {}): Player {
return Object.assign(
{
id: `${projInfo.id}-0`,
name: "Default Save",
tabs: projInfo.initialTabs.slice(),
time: Date.now(),
autosave: true,
offlineProd: true,
offlineTime: 0,
timePlayed: 0,
keepGoing: false,
modID: projInfo.id,
modVersion: projInfo.versionNumber,
2022-01-14 04:25:47 +00:00
layers: {}
},
2022-01-14 04:25:47 +00:00
player
2022-01-25 04:25:34 +00:00
) as Player;
}
export function save(playerData?: PlayerData): string {
let stringifiedSave = stringifySave(playerData ?? player[ProxyState]);
switch (projInfo.saveEncoding) {
default:
console.warn(`Unknown save encoding: ${projInfo.saveEncoding}. Defaulting to lz`);
case "lz":
stringifiedSave = LZString.compressToUTF16(stringifiedSave);
break;
case "base64":
stringifiedSave = btoa(unescape(encodeURIComponent(stringifiedSave)));
break;
case "plain":
break;
}
localStorage.setItem((playerData ?? player[ProxyState]).id, stringifiedSave);
2022-01-14 04:25:47 +00:00
return stringifiedSave;
}
export async function load(): Promise<void> {
// Load global settings
loadSettings();
try {
let save = localStorage.getItem(settings.active);
if (save == null) {
await loadSave(newSave());
return;
}
if (save[0] === "{") {
// plaintext. No processing needed
} else if (save[0] === "e") {
// Assumed to be base64, which starts with e
save = decodeURIComponent(escape(atob(save)));
} else if (save[0] === "ᯡ") {
// Assumed to be lz, which starts with ᯡ
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
save = LZString.decompressFromUTF16(save)!;
} else {
throw `Unable to determine save encoding`;
}
const player = JSON.parse(save);
if (player.modID !== projInfo.id) {
await loadSave(newSave());
return;
}
2022-01-14 04:25:47 +00:00
player.id = settings.active;
await loadSave(player);
} catch (e) {
2022-01-25 04:23:30 +00:00
console.error("Failed to load save. Falling back to new save.\n", e);
await loadSave(newSave());
}
}
export function newSave(): PlayerData {
const id = getUniqueID();
2022-01-25 04:25:34 +00:00
const player = setupInitialStore({ id });
save(player);
settings.saves.push(id);
2022-01-14 04:25:47 +00:00
return player;
}
export function getUniqueID(): string {
let id,
i = 0;
do {
id = `${projInfo.id}-${i++}`;
} while (localStorage.getItem(id));
return id;
}
2022-01-14 04:25:47 +00:00
export async function loadSave(playerObj: Partial<PlayerData>): Promise<void> {
2022-01-25 04:23:30 +00:00
console.info("Loading save", playerObj);
2022-03-04 03:39:48 +00:00
const { layers, removeLayer, addLayer } = await import("game/layers");
const { fixOldSave, getInitialLayers } = await import("data/projEntry");
for (const layer in layers) {
2022-01-25 04:23:30 +00:00
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
removeLayer(layers[layer]!);
}
2022-01-14 04:25:47 +00:00
getInitialLayers(playerObj).forEach(layer => addLayer(layer, playerObj));
2022-01-25 04:25:34 +00:00
playerObj = setupInitialStore(playerObj);
2022-01-14 04:25:47 +00:00
if (playerObj.offlineProd && playerObj.time) {
if (playerObj.offlineTime == undefined) playerObj.offlineTime = 0;
playerObj.offlineTime += (Date.now() - playerObj.time) / 1000;
}
2022-01-14 04:25:47 +00:00
playerObj.time = Date.now();
if (playerObj.modVersion !== projInfo.versionNumber) {
2022-01-14 04:25:47 +00:00
fixOldSave(playerObj.modVersion, playerObj);
}
2022-01-14 04:25:47 +00:00
Object.assign(player, playerObj);
2022-01-25 04:25:34 +00:00
settings.active = player.id;
}
setInterval(() => {
if (player.autosave) {
save();
}
}, 1000);
window.onbeforeunload = () => {
if (player.autosave) {
save();
}
};
window.save = save;
2021-08-28 16:35:25 +00:00
export const hardReset = (window.hardReset = async () => {
await loadSave(newSave());
2021-08-28 16:35:25 +00:00
});