From 00c697c9aebff564f71074995c165bc0a1fa950d Mon Sep 17 00:00:00 2001 From: Salvo Miosi Date: Sat, 7 Sep 2024 18:47:40 +0200 Subject: [PATCH] add ui for spectators --- src/Components/Header.tsx | 5 +++++ src/Locale/English/Labels.ts | 2 ++ src/Locale/Italian/Labels.ts | 2 ++ src/Model/ClientMessage.ts | 3 ++- src/Model/ServerMessage.ts | 3 +++ src/Model/UseBangConnection.ts | 6 +++--- src/Scenes/Game/GameUsersView.tsx | 5 ++--- src/Scenes/Lobby/LobbyUser.tsx | 7 +++++-- 8 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/Components/Header.tsx b/src/Components/Header.tsx index 9c0ecd3f..5b6d1d32 100644 --- a/src/Components/Header.tsx +++ b/src/Components/Header.tsx @@ -7,6 +7,7 @@ import { DEFAULT_USER_PROPIC } from '../Scenes/Lobby/LobbyUser'; import { ImageSrc } from '../Utils/ImageSerial'; import useCloseOnLoseFocus from '../Utils/UseCloseOnLoseFocus'; import UserMenu, { UserMenuItem } from './UserMenu'; +import { getUser } from '../Scenes/Lobby/Lobby'; export interface HeaderProps { scene: SceneState; @@ -30,6 +31,9 @@ function Header({ scene, settings, connection }: HeaderProps) { const handleLeaveLobby = () => connection.sendMessage({ lobby_leave: {}}); const handleReturnLobby = () => connection.sendMessage({ lobby_return: {}}); + const isSpectator = 'lobbyState' in scene && getUser(scene.lobbyState.users, scene.lobbyState.myUserId)?.team === 'game_spectator'; + const handleToggleSpectate = () => connection.sendMessage({ user_set_team: isSpectator ? 'game_player' : 'game_spectator' }); + const handleDisconnect = () => { settings.setSessionId(undefined); connection.disconnect(); @@ -83,6 +87,7 @@ function Header({ scene, settings, connection }: HeaderProps) { handleEditUser(username, settings.propic)}> {getLabel('ui', settings.muteSounds ? 'BUTTON_ENABLE_SOUNDS' : 'BUTTON_DISABLE_SOUNDS')} { scene.type === 'game' && isLobbyOwner(scene.lobbyState) && {getLabel('ui', 'BUTTON_RETURN_LOBBY')}} + { scene.type === 'lobby' && {getLabel('ui', isSpectator ? 'BUTTON_SPECTATE_OFF' : 'BUTTON_SPECTATE_ON')} } { 'lobbyInfo' in scene ? {getLabel('ui', 'BUTTON_LEAVE_LOBBY')} : {getLabel('ui', 'BUTTON_DISCONNECT')} } diff --git a/src/Locale/English/Labels.ts b/src/Locale/English/Labels.ts index a9bfb946..3f2a6e4a 100644 --- a/src/Locale/English/Labels.ts +++ b/src/Locale/English/Labels.ts @@ -72,6 +72,8 @@ export const LABELS_ENGLISH: LabelRegistry = { GAME_OPTIONS: "Game Options", BUTTON_CHAT_SEND: "Send", BUTTON_START_GAME: "Start Game", + BUTTON_SPECTATE_ON: "Join as spectator", + BUTTON_SPECTATE_OFF: "Join as player", BUTTON_ENABLE_SOUNDS: "Enable Sounds", BUTTON_DISABLE_SOUNDS: "Disable Sounds", BUTTON_RETURN_LOBBY: "Return to Lobby", diff --git a/src/Locale/Italian/Labels.ts b/src/Locale/Italian/Labels.ts index d23e0e18..14da2c76 100644 --- a/src/Locale/Italian/Labels.ts +++ b/src/Locale/Italian/Labels.ts @@ -72,6 +72,8 @@ export const LABELS_ITALIAN: LabelRegistry = { GAME_OPTIONS: "Opzioni di Partita", BUTTON_CHAT_SEND: "Invia", BUTTON_START_GAME: "Avvia Partita", + BUTTON_SPECTATE_ON: "Unisciti come spettatore", + BUTTON_SPECTATE_OFF: "Unisciti come giocatore", BUTTON_ENABLE_SOUNDS: "Abilita Souni", BUTTON_DISABLE_SOUNDS: "Disabilita Suoni", BUTTON_RETURN_LOBBY: "Ritorna alla Lobby", diff --git a/src/Model/ClientMessage.ts b/src/Model/ClientMessage.ts index babe76f0..9e3ff80a 100644 --- a/src/Model/ClientMessage.ts +++ b/src/Model/ClientMessage.ts @@ -1,6 +1,6 @@ import { GameAction } from "../Scenes/Game/Model/GameAction"; import { GameOptions } from "../Scenes/Game/Model/GameUpdate"; -import { Empty, LobbyId, LobbyInfo, UserId, UserInfo } from "./ServerMessage"; +import { Empty, LobbyId, LobbyInfo, LobbyTeam, UserId, UserInfo } from "./ServerMessage"; export interface ClientConnect { user: UserInfo; @@ -22,6 +22,7 @@ export type ClientMessage = {lobby_leave: Empty } | {lobby_chat: { message: string }} | {lobby_return: Empty } | + {user_set_team: LobbyTeam} | {game_start: Empty } | {game_rejoin: { user_id: UserId }} | {game_action: GameAction}; \ No newline at end of file diff --git a/src/Model/ServerMessage.ts b/src/Model/ServerMessage.ts index c25ac4ff..a2aaa443 100644 --- a/src/Model/ServerMessage.ts +++ b/src/Model/ServerMessage.ts @@ -13,6 +13,8 @@ export interface ClientAccepted { export type LobbyStateEnum = 'waiting' | 'playing' | 'finished'; +export type LobbyTeam = 'game_player' | 'game_spectator'; + export interface LobbyUpdate { lobby_id: LobbyId; name: string; @@ -50,6 +52,7 @@ export type LobbyChatFlag = 'is_read'; export interface LobbyAddUser { user_id: UserId; user: UserInfo; + team: LobbyTeam; flags: LobbyChatFlag[]; lifetime: Milliseconds; } diff --git a/src/Model/UseBangConnection.ts b/src/Model/UseBangConnection.ts index c5021222..18421e13 100644 --- a/src/Model/UseBangConnection.ts +++ b/src/Model/UseBangConnection.ts @@ -36,12 +36,12 @@ function handleUpdateLobbies({ lobby_id, name, num_players, num_spectators, max_ }; } -function handleLobbyAddUser({ user_id, user: { name, profile_image }, flags, lifetime }: LobbyAddUser): UpdateFunction { +function handleLobbyAddUser({ user_id, user: { name, profile_image }, team, flags, lifetime }: LobbyAddUser): UpdateFunction { return lobbyState => { let chatMessages = lobbyState.chatMessages; - let users = [...lobbyState.users]; + let users = lobbyState.users.slice(); - const newUser: UserValue = { id: user_id, name, propic: deserializeImage(profile_image), lifetime }; + const newUser: UserValue = { id: user_id, name, propic: deserializeImage(profile_image), team, lifetime }; let index = users.findIndex(user => user.id === user_id); if (index >= 0) { users[index] = newUser; diff --git a/src/Scenes/Game/GameUsersView.tsx b/src/Scenes/Game/GameUsersView.tsx index d117684a..4ca78dcc 100644 --- a/src/Scenes/Game/GameUsersView.tsx +++ b/src/Scenes/Game/GameUsersView.tsx @@ -37,10 +37,9 @@ function GameUserPlayer({ player, user, myUserId }: GameUserProps) { return
{ role &&
} { isWinner &&
} - { player ? isPlayerDead(player) && (isPlayerGhost(player) + { player && isPlayerDead(player) && (isPlayerGhost(player) ?
- :
) - :
} + :
) }
; }, [player]); diff --git a/src/Scenes/Lobby/LobbyUser.tsx b/src/Scenes/Lobby/LobbyUser.tsx index d2758552..ae66d4e1 100644 --- a/src/Scenes/Lobby/LobbyUser.tsx +++ b/src/Scenes/Lobby/LobbyUser.tsx @@ -1,6 +1,6 @@ import { ReactNode } from "react"; import getLabel from "../../Locale/GetLabel"; -import { Milliseconds, UserId } from "../../Model/ServerMessage"; +import { LobbyTeam, Milliseconds, UserId } from "../../Model/ServerMessage"; import { ImageSrc } from "../../Utils/ImageSerial"; import "./Style/LobbyUser.css"; import defaultUserPropic from "/media/icon_default_user.png"; @@ -11,6 +11,7 @@ export interface UserValue { id: UserId; name: string; propic?: ImageSrc; + team: LobbyTeam; lifetime: Milliseconds; } @@ -45,7 +46,9 @@ export default function LobbyUser({ isSelf, user, align, children }: LobbyUserPr
- {getUsername(user)}{timerWidget} + {getUsername(user)} + {user?.team === 'game_spectator' &&
} + {timerWidget}
{children}