import { defineStore } from "pinia" import { markRaw, ref, shallowRef } from "vue" import { script } from "../shared/script" import type { PlayerBroadcast } from "../shared/broadcast" import { trpcClient } from "./trpc" import type { SceneDefinition, TextSceneDefinition } from "../shared/script/types" import { sceneTypesById } from "./scene-types" import { throwError } from "../shared/util" export interface CurrentScene { id: string type: typeof sceneTypesById[Type] definition: SceneDefinition & { type: Type } controller: ReturnType } export const useGame = defineStore("gameState", () => { const currentScene = shallowRef>({ id: "pre-start", type: sceneTypesById.text, definition: script.scenesById.get("pre-start") as TextSceneDefinition, controller: markRaw(sceneTypesById.text.createController(script.scenesById.get("pre-start") as TextSceneDefinition)) }) const isConnected = ref(false) const isCrew = window.localStorage.getItem("crew-token") !== null async function switchScene(id: string) { await trpcClient.crew.switchScene.mutate({ sceneId: id }) } function handlePlayerBroadcast(broadcast: PlayerBroadcast) { console.log(broadcast) switch (broadcast.type) { case "scene-changed": const definition = script.scenesById.get(broadcast.sceneId) ?? throwError(`Unknown scene: ${broadcast.sceneId}`) const type = sceneTypesById[definition.type] currentScene.value = { id: broadcast.sceneId, type, definition, controller: markRaw(type.createController(definition as any)) } break case "scene-event": currentScene.value.controller.handleEvent(broadcast.event) break } } trpcClient.join.subscribe(undefined, { onStarted: () => { isConnected.value = true }, onData: handlePlayerBroadcast, onError(error) { console.error("🔴", error) }, onStopped() { window.location.reload() }, }) return { isCrew, isConnected, currentScene, switchScene } })