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 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-22 17:57:33 +03:00
|
|
|
import { v4 } from "uuid";
|
2022-07-13 15:18:13 +03:00
|
|
|
import { getColorByBrightness } from "./util/ColorUtil";
|
2022-07-09 08:31:43 +03:00
|
|
|
import { Theme } from "./theme/Theme";
|
2022-07-13 22:39:01 +03:00
|
|
|
import HeaderBar from "./components/HeaderBar";
|
|
|
|
|
import FloatingPanel from "./components/FloatingPanel";
|
|
|
|
|
import PageContainer from "./components/PageContainer";
|
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
|
|
|
|
2022-07-09 08:31:43 +03:00
|
|
|
const [theme, setTheme] = useState<Theme | undefined>(undefined);
|
|
|
|
|
|
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) => {
|
2022-05-22 17:57:33 +03:00
|
|
|
boardViewModel.id = v4();
|
2022-05-15 02:01:51 +03:00
|
|
|
setBoardId(boardViewModel.id);
|
|
|
|
|
setBoardViewModel(boardViewModel);
|
|
|
|
|
};
|
|
|
|
|
|
2022-07-13 22:39:01 +03:00
|
|
|
const resetGameState = () => {
|
|
|
|
|
setGame(undefined);
|
|
|
|
|
setCrashMessage(undefined);
|
|
|
|
|
setUserKeyWhoLeave(undefined);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getBoardIndex = (index: number) => {
|
|
|
|
|
if (userKey === game.player2Id) return index + game.board.pits.length / 2;
|
|
|
|
|
return index;
|
|
|
|
|
};
|
|
|
|
|
|
2021-07-02 23:13:38 +03:00
|
|
|
React.useEffect(() => {
|
2022-07-09 08:31:43 +03:00
|
|
|
setTheme(context.themeManager.theme);
|
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
|
|
|
|
2022-06-04 20:54:19 +03:00
|
|
|
React.useEffect(() => {
|
2022-07-09 08:31:43 +03:00
|
|
|
context.themeManager.onThemeChange = (theme) => {
|
|
|
|
|
setTheme(theme);
|
|
|
|
|
pitAnimator && updateBoardViewModel(pitAnimator.getBoardViewModelFromGame(game));
|
2022-06-04 20:54:19 +03:00
|
|
|
};
|
|
|
|
|
}, [boardViewModel]);
|
|
|
|
|
|
2022-07-13 22:39:01 +03:00
|
|
|
const onNewGameClick = () => {
|
2022-05-12 23:41:24 +03:00
|
|
|
resetGameState();
|
|
|
|
|
setSearchingOpponent(true);
|
|
|
|
|
context.rtmt.sendMessage("new_game", {});
|
|
|
|
|
};
|
2021-07-02 23:13:38 +03:00
|
|
|
|
2022-07-13 22:39:01 +03:00
|
|
|
const onLeaveGameClick = () => {
|
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-22 17:58:11 +03:00
|
|
|
boardViewModel.pits[getBoardIndex(index)].pitColor =
|
|
|
|
|
context.themeManager.theme.pitSelectedColor;
|
|
|
|
|
updateBoardViewModel(boardViewModel);
|
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
|
|
|
|
2022-07-13 22:39:01 +03:00
|
|
|
const textColorOnBoard = getColorByBrightness(
|
|
|
|
|
context.themeManager.theme.boardColor,
|
2022-07-13 15:21:30 +03:00
|
|
|
context.themeManager.theme.textColor,
|
|
|
|
|
context.themeManager.theme.textLightColor
|
2022-06-04 20:54:19 +03:00
|
|
|
);
|
2022-07-13 22:39:01 +03:00
|
|
|
|
2022-05-12 23:41:24 +03:00
|
|
|
return (
|
2022-07-13 22:39:01 +03:00
|
|
|
<PageContainer theme={theme!}>
|
|
|
|
|
<FloatingPanel context={context} color={context.themeManager.theme.boardColor} visible={showConnectionState}>
|
|
|
|
|
<span style={{ color: textColorOnBoard }}>{connectionStateText()}</span>
|
|
|
|
|
</FloatingPanel>
|
|
|
|
|
<HeaderBar
|
|
|
|
|
context={context}
|
|
|
|
|
game={game}
|
|
|
|
|
userKeyWhoLeave={userKeyWhoLeave}
|
|
|
|
|
crashMessage={crashMessage}
|
|
|
|
|
onNewGameClick={onNewGameClick}
|
|
|
|
|
onLeaveGameClick={onLeaveGameClick} />
|
2022-05-12 23:41:24 +03:00
|
|
|
<InfoPanel
|
2022-06-04 14:49:34 +03:00
|
|
|
context={context}
|
2022-05-12 23:41:24 +03:00
|
|
|
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}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2022-07-13 22:39:01 +03:00
|
|
|
</PageContainer>
|
2022-05-12 23:41:24 +03:00
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Home;
|