mancala/src/Home.tsx

199 lines
6.2 KiB
TypeScript

import * as React from 'react';
import { FunctionComponent, useState } from 'react';
import BoardView from './components/BoardView';
import { context } from './context'
import { Board, GameMove, Hole, Store } from './mancala';
import { Game } from './mancala';
import { decodeText, encodeText } from './rtmt/byte_util';
import { Bytes } from './rtmt/rtmt';
import { RTMTWS } from './rtmt/rtmt_websocket';
import { channel_game_move, channel_leave_game, channel_on_game_update, channel_on_game_user_leave } from './channel_names';
import Button from './components/Button';
import InfoPanel from './components/InfoPanel';
const testBoard = (): Board => {
const board = new Board(
[new Hole(0), new Hole(4), new Hole(4), new Hole(3), new Hole(2), new Hole(1)],
[new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(10)],
new Store(0), new Store(0))
return board
}
const testGame = new Game("0", "1", testBoard(), "player2", "playing")
type ConnectionState = "connecting" | "error" | "connected" | "reconnecting"
const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
const [userKey, setUserKey] = useState(undefined);
const [connectionState, setConnetionState] = useState<ConnectionState>("connecting")
const [game, setGame] = useState<Game>(undefined)
const [crashMessage, setCrashMessage] = useState<string>(undefined)
const [userKeyWhoLeave, setUserKeyWhoLeave] = useState<string>(undefined)
const onConnectionDone = () => {
setConnetionState("connected")
}
const onConnectionLost = () => {
connectToServer("reconnecting")
}
const onConnectionError = (event: Event) => {
setConnetionState("error")
}
const connectToServer = (connectionState: ConnectionState) => {
setConnetionState(connectionState)
context.userKeyStore.getUserKey((userKey: string) => {
setUserKey(userKey)
const rtmtws = context.rtmt as RTMTWS
if (rtmtws) {
rtmtws.initWebSocket(userKey, onConnectionDone, onConnectionLost, onConnectionError)
} else {
console.log("context.rtmt is not RTMTWS");
}
})
}
const listenMessages = () => {
context.rtmt.listenMessage(channel_on_game_update, (message: Bytes) => {
const newGame: Game = JSON.parse(decodeText(message))
console.log("on game update");
console.log(newGame);
setGame(new Game(newGame.player1, newGame.player2, newGame.board, newGame.turn, newGame.state))
})
context.rtmt.listenMessage(channel_on_game_update, (message: Bytes) => {
const newGame: Game = JSON.parse(decodeText(message))
console.log("on game update");
console.log(newGame);
setGame(new Game(newGame.player1, newGame.player2, newGame.board, newGame.turn, newGame.state))
})
context.rtmt.listenMessage("on_game_start", (message) => {
const newGame: Game = JSON.parse(decodeText(message))
console.log("on_game_start");
console.log(newGame);
setGame(new Game(newGame.player1, newGame.player2, newGame.board, newGame.turn, newGame.state))
})
context.rtmt.listenMessage("on_game_crashed", (message) => {
const newCrashMessage = decodeText(message)
console.log("on_game_crash");
console.log(newCrashMessage);
setCrashMessage(newCrashMessage)
})
context.rtmt.listenMessage(channel_on_game_user_leave, (message) => {
const userKeyWhoLeave = decodeText(message)
console.log("on_game_user_leave");
console.log(channel_on_game_user_leave);
setUserKeyWhoLeave(userKeyWhoLeave)
})
}
React.useEffect(() => {
listenMessages()
connectToServer("connecting")
}, [])
const resetGameState = () => {
setGame(undefined)
setCrashMessage(undefined)
setUserKeyWhoLeave(undefined)
}
const newGameClick = () => {
resetGameState()
context.rtmt.sendMessage("new_game", new Uint8Array())
}
const leaveGame = () => {
context.rtmt.sendMessage(channel_leave_game, new Uint8Array())
}
const onHoleSelect = (index: number, hole: Hole) => {
const gameMove: GameMove = { index: index }
context.rtmt.sendMessage(channel_game_move, encodeText(JSON.stringify(gameMove)))
}
const showConnectionState = connectionState != "connected"
const connectionStateText = () => {
let map: { [key: string]: string } = {
"connecting": context.texts.Connecting,
"connected": context.texts.Connected,
"error": context.texts.CannotConnect,
"reconnecting": context.texts.ConnectingAgain
};
return map[connectionState]
}
const renderNewGameButton = () => {
const newGame = <Button text={context.texts.NewGame} color="white" onClick={newGameClick} />
if (userKeyWhoLeave) {
return newGame
}
if (crashMessage) {
return newGame
}
if (!game) {
return newGame
} else if (game.state == "ended") {
return newGame
}
return <></>
}
return <div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
background: "#EEEEEE",
flex: "1",
}}>
{showConnectionState &&
<div style={{
position: "absolute",
bottom: "0px",
left: "0px",
padding: "15px 15px 5px 5px",
borderTopRightRadius: "1vw",
minWidth: "10vw",
minHeight: "1vw",
background: "grey"
}}>
{connectionStateText()}
</div>}
<div style={{
padding: "0px 50px",
background: "rgb(228, 228, 228)",
display: 'flex',
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
alignSelf: "stretch"
}}>
<h1 style={{ margin: "10px 0px" }}>{context.texts.Mancala}</h1>
<div>
{renderNewGameButton()}
{game && !userKeyWhoLeave && < Button color="white" text={context.texts.Leave} onClick={leaveGame} />}
</div>
</div>
<InfoPanel game={game} crashMessage={crashMessage} userKey={userKey} userKeyWhoLeave={userKeyWhoLeave} />
{game && <BoardView userKey={userKey} game={game} onHoleSelect={onHoleSelect} />}
</div >
}
export default Home
function channel_game_user_leave(channel_game_user_leave: any, arg1: (message: Uint8Array) => void) {
throw new Error('Function not implemented.');
}