feature: spectator
This commit is contained in:
parent
419ae7600a
commit
c73333667d
@ -2,70 +2,83 @@ import * as React from "react";
|
||||
import { FunctionComponent } from "react";
|
||||
import { Context } from "../context/context";
|
||||
import { Game } from "../models/Game";
|
||||
import { User } from "../models/User";
|
||||
import { getColorByBrightness } from "../util/ColorUtil";
|
||||
import CircularPanel from "./CircularPanel";
|
||||
|
||||
function getInfoPanelTextByGameState(params: {
|
||||
context: Context;
|
||||
game?: Game;
|
||||
crashMessage?: string;
|
||||
userKey?: string;
|
||||
userKeyWhoLeave?: string;
|
||||
currentUser: User;
|
||||
whitePlayer: User;
|
||||
blackPlayer: User;
|
||||
leftPlayer?: User;
|
||||
isSpectator?: boolean;
|
||||
}): string | undefined {
|
||||
const {
|
||||
context,
|
||||
game,
|
||||
crashMessage,
|
||||
userKey,
|
||||
userKeyWhoLeave,
|
||||
currentUser,
|
||||
whitePlayer,
|
||||
blackPlayer,
|
||||
leftPlayer,
|
||||
isSpectator
|
||||
} = params;
|
||||
if (crashMessage) {
|
||||
return context.texts.GameCrashed + " " + crashMessage;
|
||||
} else if (userKeyWhoLeave) {
|
||||
let message = context.texts.OpponentLeavesTheGame;
|
||||
if (userKeyWhoLeave == userKey) {
|
||||
message = context.texts.YouLeftTheGame;
|
||||
}
|
||||
return message;
|
||||
} else if (game?.mancalaGame.state == "ended") {
|
||||
const wonPlayer = game.mancalaGame.getWonPlayerId();
|
||||
let whoWon =
|
||||
game.mancalaGame.getWonPlayerId() === userKey
|
||||
? context.texts.YouWon
|
||||
: context.texts.YouLost;
|
||||
if (!wonPlayer) {
|
||||
|
||||
if (leftPlayer) {
|
||||
return isSpectator ? `${leftPlayer.name} ${context.texts.UserLeftTheGame}` :
|
||||
leftPlayer.id == currentUser.id ? context.texts.YouLeftTheGame : context.texts.OpponentLeftTheGame;
|
||||
}
|
||||
|
||||
const isGameEnded = game?.mancalaGame.state == "ended";
|
||||
if (isGameEnded) {
|
||||
const wonPlayerID = game.mancalaGame.getWonPlayerId();
|
||||
const wonPlayer = wonPlayerID == whitePlayer.id ? whitePlayer : blackPlayer;
|
||||
let whoWon;
|
||||
if (wonPlayer) {
|
||||
whoWon = isSpectator ? `${wonPlayer.name} ${context.texts.Won}` :
|
||||
game.mancalaGame.getWonPlayerId() === currentUser.id
|
||||
? context.texts.YouWon
|
||||
: context.texts.YouLost;
|
||||
} else {
|
||||
whoWon = context.texts.GameDraw;
|
||||
}
|
||||
return context.texts.GameEnded + " " + whoWon;
|
||||
} else {
|
||||
if (game) {
|
||||
return userKey ? game.mancalaGame.checkIsPlayerTurn(userKey)
|
||||
? context.texts.YourTurn
|
||||
: context.texts.OpponentTurn : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (game) {
|
||||
const playingPlayer = game.mancalaGame.checkIsPlayerTurn(whitePlayer.id) ? whitePlayer : blackPlayer;
|
||||
return isSpectator ? `${playingPlayer.name} ${context.texts.Playing}` : game.mancalaGame.checkIsPlayerTurn(currentUser.id)
|
||||
? context.texts.YourTurn
|
||||
: context.texts.OpponentTurn;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const InfoPanel: FunctionComponent<{
|
||||
context: Context;
|
||||
game?: Game;
|
||||
crashMessage?: string;
|
||||
userKey?: string;
|
||||
userKeyWhoLeave?: string;
|
||||
currentUser: User;
|
||||
whitePlayer: User;
|
||||
blackPlayer: User;
|
||||
leftPlayer?: User;
|
||||
style?: React.CSSProperties;
|
||||
visible?: boolean;
|
||||
isSpectator?: boolean;
|
||||
}> = ({
|
||||
context,
|
||||
game,
|
||||
crashMessage,
|
||||
userKey,
|
||||
userKeyWhoLeave,
|
||||
currentUser,
|
||||
whitePlayer,
|
||||
blackPlayer,
|
||||
leftPlayer,
|
||||
style,
|
||||
visible
|
||||
visible,
|
||||
isSpectator
|
||||
}) => {
|
||||
if (visible === false) return <></>;
|
||||
const isUserTurn = userKey ? game?.mancalaGame.checkIsPlayerTurn(userKey) : false;
|
||||
const isUserTurn = currentUser.id ? game?.mancalaGame.checkIsPlayerTurn(currentUser.id) : false;
|
||||
const containerColor = isUserTurn
|
||||
? context.themeManager.theme.playerTurnColor
|
||||
: context.themeManager.theme.boardColor;
|
||||
@ -77,9 +90,11 @@ const InfoPanel: FunctionComponent<{
|
||||
const text = getInfoPanelTextByGameState({
|
||||
context,
|
||||
game,
|
||||
crashMessage,
|
||||
userKey,
|
||||
userKeyWhoLeave
|
||||
currentUser,
|
||||
whitePlayer,
|
||||
blackPlayer,
|
||||
leftPlayer,
|
||||
isSpectator
|
||||
});
|
||||
if (text) {
|
||||
return (
|
||||
|
||||
@ -39,8 +39,6 @@ const GamePage: FunctionComponent<{
|
||||
|
||||
const [game, setGame] = useState<Game | undefined>(undefined);
|
||||
|
||||
const [crashMessage, setCrashMessage] = useState<string | undefined>(undefined);
|
||||
|
||||
const [userKeyWhoLeave, setUserKeyWhoLeave] = useState<string | undefined>(undefined);
|
||||
|
||||
const [boardViewModel, setBoardViewModel] = useState<BoardViewModel | undefined>(undefined);
|
||||
@ -93,7 +91,6 @@ const GamePage: FunctionComponent<{
|
||||
const newCrashMessage = message as string;
|
||||
console.error("on_game_crash");
|
||||
console.error(newCrashMessage);
|
||||
setCrashMessage(newCrashMessage);
|
||||
}
|
||||
const onGameUserLeave = (message: any) => {
|
||||
const userKeyWhoLeave = message;
|
||||
@ -107,17 +104,17 @@ const GamePage: FunctionComponent<{
|
||||
|
||||
const listenMessages = (game: Game, pitAnimator: PitAnimator): () => void => {
|
||||
const _onGameUpdate = (message: object) => onGameUpdateEvent(pitAnimator, message);
|
||||
context.rtmt.listenMessage(channel_on_game_update, _onGameUpdate);
|
||||
context.rtmt.listenMessage(channel_on_game_crashed, onGameCrashed);
|
||||
context.rtmt.listenMessage(channel_on_game_user_leave, onGameUserLeave);
|
||||
context.rtmt.listenMessage(channel_on_user_connection_change, onUserConnectionChange);
|
||||
context.rtmt.addMessageListener(channel_on_game_update, _onGameUpdate);
|
||||
context.rtmt.addMessageListener(channel_on_game_crashed, onGameCrashed);
|
||||
context.rtmt.addMessageListener(channel_on_game_user_leave, onGameUserLeave);
|
||||
context.rtmt.addMessageListener(channel_on_user_connection_change, onUserConnectionChange);
|
||||
checkIsSpectator(game) && userKey && context.rtmt.sendMessage(channel_listen_game_events, game.id);
|
||||
return () => {
|
||||
checkIsSpectator(game) && userKey && context.rtmt.sendMessage(channel_unlisten_game_events, game.id);
|
||||
context.rtmt.unlistenMessage(channel_on_game_update, _onGameUpdate);
|
||||
context.rtmt.unlistenMessage(channel_on_game_crashed, onGameCrashed);
|
||||
context.rtmt.unlistenMessage(channel_on_game_user_leave, onGameUserLeave);
|
||||
context.rtmt.unlistenMessage(channel_on_user_connection_change, onUserConnectionChange);
|
||||
context.rtmt.removeMessageListener(channel_on_game_update, _onGameUpdate);
|
||||
context.rtmt.removeMessageListener(channel_on_game_crashed, onGameCrashed);
|
||||
context.rtmt.removeMessageListener(channel_on_game_user_leave, onGameUserLeave);
|
||||
context.rtmt.removeMessageListener(channel_on_user_connection_change, onUserConnectionChange);
|
||||
}
|
||||
};
|
||||
|
||||
@ -198,63 +195,36 @@ const GamePage: FunctionComponent<{
|
||||
context.themeManager.theme.textColor,
|
||||
context.themeManager.theme.textLightColor
|
||||
);
|
||||
const renderNewGameBtn = userKeyWhoLeave || !game || (game && game.mancalaGame.state == "ended");
|
||||
const showBoardView = game && boardViewModel && userKey && true;
|
||||
const opponentId = getOpponentId();
|
||||
const opponentUser = { id: getOpponentId() || "0", name: "Anonymous", isOnline: opponentId ? isUserOnline(opponentId) : false, isAnonymous: true };
|
||||
const user = { id: userKey || "1", name: "Anonymous", isOnline: connectionState === "connected", isAnonymous: true };
|
||||
|
||||
const isMobile = width < 600;
|
||||
|
||||
const renderNewGameBtn = isSpectator || (userKeyWhoLeave || !game || (game && game.mancalaGame.state == "ended"));
|
||||
const showBoardView = game && boardViewModel && userKey && true;
|
||||
const topLocatedUserId = (isSpectator ? mancalaGame?.player2Id : getOpponentId()) || "0";
|
||||
const bottomLocatedUserId = (isSpectator ? mancalaGame?.player1Id : userKey) || "1";
|
||||
const topLocatedUser = {
|
||||
id: topLocatedUserId,
|
||||
name: "Anonymous",
|
||||
isOnline: isUserOnline(topLocatedUserId),
|
||||
isAnonymous: true
|
||||
};
|
||||
const bottomLocatedUser = {
|
||||
id: bottomLocatedUserId,
|
||||
name: "Anonymous",
|
||||
isOnline: isSpectator ? isUserOnline(bottomLocatedUserId) : connectionState === "connected",
|
||||
isAnonymous: true
|
||||
};
|
||||
const currentUser = isSpectator ? {
|
||||
id: "2",
|
||||
name: "Anonymous",
|
||||
isOnline: connectionState === "connected",
|
||||
isAnonymous: true
|
||||
} : bottomLocatedUser;
|
||||
const leftPlayer = userKeyWhoLeave ? (userKeyWhoLeave === topLocatedUser.id ? topLocatedUser : bottomLocatedUser) : undefined;
|
||||
return (
|
||||
<PageContainer theme={theme!}>
|
||||
<HeaderBar color={theme?.appBarBgColor}>
|
||||
<Row>
|
||||
<Link style={{ textDecoration: 'none' }} to={"/"}>
|
||||
<HeaderbarIcon />
|
||||
</Link>
|
||||
<Link style={{ textDecoration: 'none' }} to={"/"}>
|
||||
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
|
||||
</Link>
|
||||
</Row>
|
||||
<Row>
|
||||
<ThemeSwitchMenu context={context} textColor={textColorOnAppBar} />
|
||||
<Button
|
||||
context={context}
|
||||
color={context.themeManager.theme.pitColor}
|
||||
text={renderNewGameBtn ? context.texts.NewGame : context.texts.Leave}
|
||||
onClick={renderNewGameBtn ? onNewGameClick : onLeaveGameClick} />
|
||||
</Row>
|
||||
</HeaderBar>
|
||||
<BoardToolbar style={{ justifyContent: "center" }} visible={showBoardView && isMobile || false}>
|
||||
<InfoPanel
|
||||
style={{ marginTop: "0.5rem", marginBottom: "0.5rem" }}
|
||||
context={context}
|
||||
game={game}
|
||||
crashMessage={crashMessage}
|
||||
userKey={userKey}
|
||||
userKeyWhoLeave={userKeyWhoLeave} />
|
||||
</BoardToolbar>
|
||||
<BoardToolbar style={{ alignItems: "flex-end" }} visible={showBoardView || false}>
|
||||
<UserStatus style={{
|
||||
marginBottom: "0.5rem", marginLeft: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
||||
width: isMobile ? "40vw" : "30vw"
|
||||
}} context={context} layoutMode="left" user={opponentUser} visible={showBoardView || false} />
|
||||
<InfoPanel
|
||||
style={{
|
||||
marginTop: "0.5rem", marginBottom: "0.5rem",
|
||||
}}
|
||||
context={context}
|
||||
game={game}
|
||||
crashMessage={crashMessage}
|
||||
userKey={userKey}
|
||||
userKeyWhoLeave={userKeyWhoLeave}
|
||||
visible={!isMobile} />
|
||||
<UserStatus style={{
|
||||
marginBottom: "0.5rem", marginRight: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
||||
width: isMobile ? "40vw" : "30vw"
|
||||
}} context={context} layoutMode="right" user={user} visible={showBoardView || false} />
|
||||
</BoardToolbar>
|
||||
{renderHeaderBar()}
|
||||
{renderMobileBoardToolbar()}
|
||||
{buildBoardTopToolbar()}
|
||||
{showBoardView && (
|
||||
<BoardView
|
||||
game={game}
|
||||
@ -269,6 +239,63 @@ const GamePage: FunctionComponent<{
|
||||
</Center>
|
||||
</PageContainer>
|
||||
);
|
||||
|
||||
function renderHeaderBar() {
|
||||
return <HeaderBar color={theme?.appBarBgColor}>
|
||||
<Row>
|
||||
<Link style={{ textDecoration: 'none' }} to={"/"}>
|
||||
<HeaderbarIcon />
|
||||
</Link>
|
||||
<Link style={{ textDecoration: 'none' }} to={"/"}>
|
||||
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
|
||||
</Link>
|
||||
</Row>
|
||||
<Row>
|
||||
<ThemeSwitchMenu context={context} textColor={textColorOnAppBar} />
|
||||
<Button
|
||||
context={context}
|
||||
color={context.themeManager.theme.pitColor}
|
||||
text={renderNewGameBtn ? context.texts.NewGame : context.texts.Leave}
|
||||
onClick={renderNewGameBtn ? onNewGameClick : onLeaveGameClick} />
|
||||
</Row>
|
||||
</HeaderBar>;
|
||||
}
|
||||
|
||||
function renderMobileBoardToolbar() {
|
||||
return <BoardToolbar style={{ justifyContent: "center" }} visible={showBoardView && isMobile || false}>
|
||||
{buildInfoPanel()}
|
||||
</BoardToolbar>;
|
||||
}
|
||||
|
||||
function buildBoardTopToolbar() {
|
||||
return <BoardToolbar style={{ alignItems: "flex-end" }} visible={showBoardView || false}>
|
||||
<UserStatus style={{
|
||||
marginBottom: "0.5rem", marginLeft: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
||||
width: isMobile ? "40vw" : "30vw"
|
||||
}} context={context} layoutMode="left" user={topLocatedUser} visible={showBoardView || false} />
|
||||
{buildInfoPanel()}
|
||||
<UserStatus style={{
|
||||
marginBottom: "0.5rem", marginRight: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
||||
width: isMobile ? "40vw" : "30vw"
|
||||
}} context={context} layoutMode="right" user={bottomLocatedUser} visible={showBoardView || false} />
|
||||
</BoardToolbar>;
|
||||
}
|
||||
|
||||
function buildInfoPanel() {
|
||||
return (
|
||||
<InfoPanel
|
||||
style={{ marginTop: "0.5rem", marginBottom: "0.5rem" }}
|
||||
context={context}
|
||||
game={game}
|
||||
currentUser={currentUser}
|
||||
whitePlayer={topLocatedUser}
|
||||
blackPlayer={bottomLocatedUser}
|
||||
leftPlayer={leftPlayer}
|
||||
visible={!isMobile}
|
||||
isSpectator={isSpectator} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GamePage;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user