Added /new and query param handlers #54
3 changed files with 82 additions and 6 deletions
68
src/game/routing.ts
Normal file
68
src/game/routing.ts
Normal file
|
@ -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<string, string> = {};
|
||||||
|
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<T extends string | boolean | DecimalSource>(
|
||||||
|
key: string,
|
||||||
|
ref: Ref<T>,
|
||||||
|
newSavesOnly?: boolean
|
||||||
|
): void;
|
||||||
|
export function registerQueryParam<T extends string | boolean | DecimalSource>(
|
||||||
|
key: string,
|
||||||
|
handlerOrRef: ((value: string) => void) | Ref<T>,
|
||||||
|
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<number>) {
|
||||||
|
return function (value: string) {
|
||||||
|
ref.value = parseFloat(value);
|
||||||
|
};
|
||||||
|
}
|
15
src/main.ts
15
src/main.ts
|
@ -3,7 +3,8 @@ import App from "App.vue";
|
||||||
import projInfo from "data/projInfo.json";
|
import projInfo from "data/projInfo.json";
|
||||||
import "game/notifications";
|
import "game/notifications";
|
||||||
import state from "game/state";
|
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 { useRegisterSW } from "virtual:pwa-register/vue";
|
||||||
import type { App as VueApp } from "vue";
|
import type { App as VueApp } from "vue";
|
||||||
import { createApp, nextTick } 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;",
|
"font-weight: bold; font-size: 24px; color: #A3BE8C; background: #2E3440; padding: 4px 8px; border-radius: 8px;",
|
||||||
"padding: 4px;"
|
"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 { globalBus } = await import("./game/events");
|
||||||
const { startGameLoop } = await import("./game/gameLoop");
|
const { startGameLoop } = await import("./game/gameLoop");
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import projInfo from "data/projInfo.json";
|
||||||
import { globalBus } from "game/events";
|
import { globalBus } from "game/events";
|
||||||
import type { Player } from "game/player";
|
import type { Player } from "game/player";
|
||||||
import player, { stringifySave } 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 LZString from "lz-string";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
@ -33,9 +33,6 @@ export function save(playerData?: Player): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function load(): Promise<void> {
|
export async function load(): Promise<void> {
|
||||||
// Load global settings
|
|
||||||
loadSettings();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let save = localStorage.getItem(settings.active);
|
let save = localStorage.getItem(settings.active);
|
||||||
if (save == null) {
|
if (save == null) {
|
||||||
|
|
Loading…
Reference in a new issue