level-up/frontend/game.ts
Moritz Ruth 3498bbb8ad
All checks were successful
Build / build (push) Successful in 1m20s
Add virtual curtain
2025-04-14 17:37:03 +02:00

82 lines
No EOL
2.7 KiB
TypeScript

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<Type extends keyof typeof sceneTypesById> {
id: string
type: typeof sceneTypesById[Type]
definition: SceneDefinition & { type: Type }
controller: ReturnType<typeof sceneTypesById[Type]["createController"]>
}
export const useGame = defineStore("gameState", () => {
const currentScene = shallowRef<CurrentScene<keyof typeof sceneTypesById>>({
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 isVirtualCurtainOpen = ref(false)
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
case "virtual-curtain-changed":
isVirtualCurtainOpen.value = broadcast.isOpen
break
}
}
trpcClient.join.subscribe(undefined, {
onStarted: () => {
isConnected.value = true
},
onData: handlePlayerBroadcast,
onError(error) {
console.error("🔴", error)
},
onStopped() {
window.location.reload()
},
})
return {
isCrew,
isConnected,
currentScene,
isVirtualCurtainOpen,
switchScene,
async setVirtualCurtainOpen(isOpen: boolean) {
await trpcClient.crew.setVirtualCurtainOpen.mutate({ isOpen })
}
}
})