82 lines
No EOL
2.7 KiB
TypeScript
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 })
|
|
}
|
|
}
|
|
}) |