2022-05-12 23:41:24 +03:00
|
|
|
import * as React from "react";
|
|
|
|
|
import { FunctionComponent, useEffect, useState } from "react";
|
|
|
|
|
import BoardView from "./components/BoardView";
|
|
|
|
|
import { context } from "./context";
|
|
|
|
|
import { RTMTWS } from "./rtmt/rtmt_websocket";
|
|
|
|
|
import {
|
|
|
|
|
channel_game_move,
|
|
|
|
|
channel_leave_game,
|
2022-05-15 02:06:09 +03:00
|
|
|
channel_on_game_crashed,
|
|
|
|
|
channel_on_game_start,
|
2022-05-12 23:41:24 +03:00
|
|
|
channel_on_game_update,
|
|
|
|
|
channel_on_game_user_leave,
|
|
|
|
|
} from "./channel_names";
|
|
|
|
|
import Button from "./components/Button";
|
|
|
|
|
import InfoPanel from "./components/InfoPanel";
|
|
|
|
|
import { CommonMancalaGame, MancalaGame, Pit } from "mancala.js";
|
|
|
|
|
import { GameMove } from "./models/GameMove";
|
2022-05-15 02:01:51 +03:00
|
|
|
import PitAnimator from "./animation/PitAnimator";
|
|
|
|
|
import BoardViewModel from "./viewmodel/BoardViewModel";
|
2022-05-12 23:41:24 +03:00
|
|
|
|
|
|
|
|
type ConnectionState = "connecting" | "error" | "connected" | "reconnecting";
|
2021-07-02 23:13:38 +03:00
|
|
|
|
2021-06-29 03:29:46 +03:00
|
|
|
const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
|
|
|
|
|
const [userKey, setUserKey] = useState(undefined);
|
|
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
const [connectionState, setConnetionState] =
|
|
|
|
|
useState<ConnectionState>("connecting");
|
2021-06-30 19:41:53 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
const [searchingOpponent, setSearchingOpponent] = useState<boolean>(false);
|
2021-07-04 01:23:10 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
const [game, setGame] = useState<CommonMancalaGame>(undefined);
|
2021-07-04 01:04:59 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
const [crashMessage, setCrashMessage] = useState<string>(undefined);
|
2021-07-04 00:45:00 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
const [userKeyWhoLeave, setUserKeyWhoLeave] = useState<string>(undefined);
|
|
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
const [boardViewModel, setBoardViewModel] = useState<BoardViewModel>(null);
|
2022-05-12 23:41:24 +03:00
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
const [boardId, setBoardId] = useState<string>();
|
2022-05-12 23:41:24 +03:00
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
const [pitAnimator, setPitAnimator] = useState<PitAnimator>();
|
2021-07-04 01:04:59 +03:00
|
|
|
|
2021-07-02 23:13:38 +03:00
|
|
|
const onConnectionDone = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
setConnetionState("connected");
|
|
|
|
|
};
|
2021-07-02 23:13:38 +03:00
|
|
|
|
|
|
|
|
const onConnectionLost = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
connectToServer("reconnecting");
|
|
|
|
|
};
|
2021-06-30 19:41:53 +03:00
|
|
|
|
2021-07-02 23:13:38 +03:00
|
|
|
const onConnectionError = (event: Event) => {
|
2022-05-12 23:41:24 +03:00
|
|
|
setConnetionState("error");
|
|
|
|
|
};
|
2021-07-02 23:13:38 +03:00
|
|
|
|
|
|
|
|
const connectToServer = (connectionState: ConnectionState) => {
|
2022-05-12 23:41:24 +03:00
|
|
|
setConnetionState(connectionState);
|
2021-06-29 03:29:46 +03:00
|
|
|
context.userKeyStore.getUserKey((userKey: string) => {
|
2022-05-12 23:41:24 +03:00
|
|
|
setUserKey(userKey);
|
|
|
|
|
const rtmtws = context.rtmt as RTMTWS;
|
2021-06-29 03:29:46 +03:00
|
|
|
if (rtmtws) {
|
2022-05-12 23:41:24 +03:00
|
|
|
rtmtws.initWebSocket(
|
|
|
|
|
userKey,
|
|
|
|
|
onConnectionDone,
|
|
|
|
|
onConnectionLost,
|
|
|
|
|
onConnectionError
|
|
|
|
|
);
|
2021-06-29 03:29:46 +03:00
|
|
|
} else {
|
2022-05-04 23:41:04 +03:00
|
|
|
console.error("context.rtmt is not RTMTWS");
|
2021-06-29 03:29:46 +03:00
|
|
|
}
|
2022-05-12 23:41:24 +03:00
|
|
|
});
|
|
|
|
|
};
|
2021-06-29 03:29:46 +03:00
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
const listenMessages = (pitAnimator: PitAnimator) => {
|
2022-05-15 02:06:09 +03:00
|
|
|
context.rtmt.listenMessage(channel_on_game_start, (message: Object) => {
|
2022-05-04 23:41:04 +03:00
|
|
|
const newGame: CommonMancalaGame = message as CommonMancalaGame;
|
2022-05-12 23:41:24 +03:00
|
|
|
const mancalaGame = MancalaGame.createFromMancalaGame(newGame);
|
2022-05-15 02:01:51 +03:00
|
|
|
setSearchingOpponent(false);
|
|
|
|
|
setGame(mancalaGame);
|
|
|
|
|
pitAnimator.setNewGame(mancalaGame);
|
2022-05-12 23:41:24 +03:00
|
|
|
});
|
2021-06-27 19:28:55 +03:00
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
context.rtmt.listenMessage(channel_on_game_update, (message: Object) => {
|
2022-05-04 23:41:04 +03:00
|
|
|
const newGame: CommonMancalaGame = message as CommonMancalaGame;
|
2022-05-15 02:01:51 +03:00
|
|
|
const mancalaGame = MancalaGame.createFromMancalaGame(newGame);
|
|
|
|
|
setGame(mancalaGame);
|
|
|
|
|
pitAnimator.setUpdatedGame(mancalaGame);
|
2022-05-12 23:41:24 +03:00
|
|
|
});
|
2021-07-04 00:45:00 +03:00
|
|
|
|
2022-05-15 02:06:09 +03:00
|
|
|
context.rtmt.listenMessage(channel_on_game_crashed, (message: any) => {
|
2022-05-12 23:41:24 +03:00
|
|
|
const newCrashMessage = message as string;
|
2022-05-04 23:41:04 +03:00
|
|
|
console.error("on_game_crash");
|
|
|
|
|
console.error(newCrashMessage);
|
2022-05-12 23:41:24 +03:00
|
|
|
setCrashMessage(newCrashMessage);
|
|
|
|
|
});
|
2021-07-04 01:04:59 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
context.rtmt.listenMessage(channel_on_game_user_leave, (message: any) => {
|
2022-04-23 12:53:08 +03:00
|
|
|
const userKeyWhoLeave = message;
|
2022-05-12 23:41:24 +03:00
|
|
|
setUserKeyWhoLeave(userKeyWhoLeave);
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-06-27 19:28:55 +03:00
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
const updateBoardViewModel = (boardViewModel: BoardViewModel) => {
|
|
|
|
|
setBoardId(boardViewModel.id);
|
|
|
|
|
setBoardViewModel(boardViewModel);
|
|
|
|
|
};
|
|
|
|
|
|
2021-07-02 23:13:38 +03:00
|
|
|
React.useEffect(() => {
|
2022-05-15 02:01:51 +03:00
|
|
|
const pitAnimator = new PitAnimator(context, updateBoardViewModel);
|
|
|
|
|
setPitAnimator(pitAnimator);
|
|
|
|
|
listenMessages(pitAnimator);
|
2022-05-12 23:41:24 +03:00
|
|
|
connectToServer("connecting");
|
2022-05-15 02:01:51 +03:00
|
|
|
return () => {
|
|
|
|
|
pitAnimator.dispose();
|
|
|
|
|
};
|
2022-05-12 23:41:24 +03:00
|
|
|
}, []);
|
2021-07-02 23:13:38 +03:00
|
|
|
|
2021-07-04 01:04:59 +03:00
|
|
|
const resetGameState = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
setGame(undefined);
|
|
|
|
|
setCrashMessage(undefined);
|
|
|
|
|
setUserKeyWhoLeave(undefined);
|
|
|
|
|
};
|
2021-07-04 01:04:59 +03:00
|
|
|
|
2021-07-02 23:13:38 +03:00
|
|
|
const newGameClick = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
resetGameState();
|
|
|
|
|
setSearchingOpponent(true);
|
|
|
|
|
context.rtmt.sendMessage("new_game", {});
|
|
|
|
|
};
|
2021-07-02 23:13:38 +03:00
|
|
|
|
2021-06-29 03:29:46 +03:00
|
|
|
const leaveGame = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
context.rtmt.sendMessage(channel_leave_game, {});
|
|
|
|
|
};
|
2021-06-29 03:29:46 +03:00
|
|
|
|
2022-05-15 02:01:51 +03:00
|
|
|
const onHoleSelect = (index: number, pit: Pit) => {
|
|
|
|
|
//TODO : stoneCount comes from view model!
|
|
|
|
|
if (pit.stoneCount === 0) {
|
|
|
|
|
//TODO : warn user
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-05-12 23:41:24 +03:00
|
|
|
const gameMove: GameMove = { index: index };
|
|
|
|
|
context.rtmt.sendMessage(channel_game_move, gameMove);
|
|
|
|
|
};
|
2021-06-29 03:29:46 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
const showConnectionState = connectionState != "connected";
|
2021-07-02 23:13:38 +03:00
|
|
|
|
|
|
|
|
const connectionStateText = () => {
|
|
|
|
|
let map: { [key: string]: string } = {
|
2022-05-12 23:41:24 +03:00
|
|
|
connecting: context.texts.Connecting,
|
|
|
|
|
connected: context.texts.Connected,
|
|
|
|
|
error: context.texts.CannotConnect,
|
|
|
|
|
reconnecting: context.texts.ConnectingAgain,
|
2021-07-02 23:13:38 +03:00
|
|
|
};
|
|
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
return map[connectionState];
|
|
|
|
|
};
|
2021-07-02 23:13:38 +03:00
|
|
|
|
2021-07-04 00:45:00 +03:00
|
|
|
const renderNewGameButton = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
const newGame = (
|
|
|
|
|
<Button
|
|
|
|
|
text={context.texts.NewGame}
|
|
|
|
|
color="#005f73"
|
|
|
|
|
onClick={newGameClick}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2021-07-04 01:04:59 +03:00
|
|
|
if (userKeyWhoLeave) {
|
2022-05-12 23:41:24 +03:00
|
|
|
return newGame;
|
2021-07-04 01:04:59 +03:00
|
|
|
}
|
2021-07-04 00:45:00 +03:00
|
|
|
if (crashMessage) {
|
2022-05-12 23:41:24 +03:00
|
|
|
return newGame;
|
2021-07-04 00:45:00 +03:00
|
|
|
}
|
|
|
|
|
if (!game) {
|
2022-05-12 23:41:24 +03:00
|
|
|
return newGame;
|
2021-07-04 00:45:00 +03:00
|
|
|
} else if (game.state == "ended") {
|
2022-05-12 23:41:24 +03:00
|
|
|
return newGame;
|
2021-07-04 00:45:00 +03:00
|
|
|
}
|
2022-05-12 23:41:24 +03:00
|
|
|
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 ",
|
|
|
|
|
borderTopRightRadius: "1vw",
|
|
|
|
|
minWidth: "10vw",
|
|
|
|
|
minHeight: "1vw",
|
|
|
|
|
background: "#2F2504",
|
|
|
|
|
color: "white",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{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 &&
|
|
|
|
|
!crashMessage &&
|
|
|
|
|
(game?.state === "playing" || game?.state === "initial") && (
|
|
|
|
|
<Button
|
|
|
|
|
color="#005f73"
|
|
|
|
|
text={context.texts.Leave}
|
|
|
|
|
onClick={leaveGame}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2021-07-04 00:45:00 +03:00
|
|
|
</div>
|
2022-05-12 23:41:24 +03:00
|
|
|
<InfoPanel
|
|
|
|
|
game={game}
|
|
|
|
|
crashMessage={crashMessage}
|
|
|
|
|
userKey={userKey}
|
|
|
|
|
userKeyWhoLeave={userKeyWhoLeave}
|
|
|
|
|
searchingOpponent={searchingOpponent}
|
|
|
|
|
/>
|
2022-05-15 02:01:51 +03:00
|
|
|
{game && boardViewModel && (
|
2022-05-12 23:41:24 +03:00
|
|
|
<BoardView
|
|
|
|
|
userKey={userKey}
|
|
|
|
|
game={game}
|
2022-05-15 02:01:51 +03:00
|
|
|
boardId={boardId}
|
|
|
|
|
boardViewModel={boardViewModel}
|
|
|
|
|
context={context}
|
2022-05-12 23:41:24 +03:00
|
|
|
onHoleSelect={onHoleSelect}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-07-04 00:45:00 +03:00
|
|
|
</div>
|
2022-05-12 23:41:24 +03:00
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Home;
|