diff --git a/src/game/routing.ts b/src/game/routing.ts new file mode 100644 index 0000000..693c1d6 --- /dev/null +++ b/src/game/routing.ts @@ -0,0 +1,68 @@ +import { globalBus } from "game/events"; +import { DecimalSource } from "util/bignum"; +import { Ref } from "vue"; +import player from "./player"; + +// https://stackoverflow.com/questions/2090551/parse-query-string-in-javascript +function parseQuery(queryString = window.location.search) { + const query: Record = {}; + const pairs = (queryString[0] === "?" ? queryString.substring(1) : queryString).split("&"); + for (let i = 0; i < pairs.length; i++) { + const pair = pairs[i].split("="); + query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ""); + } + return query; +} +const params = parseQuery(); + +/** + * Register a handler to be called when creating new saves based on a query param + * @param key The query param to regster + * @param handler The callback function when the query param is present + * @param newSavesOnly If set to true, only call the handler on the /new path + */ +export function registerQueryParam( + key: string, + handler: (value: string) => void, + newSavesOnly?: boolean +): void; +/** + * Register a ref to have its value set based on a query param + * @param key The query param to regster + * @param ref The ref to set the value of + * @param newSavesOnly If set to true, only overwrite values on the /new path + * @see {@link numberHandler}. + */ +export function registerQueryParam( + key: string, + ref: Ref, + newSavesOnly?: boolean +): void; +export function registerQueryParam( + key: string, + handlerOrRef: ((value: string) => void) | Ref, + newSavesOnly = false +) { + globalBus.on("onLoad", () => { + if (newSavesOnly && player.timePlayed > 0) { + return; + } + if (key in params) { + if (typeof handlerOrRef === "function") { + handlerOrRef(params[key]); + } else { + if (typeof handlerOrRef.value === "boolean") { + (handlerOrRef.value as boolean) = params[key].toLowerCase() === "true"; + } else { + (handlerOrRef.value as string | DecimalSource) = params[key]; + } + } + } + }); +} + +export function numberHandler(ref: Ref) { + return function (value: string) { + ref.value = parseFloat(value); + }; +} diff --git a/src/main.ts b/src/main.ts index e416fa5..1e24deb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,8 @@ import App from "App.vue"; import projInfo from "data/projInfo.json"; import "game/notifications"; import state from "game/state"; -import { load } from "util/save"; +import { loadSettings } from "game/settings"; +import { load, loadSave, newSave } from "util/save"; import { useRegisterSW } from "virtual:pwa-register/vue"; import type { App as VueApp } from "vue"; import { createApp, nextTick } from "vue"; @@ -59,7 +60,17 @@ requestAnimationFrame(async () => { "font-weight: bold; font-size: 24px; color: #A3BE8C; background: #2E3440; padding: 4px 8px; border-radius: 8px;", "padding: 4px;" ); - await load(); + + // Load global settings + loadSettings(); + + if (window.location.pathname === "/new") { + await loadSave(newSave()); + } else { + await load(); + } + window.history.replaceState({}, document.title, "/"); + const { globalBus } = await import("./game/events"); const { startGameLoop } = await import("./game/gameLoop"); diff --git a/src/util/save.ts b/src/util/save.ts index 4137e5b..3f7da26 100644 --- a/src/util/save.ts +++ b/src/util/save.ts @@ -2,7 +2,7 @@ import projInfo from "data/projInfo.json"; import { globalBus } from "game/events"; import type { Player } from "game/player"; import player, { stringifySave } from "game/player"; -import settings, { loadSettings } from "game/settings"; +import settings from "game/settings"; import LZString from "lz-string"; import { ref } from "vue"; @@ -33,9 +33,6 @@ export function save(playerData?: Player): string { } export async function load(): Promise { - // Load global settings - loadSettings(); - try { let save = localStorage.getItem(settings.active); if (save == null) {