Skip to content

Commit

Permalink
Merge branch 'main' into prod
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsSammyM committed Oct 16, 2024
2 parents d388ee0 + b7e4b1b commit 6ba8b08
Show file tree
Hide file tree
Showing 27 changed files with 315 additions and 90 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"Armorsmith",
"cancel",
"chrono",
"Chronokaiser",
"Consig",
"Deodat",
"Doesnt",
Expand Down
5 changes: 5 additions & 0 deletions client/src/components/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,8 @@ export function translateChatMessage(message: ChatMessageVariant, playerNames?:
return translate("chatMessage.youAreLoveLinked", playerNames[message.player]);
case "playerDiedOfABrokenHeart":
return translate("chatMessage.playerDiedOfBrokenHeart", playerNames[message.player], playerNames[message.lover]);
case "chronokaiserSpeedUp":
return translate("chatMessage.chronokaiserSpeedUp", message.percent);
case "deputyShotYou":
case "deathCollectedSouls":
case "targetWasAttacked":
Expand Down Expand Up @@ -991,6 +993,9 @@ export type ChatMessageVariant = {
type: "deathCollectedSouls"
} | {
type: "revolutionaryWon"
} | {
type: "chronokaiserSpeedUp"
percent: number
} | {
type: "doomsayerFailed"
} | {
Expand Down
1 change: 1 addition & 0 deletions client/src/game/gameManager.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export type GameManager = {
sendKickPlayerPacket(playerId: number): void;
sendSetSpectatorPacket(spectator: boolean): void;
sendSetNamePacket(name: string): void;
sendReadyUpPacket(ready: boolean): void;
sendSendLobbyMessagePacket(text: string): void;
sendSetLobbyNamePacket(name: string): void;
sendStartGamePacket(): Promise<boolean>;
Expand Down
11 changes: 9 additions & 2 deletions client/src/game/gameManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ 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!)?.host ?? false;
GAME_MANAGER.state.host = lobbyState.players.get(lobbyState.myId!)?.ready === "host";
}
},
setSpectatorGameState() {
Expand Down Expand Up @@ -122,7 +122,7 @@ export function createGameManager(): GameManager {
},
getMyHost() {
if (gameManager.state.stateType === "lobby")
return gameManager.state.players.get(gameManager.state.myId!)?.host;
return gameManager.state.players.get(gameManager.state.myId!)?.ready === "host";
if (gameManager.state.stateType === "game")
return gameManager.state.host;
return undefined;
Expand Down Expand Up @@ -307,6 +307,13 @@ export function createGameManager(): GameManager {
name: name
});
},

