import { hasWon } from "@/data/mod"; import { globalBus } from "@/game/events"; import player from "@/game/player"; import { Computable, GetComputableTypeWithDefault, GetComputableType, ProcessedComputable, processComputable } from "@/util/computed"; import { createLazyProxy } from "@/util/proxies"; import { unref } from "vue"; import { findFeatures, Replace, setDefault } from "./feature"; export const hotkeys: Record = {}; export const HotkeyType = Symbol("Hotkey"); export interface HotkeyOptions { enabled?: Computable; key: string; description: Computable; onPress: VoidFunction; } interface BaseHotkey { type: typeof HotkeyType; } export type Hotkey = Replace< T & BaseHotkey, { enabled: GetComputableTypeWithDefault; description: GetComputableType; } >; export type GenericHotkey = Replace< Hotkey, { enabled: ProcessedComputable; } >; export function createHotkey( optionsFunc: () => T & ThisType> ): Hotkey { return createLazyProxy(() => { const hotkey: T & Partial = optionsFunc(); hotkey.type = HotkeyType; processComputable(hotkey as T, "enabled"); setDefault(hotkey, "enabled", true); processComputable(hotkey as T, "description"); return hotkey as unknown as Hotkey; }); } globalBus.on("addLayer", layer => { (findFeatures(layer, HotkeyType) as GenericHotkey[]).forEach(hotkey => { hotkeys[hotkey.key] = hotkey; }); }); globalBus.on("removeLayer", layer => { (findFeatures(layer, HotkeyType) as GenericHotkey[]).forEach(hotkey => { hotkeys[hotkey.key] = undefined; }); }); document.onkeydown = function (e) { if ((e.target as HTMLElement | null)?.tagName === "INPUT") { return; } if (hasWon.value && !player.keepGoing) { return; } let key = e.key; if (e.shiftKey) { key = "shift+" + key; } if (e.ctrlKey) { key = "ctrl+" + key; } const hotkey = hotkeys[key]; if (hotkey && unref(hotkey.enabled)) { e.preventDefault(); hotkey.onPress(); } };