LasTres/js-src/components/game.tsx

145 lines
6.2 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 type { ActionHash } from '@lastres/action'
import type { TalkNPCs, TalkNPC } from '@lastres/talk-npc'
import type { Words } from '@lastres/word'
import UpperPanel from '@lastres/components/upper-panel'
import BottomPanel from '@lastres/components/bottom-panel'
import PJSelectionMenu from '@lastres/components/pj-selection-menu'
import WordSelector from '@lastres/components/word-selector'
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 enum StateGame {
MainScreen,
SelectingWord,
}
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 [enemyTeamPJs, setEnemyTeamPJs] = React.useState<PJ[] | null>(null)
const [isBattling, setIsBattling] = React.useState<boolean | 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 [actionHash, setActionHash] = React.useState<ActionHash | null>(null)
const [talkNPCs, setTalkNPCs] = React.useState<TalkNPCs | null>(null)
const [stateGame, setStateGame] = React.useState<StateGame>(StateGame.MainScreen)
const [NPCToSayWord, setNPCToSayWord] = React.useState<TalkNPC | null>(null)
const [words, setWords] = React.useState<Words | 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) {
console.log('Opening websocket')
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.CONNECTING) {
return
}
if (webSocket.readyState === WebSocket.OPEN) {
new OutputPacketPing().send(webSocket)
return
}
window.clearInterval(interval)
}, 50000)
}
const inputPackets = new InputPackets(setTeamPJs,
setEnemyTeamPJs, setIsBattling,
setCurrentLocation, setConnectedLocations,
logLines, setLogLines, setError,
setScrollLog, logPresentationRef,
setMovingTo, setRemainingFrames,
setActionHash, setTalkNPCs, setWords)
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
})
}, 300)
if (stateGame === StateGame.SelectingWord) {
return (
<WordSelector words={words}
setStateGame={setStateGame}
websocket={websocket}
NPCToSayWord={NPCToSayWord}/>
)
}
if (stateGame === StateGame.MainScreen) {
return (
<>
<UpperPanel teamPJs={teamPJs}
enemyTeamPJs={enemyTeamPJs}
isBattling={isBattling}
currentLocation={currentLocation}
connectedLocations={connectedLocations}
logLines={logLines}
websocket={websocket}
logPresentationRef={logPresentationRef}
movingTo={movingTo}
remainingFrames={remainingFrames}/>
<BottomPanel actionHash={actionHash}
websocket={websocket}
talkNPCs={talkNPCs}
setNPCToSayWord={setNPCToSayWord}
setStateGame={setStateGame}/>
</>
)
}
return <></>
}