144 lines
6.1 KiB
TypeScript
144 lines
6.1 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 type OnWordSelectCallback = (npc: TalkNPC, word: string) => 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 [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 [onWordSelect, setOnWordSelect] = React.useState<OnWordSelectCallback | null>(null)
|
|
const [stateGame, setStateGame] = React.useState<StateGame>(StateGame.MainScreen)
|
|
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}/>
|
|
)
|
|
}
|
|
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}
|
|
setOnWordSelect={setOnWordSelect}
|
|
setStateGame={setStateGame}/>
|
|
</>
|
|
)
|
|
}
|
|
return <></>
|
|
}
|