sendReadyUpPacket(ready) {
this.server.sendPacket({
type: "readyUp",
ready: ready
});
},
sendSendLobbyMessagePacket(text) {
this.server.sendPacket({
type: "sendLobbyMessage",
Expand Down
2 changes: 1 addition & 1 deletion client/src/game/gameState.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export type LobbyState = {
chatMessages: ChatMessage[],
}
export type LobbyClient = {
host: boolean,
ready: "host" | "ready" | "notReady",
connection: "connected" | "disconnected" | "couldReconnect",
clientType: LobbyClientType
}
Expand Down
2 changes: 2 additions & 0 deletions client/src/game/localStorage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function loadReconnectData(): {

export type Settings = {
volume: number;
defaultName: string | null;
language: Language;
roleSpecificMenus: Record<Role, RoleSpecificMenuType>
};
Expand Down Expand Up @@ -95,5 +96,6 @@ export function deleteGameModes() {
export const DEFAULT_SETTINGS: Readonly<Settings> = {
volume: 0.5,
language: "en_us",
defaultName: null,
roleSpecificMenus: Object.fromEntries(getAllRoles().map(role => [role, "playerList"])) as Record<Role, "playerList">
};
24 changes: 22 additions & 2 deletions client/src/game/messageListener.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Tag } from "./gameState.d";
import { Role } from "./roleState.d";
import translate from "./lang";
import { computePlayerKeywordData, computePlayerKeywordDataForLobby } from "../components/StyledText";
import { deleteReconnectData, saveReconnectData } from "./localStorage";
import { deleteReconnectData, loadSettings, saveReconnectData } from "./localStorage";
import { WikiArticleLink } from "../components/WikiArticleLink";
import React from "react";
import WikiArticle from "../components/WikiArticle";
Expand Down Expand Up @@ -73,6 +73,10 @@ export default function messageListener(packet: ToClientPacket){


saveReconnectData(packet.roomCode, packet.playerId);
const defaultName = loadSettings().defaultName;
if(defaultName !== null && defaultName !== undefined && defaultName !== ""){
GAME_MANAGER.sendSetNamePacket(defaultName)
}
ANCHOR_CONTROLLER?.clearCoverCard();
break;
case "rejectJoin":
Expand Down Expand Up @@ -131,7 +135,23 @@ export default function messageListener(packet: ToClientPacket){
case "playersHost":
if(GAME_MANAGER.state.stateType === "lobby"){
for(let [playerId, player] of GAME_MANAGER.state.players){
player.host = packet.hosts.includes(playerId);
if (packet.hosts.includes(playerId)) {
player.ready = "host";
} else {
player.ready = player.ready === "host" ? "ready" : player.ready
}
}
GAME_MANAGER.state.players = new Map(GAME_MANAGER.state.players.entries());
}
break;
case "playersReady":
if(GAME_MANAGER.state.stateType === "lobby"){
for(let [playerId, player] of GAME_MANAGER.state.players){
if (packet.ready.includes(playerId)) {
player.ready = "ready";
} else {
player.ready = player.ready === "host" ? "host" : "notReady"
}
}
GAME_MANAGER.state.players = new Map(GAME_MANAGER.state.players.entries());
}
Expand Down
6 changes: 6 additions & 0 deletions client/src/game/packet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export type ToClientPacket = {
} | {
type: "playersHost",
hosts: LobbyClientID[],
} | {
type: "playersReady",
ready: LobbyClientID[],
} | {
type: "playersLostConnection",
lostConnection: LobbyClientID[],
Expand Down Expand Up @@ -191,6 +194,9 @@ export type ToServerPacket = {
} | {
type: "setName",
name: string
} | {
type: "readyUp",
ready: boolean
} | {
type: "sendLobbyMessage",
text: string
Expand Down
2 changes: 1 addition & 1 deletion client/src/menu/GlobalMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function GlobalMenu(): ReactElement {
if (state.stateType === "game") {
return state.host
} else {
return state.players.get(state.myId!)?.host
return state.players.get(state.myId!)?.ready === "host"
}
},
["lobbyClients", "playersHost", "gamePlayers"]
Expand Down
59 changes: 37 additions & 22 deletions client/src/menu/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function roleSpecificMenuType(role: Role): RoleSpecificMenuType | null {

export default function SettingsMenu(): ReactElement {
const [volume, setVolume] = useState<number>(loadSettings().volume);
const [defaultName, setDefaultName] = useState<string | null>(loadSettings().defaultName);
const [roleSpecificMenuSettings, setRoleSpecificMenuSettings] = useState(loadSettings().roleSpecificMenus);
const mobile = useContext(MobileContext)!;
const anchorController = useContext(AnchorControllerContext)!;
Expand Down Expand Up @@ -69,30 +70,44 @@ export default function SettingsMenu(): ReactElement {
</section>
</div>
<div>
{mobile && <h2>{translate("menu.settings.advanced")}</h2>}
<details className="standout role-specific-menu-settings">
<summary>
{translate("menu.settings.roleSpecificMenus")}
</summary>
<section className="standout">
<h2>{translate("menu.settings.defaultName")}</h2>
<input type="text"
value={defaultName===null?"":defaultName}
placeholder={translate("menu.lobby.field.namePlaceholder")}
onChange={(e) => {
const defaultName = e.target.value === "" ? null : e.target.value;
saveSettings({defaultName});
setDefaultName(defaultName);
}
}/>
</section>
<section>
{mobile && <h2>{translate("menu.settings.advanced")}</h2>}
<details className="standout role-specific-menu-settings">
<summary>
{translate("menu.settings.roleSpecificMenus")}
</summary>

{Object.entries(roleSpecificMenuSettings).map(([key, type]) => {
return <div className="role-specific-menu-settings-selector" key={key} >
<StyledText>{translate(`role.${key}.name`)}</StyledText>
<select defaultValue={type} onChange={e => {
const newRoleSpecificMenuSettings = {
...roleSpecificMenuSettings,
[key]: e.target.options[e.target.selectedIndex].value as RoleSpecificMenuType
};
{Object.entries(roleSpecificMenuSettings).map(([key, type]) => {
return <div className="role-specific-menu-settings-selector" key={key} >
<StyledText>{translate(`role.${key}.name`)}</StyledText>
<select defaultValue={type} onChange={e => {
const newRoleSpecificMenuSettings = {
...roleSpecificMenuSettings,
[key]: e.target.options[e.target.selectedIndex].value as RoleSpecificMenuType
};

setRoleSpecificMenuSettings(newRoleSpecificMenuSettings);
saveSettings({ roleSpecificMenus: newRoleSpecificMenuSettings })
}}>
<option value="playerList">{translate("menu.settings.roleSpecificMenus.playerList")}</option>
<option value="standalone">{translate("menu.settings.roleSpecificMenus.standalone")}</option>
</select>
</div>
})}
</details>
setRoleSpecificMenuSettings(newRoleSpecificMenuSettings);
saveSettings({ roleSpecificMenus: newRoleSpecificMenuSettings })
}}>
<option value="playerList">{translate("menu.settings.roleSpecificMenus.playerList")}</option>
<option value="standalone">{translate("menu.settings.roleSpecificMenus.standalone")}</option>
</select>
</div>
})}
</details>
</section>
</div>
</main>
</div>
Expand Down
4 changes: 2 additions & 2 deletions client/src/menu/lobby/LobbyMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function LobbyMenu(): ReactElement {
["playersHost", "lobbyClients"]
)!;
const isHost = useLobbyState(
lobbyState => lobbyState.players.get(lobbyState.myId!)?.host,
lobbyState => lobbyState.players.get(lobbyState.myId!)?.ready === "host",
["playersHost", "lobbyClients", "yourId"]
)!;
const mobile = useContext(MobileContext)!;
Expand Down Expand Up @@ -152,7 +152,7 @@ function LobbyMenuHeader(props: Readonly<{
}>): JSX.Element {
const [lobbyName, setLobbyName] = useState<string>(GAME_MANAGER.state.stateType === "lobby" ? GAME_MANAGER.state.lobbyName : "Mafia Lobby");
const host = useLobbyState(
lobbyState => lobbyState.players.get(lobbyState.myId!)?.host,
lobbyState => lobbyState.players.get(lobbyState.myId!)?.ready === "host",
["lobbyClients", "yourId", "playersHost"]
)!;
const mobile = useContext(MobileContext)!;
Expand Down
33 changes: 24 additions & 9 deletions client/src/menu/lobby/LobbyNamePane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import GAME_MANAGER from "../..";
import translate from "../../game/lang";
import Icon from "../../components/Icon";
import { useLobbyState } from "../../components/useHooks";
import { Button } from "../../components/Button";



Expand All @@ -12,23 +13,37 @@ export default function LobbyNamePane(): ReactElement {
["lobbyClients", "yourId"]
)!;

return <section className="player-list-menu-colors selector-section">
const ready = useLobbyState(
lobbyState => lobbyState.players.get(lobbyState.myId!)?.ready,
["lobbyClients", "playersHost", "playersReady", "yourId"]
)!;

return <section className="player-list-menu-colors selector-section lobby-name-pane">
{!isSpectator && <NameSelector/>}
{isSpectator && <button
onClick={()=>{GAME_MANAGER.sendSetSpectatorPacket(false)}}
><Icon>sports_esports</Icon> {translate("switchToPlayer")}</button>}
<div className="name-pane-buttons">
<Button onClick={() => GAME_MANAGER.sendSetSpectatorPacket(!isSpectator)}>
{isSpectator
? <><Icon>sports_esports</Icon> {translate("switchToPlayer")}</>
: <><Icon>visibility</Icon> {translate("switchToSpectator")}</>}
</Button>
{ready !== "host" && <Button
highlighted={ready === "notReady"}
onClick={() => {GAME_MANAGER.sendReadyUpPacket(ready === "notReady")}}
>
{ready === "ready"
? <><Icon>clear</Icon> {translate("menu.lobby.button.unready")}</>
: <><Icon>check</Icon> {translate("menu.lobby.button.readyUp")}</>}
</Button>}
</div>
</section>
}

function NameSelector(): ReactElement {
const [enteredName, setEnteredName] = React.useState("");

return <>
return <div className="name-pane-selector">
<div className="lobby-name">
<section><h2>{GAME_MANAGER.getMyName() ?? ""}</h2></section>
<button
onClick={()=>{GAME_MANAGER.sendSetSpectatorPacket(true)}}
><Icon>visibility</Icon> {translate("switchToSpectator")}</button>
</div>
<div className="name-box">
<input type="text" value={enteredName}
Expand All @@ -43,5 +58,5 @@ function NameSelector(): ReactElement {
GAME_MANAGER.sendSetNamePacket(enteredName)
}}>{translate("menu.lobby.button.setName")}</button>
</div>
</>
</div>
}
17 changes: 12 additions & 5 deletions client/src/menu/lobby/LobbyPlayerList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ import { useLobbyState } from "../../components/useHooks";
export default function LobbyPlayerList(): ReactElement {
const players = useLobbyState(
lobbyState => lobbyState.players,
["playersHost", "playersLostConnection", "lobbyClients"]
["playersHost", "playersLostConnection", "lobbyClients", "playersReady"]
)!;
const host = useLobbyState(
lobbyState => lobbyState.players.get(lobbyState.myId!)?.host,
["playersHost", "lobbyClients", "yourId"]
lobbyState => lobbyState.players.get(lobbyState.myId!)?.ready === "host",
["playersHost", "lobbyClients", "yourId", "playersReady"]
)!;

return <>
<LobbyNamePane/>
<section className="player-list player-list-menu-colors selector-section">
<h2>{translate("menu.lobby.players")}</h2>
<div>
<div className="list">
<ol>
{[...players.entries()]
.filter(([_, player]) => player.clientType.type !== "spectator")
.map(([id, player]) =>
<li key={id} className={player.connection==="couldReconnect" ? "keyword-dead" : ""}>
<div>
{player.connection === "couldReconnect" && <Icon>signal_cellular_connected_no_internet_4_bar</Icon>}
{player.host && <Icon>shield</Icon>}
{player.ready === "host" && <Icon>shield</Icon>}
{player.ready === "ready" && <Icon>check</Icon>}
{(player.clientType as PlayerClientType).name}
</div>
{host && <button
Expand All @@ -40,6 +41,12 @@ export default function LobbyPlayerList(): ReactElement {
}
</ol>
</div>
<div className="spectators-ready">
{translate("menu.lobby.spectatorsReady",
[...players.values()].filter(p => p.clientType.type === "spectator" && p.ready !== "notReady").length,
[...players.values()].filter(p => p.clientType.type === "spectator").length
)}
</div>
</section>
</>
}
Loading

0 comments on commit 6ba8b08

Please sign in to comment.