LasTres/js-src/components/game.tsx

105 lines
4.4 KiB
TypeScript

import * as React from 'react'
import type { PJ } from '@lastres/pj'
import type { Location } from '@lastres/location'
import type { LogLine } from '@lastres/log-line'
import UpperPanel from '@lastres/components/upper-panel'
import BottomPanel from '@lastres/components/bottom-panel'
import PJSelectionMenu from '@lastres/components/pj-selection-menu'
import OutputPacketInit from '@lastres/output-packet/init'
import OutputPacketPing from '@lastres/output-packet/ping'
import InputPackets from '@lastres/input-packets'
export type SetWebsocketCallback = (websocket: WebSocket | null) => WebSocket | null
export interface GameProps {
setSelectedPJ: (set: PJ | null) => void
selectedPJ: PJ | null
userWantsToCreatePJ: boolean
setUserWantsToCreatePJ: (set: boolean) => void
error: string | null
setError: (set: string | null) => void
websocket: WebSocket | null
setWebsocket: (websocket: WebSocket | null | SetWebsocketCallback) => void
}
export default function Game (props: GameProps): JSX.Element {
const selectedPJ = props.selectedPJ
if (selectedPJ === null) {
return (
<>
<PJSelectionMenu
setSelectedPJ={props.setSelectedPJ}
userWantsToCreatePJ={props.userWantsToCreatePJ}
setUserWantsToCreatePJ={props.setUserWantsToCreatePJ}
error={props.error}
setError={props.setError}/>
</>
)
}
const [teamPJs, setTeamPJs] = React.useState<PJ[] | null>(null)
const [currentLocation, setCurrentLocation] = React.useState<Location | null>(null)
const [connectedLocations, setConnectedLocations] = React.useState<Location[] | null>(null)
const [logLines, setLogLines] = React.useState<LogLine[] | null>(null)
const [error, setError] = React.useState<string | null>(null)
const [scrollLog, setScrollLog] = React.useState<number | null>(null)
const [movingTo, setMovingTo] = React.useState<Location | null>(null)
const [remainingFrames, setRemainingFrames] = React.useState<number | null>(null)
const logPresentationRef = React.useRef<HTMLDivElement>(null)
const websocket = props.websocket
const setWebsocket = props.setWebsocket
window.setTimeout(() => {
setWebsocket((websocket): WebSocket | null => {
if (websocket === null) {
const locationProtocol = window.location.protocol
if (locationProtocol == null) {
return null
}
const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws'
const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`)
webSocket.onopen = () => {
new OutputPacketInit(selectedPJ.uuid).send(webSocket)
let interval: number = 0
interval = window.setInterval(() => {
if (webSocket.readyState === WebSocket.OPEN) {
new OutputPacketPing().send(webSocket)
return
}
window.clearInterval(interval)
}, 250000)
}
const inputPackets = new InputPackets(setTeamPJs,
setCurrentLocation, setConnectedLocations,
logLines, setLogLines, setError, setScrollLog,
logPresentationRef, setMovingTo, setRemainingFrames)
webSocket.onmessage = (event) => {
const packet = JSON.parse(event.data)
inputPackets.handle(packet)
}
webSocket.onerror = (event) => {
console.log(event)
}
webSocket.onclose = (event) => {
console.log('Websocket closed')
setWebsocket(null)
}
return webSocket
}
return websocket
})
}, 100)
return (
<>
<UpperPanel teamPJs={teamPJs}
currentLocation={currentLocation}
connectedLocations={connectedLocations}
logLines={logLines}
websocket={websocket}
logPresentationRef={logPresentationRef}
movingTo={movingTo}
remainingFrames={remainingFrames}/>
<BottomPanel/>
</>
)
}