Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host Settings Menu #767

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion client/src/components/useHooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { StateEventType } from "../game/gameManager.d";
import GameState, { LobbyState, PlayerGameState } from "../game/gameState.d";
import DUMMY_NAMES from "../resources/dummyNames.json";

function usePacketListener(listener: (type?: StateEventType) => void) {
export function usePacketListener(listener: (type?: StateEventType) => void) {
// Catch all the packets we miss between setState and useEffect
const packets: StateEventType[] = [];
const packetQueueListener = (type?: StateEventType) => {
Expand Down
4 changes: 4 additions & 0 deletions client/src/game/gameManager.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ export type GameManager = {
): void

sendVoteFastForwardPhase(fastForward: boolean): void;
sendHostDataRequest(): void;
sendHostEndGamePacket(): void;
sendHostSkipPhase(): void;
sendHostSetPlayerNamePacket(player_id: number, name: string): void;

messageListener(serverMessage: ToClientPacket): void;

Expand Down
30 changes: 29 additions & 1 deletion client/src/game/gameManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import PlayMenu from "../menu/main/PlayMenu";
import { createGameState, createLobbyState } from "./gameState";
import { deleteReconnectData } from "./localStorage";
import AudioController from "../menu/AudioController";
import ListMap from "../ListMap";

export function createGameManager(): GameManager {

Expand Down Expand Up @@ -77,7 +78,11 @@ export function createGameManager(): GameManager {
GAME_MANAGER.state.roleList = lobbyState.roleList;
GAME_MANAGER.state.phaseTimes = lobbyState.phaseTimes;
GAME_MANAGER.state.enabledRoles = lobbyState.enabledRoles;
GAME_MANAGER.state.host = lobbyState.players.get(lobbyState.myId!)?.ready === "host";
if (lobbyState.players.get(lobbyState.myId!)?.ready === "host") {
GAME_MANAGER.state.host = {
clients: new ListMap()
};
}
GAME_MANAGER.state.myId = lobbyState.myId
}
},
Expand Down Expand Up @@ -451,6 +456,29 @@ export function createGameManager(): GameManager {
});
},

sendHostDataRequest() {
this.server.sendPacket({
type: "hostDataRequest"
})
},
sendHostEndGamePacket() {
this.server.sendPacket({
type: "endGame"
})
},
sendHostSkipPhase() {
this.server.sendPacket({
type: "skipPhase"
})
},
sendHostSetPlayerNamePacket(playerId, name) {
this.server.sendPacket({
type: "setPlayerName",
id: playerId,
name
})
},

messageListener(serverMessage) {
messageListener(serverMessage);
},
Expand Down
19 changes: 17 additions & 2 deletions client/src/game/gameState.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,22 @@ export type LobbyState = {
}
export type LobbyClient = {
ready: "host" | "ready" | "notReady",
connection: "connected" | "disconnected" | "couldReconnect",
connection: ClientConnection,
clientType: LobbyClientType
}
export type ClientConnection = "connected" | "disconnected" | "couldReconnect";
export type GameClient = {
clientType: GameClientType,
connection: ClientConnection,
host: boolean,
}
export type GameClientType = {
type: "spectator",
index: number
} | {
type: "player",
index: number,
}
export type LobbyClientType = {
type: "spectator"
} | PlayerClientType;
Expand Down Expand Up @@ -78,7 +91,9 @@ type GameState = {
ticking: boolean,

clientState: PlayerGameState | {type: "spectator"},
host: boolean,
host: null | {
clients: ListMap<LobbyClientID, GameClient>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cant call this game client and then have it only exist if you are the host. Right you just like??? I guess the clients dont need it

This code is not self-explanatory

},

missedChatMessages: boolean
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/game/gameState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function createGameState(): GameState {
ticking: true,

clientState: createPlayerGameState(),
host: false,
host: null,

missedChatMessages: false
}
Expand Down
37 changes: 22 additions & 15 deletions client/src/game/messageListener.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ANCHOR_CONTROLLER, chatMessageToAudio } from "./../menu/Anchor";
import GAME_MANAGER from "./../index";
import GameScreen from "./../menu/game/GameScreen";
import { ToClientPacket } from "./packet";
import { PlayerIndex, Tag } from "./gameState.d";
import { GameClient, PlayerIndex, Tag } from "./gameState.d";
import { Role } from "./roleState.d";
import translate from "./lang";
import { computePlayerKeywordData, computePlayerKeywordDataForLobby } from "../components/StyledText";
Expand All @@ -23,7 +23,6 @@ import { defaultAlibi } from "../menu/game/gameScreenContent/WillMenu";
import ListMap from "../ListMap";
import { sortControllerIdCompare } from "./abilityInput";


function sendDefaultName() {
const defaultName = loadSettingsParsed().defaultName;
if(defaultName !== null && defaultName !== undefined && defaultName !== ""){
Expand All @@ -32,10 +31,8 @@ function sendDefaultName() {
}

export default function messageListener(packet: ToClientPacket){

console.log(JSON.stringify(packet, null, 2));


switch(packet.type) {
case "pong":
if (GAME_MANAGER.state.stateType !== "disconnected") {
Expand Down Expand Up @@ -149,7 +146,19 @@ export default function messageListener(packet: ToClientPacket){
}
GAME_MANAGER.state.players = new ListMap(GAME_MANAGER.state.players.entries());
}else if(GAME_MANAGER.state.stateType === "game"){
GAME_MANAGER.state.host = packet.hosts.includes(GAME_MANAGER.state.myId ?? -1)
if (packet.hosts.includes(GAME_MANAGER.state.myId ?? -1)) {
if (GAME_MANAGER.state.host === null) {
GAME_MANAGER.state.host = {
clients: new ListMap()
}
}

for (const [id, client] of GAME_MANAGER.state.host.clients.entries()) {
client.host = packet.hosts.includes(id);
}
} else {
GAME_MANAGER.state.host = null
}
}
break;
case "playersReady":
Expand Down Expand Up @@ -193,11 +202,10 @@ export default function messageListener(packet: ToClientPacket){
break;
case "lobbyClients":
if(GAME_MANAGER.state.stateType === "lobby"){

const oldMySpectator = GAME_MANAGER.state.players.get(GAME_MANAGER.state.myId!)?.clientType.type === "spectator";

GAME_MANAGER.state.players = new ListMap();
for(let [clientId, lobbyClient] of packet.clients){
for(const [clientId, lobbyClient] of packet.clients){
GAME_MANAGER.state.players.insert(clientId, lobbyClient);
}
const newMySpectator = GAME_MANAGER.state.players.get(GAME_MANAGER.state.myId!)?.clientType.type === "spectator";
Expand All @@ -215,6 +223,13 @@ export default function messageListener(packet: ToClientPacket){
);
}
break;
case "hostData":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crazy

if (GAME_MANAGER.state.stateType === "game") {
GAME_MANAGER.state.host = {
clients: new ListMap<number, GameClient>(packet.clients)
}
}
break;
case "lobbyName":
if(GAME_MANAGER.state.stateType === "lobby" || GAME_MANAGER.state.stateType === "game"){
GAME_MANAGER.state.lobbyName = packet.name;
Expand Down Expand Up @@ -322,14 +337,6 @@ export default function messageListener(packet: ToClientPacket){
if(GAME_MANAGER.state.stateType === "game")
GAME_MANAGER.state.timeLeftMs = packet.secondsLeft * 1000;
break;
case "playerOnTrial":
if(GAME_MANAGER.state.stateType === "game" && (
GAME_MANAGER.state.phaseState.type === "testimony" ||
GAME_MANAGER.state.phaseState.type === "judgement" ||
GAME_MANAGER.state.phaseState.type === "finalWords"
))
GAME_MANAGER.state.phaseState.playerOnTrial = packet.playerIndex;
break;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt be in this PR but whateva

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick

case "playerAlive":
if(GAME_MANAGER.state.stateType === "game"){
for(let i = 0; i < GAME_MANAGER.state.players.length && i < packet.alive.length; i++){
Expand Down
18 changes: 14 additions & 4 deletions client/src/game/packet.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PhaseType, PlayerIndex, Verdict, PhaseTimes, Tag, LobbyClientID, ChatGroup, PhaseState, LobbyClient, ModifierType, InsiderGroup } from "./gameState.d"
import { PhaseType, PlayerIndex, Verdict, PhaseTimes, Tag, LobbyClientID, ChatGroup, PhaseState, LobbyClient, ModifierType, InsiderGroup, GameClient } from "./gameState.d"
import { Grave } from "./graveState"
import { ChatMessage } from "../components/ChatMessage"
import { RoleList, RoleOutline } from "./roleListState.d"
Expand All @@ -16,6 +16,9 @@ export type LobbyPreviewData = {

export type ToClientPacket = {
type: "pong",
} | {
type: "hostData",
clients: ListMapData<LobbyClientID, GameClient>
} | {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wild

type: "rateLimitExceeded",
} | {
Expand Down Expand Up @@ -102,9 +105,6 @@ export type ToClientPacket = {
type: "phaseTimeLeft",
secondsLeft: number
} |{
type: "playerOnTrial",
playerIndex: PlayerIndex
} | {
type: "playerAlive",
alive: [boolean]
} | {
Expand Down Expand Up @@ -178,6 +178,8 @@ export type ToServerPacket = {
type: "ping",
} | {
type: "lobbyListRequest",
} | {
type: "hostDataRequest",
} | {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like

type: "reJoin",
roomCode: number,
Expand Down Expand Up @@ -289,4 +291,12 @@ export type ToServerPacket = {
} | {
type: "voteFastForwardPhase",
fastForward: boolean
} | {
type: "endGame",
} | {
type: "skipPhase",
} | {
type: "setPlayerName",
id: number,
name: string
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name these something more specific? HostForceEndGame
HostForceSkipPhase
HostForceSetPlayerName

14 changes: 10 additions & 4 deletions client/src/menu/GlobalMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Icon from '../components/Icon';
import SettingsMenu from './Settings';
import { useLobbyOrGameState } from '../components/useHooks';
import { Button } from '../components/Button';
import HostMenu from './HostMenu';

export default function GlobalMenu(): ReactElement {
const lobbyName = useLobbyOrGameState(
Expand All @@ -21,7 +22,7 @@ export default function GlobalMenu(): ReactElement {
const host = useLobbyOrGameState(
state => {
if (state.stateType === "game") {
return state.host
return state.host !== null
} else {
return state.players.get(state.myId!)?.ready === "host"
}
Expand Down Expand Up @@ -71,9 +72,14 @@ export default function GlobalMenu(): ReactElement {
<section className="standout">
<h2>{lobbyName}</h2>
<RoomLinkButton/>
{(stateType === "game" && host) && <Button onClick={()=>GAME_MANAGER.sendBackToLobbyPacket()}>
{translate("backToLobby")}
</Button>}
{(stateType === "game" && host) && <>
<Button onClick={()=>GAME_MANAGER.sendBackToLobbyPacket()}>
{translate("backToLobby")}
</Button>
<Button onClick={()=>anchorController.setCoverCard(<HostMenu />)}>
{translate("menu.hostSettings.title")}
</Button>
</>}
</section>
}
<section>
Expand Down
57 changes: 57 additions & 0 deletions client/src/menu/HostMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { ReactElement, useContext, useEffect, useState } from "react";
import translate from "../game/lang";
import GAME_MANAGER from "..";
import { Button } from "../components/Button";
import { usePacketListener } from "../components/useHooks";
import { AnchorControllerContext } from "./Anchor";
import "./lobby/lobbyMenu.css"
import LobbyPlayerList from "./lobby/LobbyPlayerList";

export default function HostMenu(): ReactElement {
const anchorController = useContext(AnchorControllerContext)!;

useEffect(() => {
GAME_MANAGER.sendHostDataRequest();
}, [])

const [lastRefreshed, setLastRefreshed] = useState(new Date());

usePacketListener(type => {
// Check on every packet since like 1 million packets can affect this
if (!(GAME_MANAGER.state.stateType === "game" && GAME_MANAGER.state.host !== null)) {
anchorController.clearCoverCard();
}

if (type === "hostData") {
setLastRefreshed(new Date(Date.now()))
}
});

return <div className="settings-menu-card">
<header>
<h1>{translate("menu.hostSettings.title")}</h1>
{translate("menu.hostSettings.lastRefresh", lastRefreshed.toLocaleTimeString())}
</header>

<Button onClick={() => GAME_MANAGER.sendHostDataRequest()}
>{translate("refresh")}</Button>

<main className="settings-menu">
<LobbyPlayerList />
<div className="chat-menu-colors">
<h2>{translate("menu.hostSettings.lobby")}</h2>
<section>
<Button onClick={()=>GAME_MANAGER.sendBackToLobbyPacket()}>
{translate("backToLobby")}
</Button>
<Button onClick={()=>GAME_MANAGER.sendHostEndGamePacket()}>
{translate("menu.hostSettings.endGame")}
</Button>
<Button onClick={()=>GAME_MANAGER.sendHostSkipPhase()}>
{translate("menu.hostSettings.skipPhase")}
</Button>
</section>
</div>
</main>
</div>
}
6 changes: 3 additions & 3 deletions client/src/menu/game/HeaderMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function HeaderMenu(props: Readonly<{

const phaseState = useGameState(
gameState => gameState.phaseState,
["phase", "playerOnTrial"]
["phase"]
)!

const backgroundStyle =
Expand All @@ -27,7 +27,7 @@ export default function HeaderMenu(props: Readonly<{
"background-day";

const host = useGameState(
state => state.host,
state => state.host !== null,
["playersHost"]
)!;

Expand Down Expand Up @@ -78,7 +78,7 @@ function Information(): ReactElement {
)!
const phaseState = useGameState(
gameState => gameState.phaseState,
["phase", "playerOnTrial"]
["phase"]
)!
const players = useGameState(
gameState => gameState.players,
Expand Down
2 changes: 1 addition & 1 deletion client/src/menu/game/gameScreenContent/PlayerListMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function PlayerCard(props: Readonly<{
)!;
const phaseState = useGameState(
gameState => gameState.phaseState,
["phase", "playerOnTrial"]
["phase"]
)!
const numVoted = useGameState(
gameState => gameState.players[props.playerIndex].numVoted,
Expand Down
Loading
Loading