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 authored Apr 26, 2024
2 parents 054d42b + 08990f2 commit b197300
Show file tree
Hide file tree
Showing 23 changed files with 258 additions and 91 deletions.
75 changes: 53 additions & 22 deletions client/src/components/ChatMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ReactElement } from "react";
import translate, { translateChecked } from "../game/lang";
import React from "react";
import GAME_MANAGER, { find, replaceMentions } from "..";
Expand All @@ -13,14 +12,14 @@ import { RoleOutline, translateRoleOutline } from "../game/roleListState.d";
import { AuditorResult } from "../menu/game/gameScreenContent/RoleSpecificMenus/LargeAuditorMenu";
import { OjoAction } from "../menu/game/gameScreenContent/RoleSpecificMenus/SmallOjoMenu";

export default function ChatElement(
const ChatElement = React.memo((
props: {
message: ChatMessage,
playerNames?: string[],
playerKeywordData?: KeywordDataMap,
playerSenderKeywordData?: KeywordDataMap
},
): ReactElement {
) => {
const message = props.message;
const playerNames = props.playerNames ?? GAME_MANAGER.getPlayerNames();
const chatMessageStyles = require("../resources/styling/chatMessage.json");
Expand All @@ -43,6 +42,19 @@ export default function ChatElement(

// Special chat messages that don't play by the rules
switch (message.variant.type) {
case "lobbyMessage":
if (containsMention(message.variant, playerNames)) {
style += " mention";
}

return <span className={`chat-message ${style}`}>
<StyledText
playerKeywordData={props.playerSenderKeywordData ?? PLAYER_SENDER_KEYWORD_DATA}
>{icon ?? ""} {`sender-${message.variant.sender}`}: </StyledText>
<StyledText
playerKeywordData={props.playerKeywordData}
>{translateChatMessage(message.variant, playerNames)}</StyledText>
</span>;
case "normal":
if(message.variant.messageSender.type !== "player" && message.variant.messageSender.type !== "livingToDead"){
style += " discreet";
Expand All @@ -63,30 +75,15 @@ export default function ChatElement(
messageSender = translate("role."+message.variant.messageSender.type+".name");
}

if (
GAME_MANAGER.state.stateType === "game" && GAME_MANAGER.state.clientState.type === "player" && GAME_MANAGER.state.clientState.myIndex !== null &&
(find(GAME_MANAGER.state.players[GAME_MANAGER.state.clientState.myIndex].name ?? "").test(sanitizePlayerMessage(replaceMentions(
message.variant.text,
playerNames
))) ||
(
GAME_MANAGER.state.stateType === "game" && GAME_MANAGER.state.clientState.type === "player" &&
GAME_MANAGER.state.clientState.myIndex !== null &&
find("" + (GAME_MANAGER.state.clientState.myIndex + 1)).test(sanitizePlayerMessage(replaceMentions(
message.variant.text,
playerNames
)))
))

) {
if (containsMention(message.variant, playerNames)) {
style += " mention";
}

return <span className="chat-message">
<StyledText className={style}
return <span className={`chat-message ${style}`}>
<StyledText
playerKeywordData={props.playerSenderKeywordData ?? PLAYER_SENDER_KEYWORD_DATA}
>{icon ?? ""} {messageSender}: </StyledText>
<StyledText className={style}
<StyledText
playerKeywordData={props.playerKeywordData}
>{translateChatMessage(message.variant, playerNames)}</StyledText>
</span>;
Expand Down Expand Up @@ -118,8 +115,36 @@ export default function ChatElement(
return <StyledText className={"chat-message " + style}
playerKeywordData={props.playerKeywordData}
>{(icon??"")} {translateChatMessage(message.variant, playerNames)}</StyledText>;
});

function containsMention(message: ChatMessageVariant & { text: string }, playerNames: string[]): boolean {
let myNumber: number | null = null;
let myName: string | null = null;
if (GAME_MANAGER.state.stateType === "game" && GAME_MANAGER.state.clientState.type === "player" && GAME_MANAGER.state.clientState.myIndex !== null) {
myName = GAME_MANAGER.state.players[GAME_MANAGER.state.clientState.myIndex].name ?? ""
myNumber = GAME_MANAGER.state.clientState.myIndex;
} else if (GAME_MANAGER.state.stateType === "lobby") {
const myPlayer = GAME_MANAGER.state.players.get(GAME_MANAGER.state.myId!);
if (myPlayer !== null && myPlayer?.clientType.type === "player") {
myName = myPlayer.clientType.name;
} else {
return false
}
}
if (myName === null) {
return false;
}
return (
find(myName).test(sanitizePlayerMessage(replaceMentions(message.text, playerNames))) ||
(
myNumber !== null &&
find("" + (myNumber + 1)).test(sanitizePlayerMessage(replaceMentions(message.text, playerNames)))
)
)
}

export default ChatElement;

function playerListToString(playerList: PlayerIndex[], playerNames: string[]): string {

return playerList.map((playerIndex) => {
Expand All @@ -140,6 +165,8 @@ export function translateChatMessage(message: ChatMessageVariant, playerNames?:
}

switch (message.type) {
case "lobbyMessage":
return sanitizePlayerMessage(replaceMentions(message.text, playerNames));
case "normal":
return sanitizePlayerMessage(replaceMentions(message.text, playerNames));
case "whisper":
Expand Down Expand Up @@ -459,6 +486,10 @@ export type ChatMessage = {
chatGroup: ChatGroup | null
}
export type ChatMessageVariant = {
type: "lobbyMessage",
sender: string,
text: string
} | {
type: "normal",
messageSender: MessageSender,
text: string
Expand Down
30 changes: 26 additions & 4 deletions client/src/components/StyledText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import DUMMY_NAMES from "../resources/dummyNames.json";
import { ARTICLES, WikiArticleLink, getArticleLangKey } from "./WikiArticleLink";
import GameScreen, { ContentMenu } from "../menu/game/GameScreen";
import { Player } from "../game/gameState.d";
import Anchor from "../menu/Anchor";
import WikiCoverCard from "./WikiCoverCard";

export type TokenData = {
style?: string,
Expand All @@ -35,10 +37,16 @@ type Token = {
} & KeywordData[number])

(window as any).setWikiSearchPage = (page: WikiArticleLink) => {
if (GameScreen.instance) {
GameScreen.instance?.openMenu(ContentMenu.WikiMenu, () => {
GAME_MANAGER.setWikiArticle(page);
});
if (GAME_MANAGER.wikiArticleCallbacks.length === 0) {
if (GameScreen.instance) {
GameScreen.instance.openMenu(ContentMenu.WikiMenu, () => {
GAME_MANAGER.setWikiArticle(page);
});
} else {
Anchor.setCoverCard(<WikiCoverCard />, () => {
GAME_MANAGER.setWikiArticle(page);
})
}
} else {
GAME_MANAGER.setWikiArticle(page);
}
Expand Down Expand Up @@ -191,6 +199,20 @@ export function computePlayerKeywordData(players: Player[]) {
}
}

export function computePlayerKeywordDataForLobby(playerNames: string[]) {
for (const key in PLAYER_KEYWORD_DATA) {
delete PLAYER_KEYWORD_DATA[key];
}
for (const key in PLAYER_SENDER_KEYWORD_DATA) {
delete PLAYER_SENDER_KEYWORD_DATA[key];
}

for(const name of playerNames) {
PLAYER_SENDER_KEYWORD_DATA["sender-"+name] = [{ style: "keyword-player-sender", replacement: name }];
PLAYER_KEYWORD_DATA[name] = [{ style: "keyword-player", replacement: name }];
}
}

export const DUMMY_NAMES_KEYWORD_DATA: KeywordDataMap = {};
computeDummyNamesKeywordData();

Expand Down
11 changes: 9 additions & 2 deletions client/src/components/Wiki.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ export default function Wiki(props: {
}, [history]);

useEffect(() => {
GAME_MANAGER.setSetWikiArticleFunction(chooseArticle);
GAME_MANAGER.addSetWikiArticleCallback(chooseArticle);

return () => GAME_MANAGER.removeSetWikiArticleCallback(chooseArticle);
}, [setArticle, chooseArticle]);
GAME_MANAGER.setSetWikiArticleFunction(chooseArticle);

// This makes sure you can call GAME_MANAGER.setWikiArticle immediately after this component is added
GAME_MANAGER.addSetWikiArticleCallback(chooseArticle);
setTimeout(() => {
GAME_MANAGER.removeSetWikiArticleCallback(chooseArticle);
}, 100)

function goBack() {
if (history.length > 1) {
Expand Down
7 changes: 5 additions & 2 deletions client/src/game/gameManager.d.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { WikiArticleLink } from "../components/WikiArticleLink";
import { DoomsayerGuess } from "../menu/game/gameScreenContent/RoleSpecificMenus/LargeDoomsayerMenu";
import { OjoAction } from "../menu/game/gameScreenContent/RoleSpecificMenus/SmallOjoMenu";
import GameState, { PhaseType, PhaseTimes, PlayerIndex, State, Verdict, Player } from "./gameState.d";
import { PhaseType, PhaseTimes, PlayerIndex, State, Verdict, Player } from "./gameState.d";
import { ToClientPacket, ToServerPacket } from "./packet";
import { RoleList, RoleOutline } from "./roleListState.d";
import { Role } from "./roleState.d";
Expand Down Expand Up @@ -44,7 +44,9 @@ export type GameManager = {
setPrependWhisperFunction: (f: ((index: PlayerIndex) => void)) => void;
prependWhisper: (index: PlayerIndex) => void;

setSetWikiArticleFunction: (f: ((article: WikiArticleLink | null) => void)) => void;
wikiArticleCallbacks: ((article: WikiArticleLink | null) => void)[];
addSetWikiArticleCallback: (callback: ((article: WikiArticleLink | null) => void)) => void;
removeSetWikiArticleCallback: (callback: ((article: WikiArticleLink | null) => void)) => void;
setWikiArticle: (article: WikiArticleLink | null) => void;

leaveGame(): void;
Expand All @@ -68,6 +70,7 @@ export type GameManager = {
sendKickPlayerPacket(playerId: number): void;
sendSetSpectatorPacket(spectator: boolean): void;
sendSetNamePacket(name: string): void;
sendSendLobbyMessagePacket(text: string): void;
sendSetLobbyNamePacket(name: string): void;
sendStartGamePacket(): Promise<boolean>;
sendBackToLobbyPacket(): void;
Expand Down
22 changes: 19 additions & 3 deletions client/src/game/gameManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ export function createGameManager(): GameManager {
switch (GAME_MANAGER.state.stateType) {
case "game":
return GAME_MANAGER.state.players.map((player) => player.toString());
case "lobby":
return [];
default:
return DUMMY_NAMES;
}
Expand Down Expand Up @@ -172,10 +174,18 @@ export function createGameManager(): GameManager {
},
prependWhisper: (index) => {},

setSetWikiArticleFunction: (f) => {
gameManager.setWikiArticle = f;
wikiArticleCallbacks: [],
addSetWikiArticleCallback: (callback) => {
gameManager.wikiArticleCallbacks.push(callback);
},
removeSetWikiArticleCallback: (callback) => {
gameManager.wikiArticleCallbacks.splice(gameManager.wikiArticleCallbacks.indexOf(callback), 1)
},
setWikiArticle: (article) => {
for (const callback of gameManager.wikiArticleCallbacks) {
callback(article);
}
},
setWikiArticle: (article) => {},


leaveGame() {
Expand Down Expand Up @@ -277,6 +287,12 @@ export function createGameManager(): GameManager {
name: name
});
},
sendSendLobbyMessagePacket(text) {
this.server.sendPacket({
type: "sendLobbyMessage",
text: text
});
},

sendSetLobbyNamePacket(name) {
this.server.sendPacket({
Expand Down
1 change: 1 addition & 0 deletions client/src/game/gameState.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type LobbyState = {
phaseTimes: PhaseTimes,

players: Map<LobbyClientID, LobbyClient>,
chatMessages: ChatMessage[],
}
export type LobbyClient = {
host: boolean,
Expand Down
3 changes: 2 additions & 1 deletion client/src/game/gameState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export function createLobbyState(): LobbyState {
excludedRoles: [],
phaseTimes: defaultPhaseTimes(),

players: new Map<LobbyClientID, LobbyClient>()
players: new Map<LobbyClientID, LobbyClient>(),
chatMessages: [],
}
}

Expand Down
15 changes: 11 additions & 4 deletions client/src/game/messageListener.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ToClientPacket } from "./packet";
import { Tag } from "./gameState.d";
import { Role } from "./roleState.d";
import translate from "./lang";
import { computePlayerKeywordData } from "../components/StyledText";
import { computePlayerKeywordData, computePlayerKeywordDataForLobby } from "../components/StyledText";
import { deleteReconnectData, saveReconnectData } from "./localStorage";
import { WikiArticleLink } from "../components/WikiArticleLink";
import React from "react";
Expand Down Expand Up @@ -147,6 +147,13 @@ export default function messageListener(packet: ToClientPacket){
for(let [clientId, lobbyClient] of Object.entries(packet.clients)){
GAME_MANAGER.state.players.set(Number.parseInt(clientId), lobbyClient);
}

// Recompute keyword data, since player names are keywords.
computePlayerKeywordDataForLobby(
Array.from(GAME_MANAGER.state.players.values())
.filter(client => client.clientType.type === "player")
.map(client => (client.clientType as { type: "player", name: string }).name)
);
}
break;
case "lobbyName":
Expand Down Expand Up @@ -223,7 +230,7 @@ export default function messageListener(packet: ToClientPacket){
if(packet.phase.type === "briefing" && GAME_MANAGER.state.clientState.type === "player"){
const role = GAME_MANAGER.state.clientState.roleState?.type;
if(role !== undefined){
Anchor.setCoverCard(<WikiArticle article={"role/"+role as WikiArticleLink}/>, "wiki-menu-colors");
Anchor.setCoverCard(<WikiArticle article={"role/"+role as WikiArticleLink}/>);
}
}
}
Expand Down Expand Up @@ -353,9 +360,9 @@ export default function messageListener(packet: ToClientPacket){
GAME_MANAGER.state.fastForward = packet.fastForward;
break;
case "addChatMessages":
if(GAME_MANAGER.state.stateType === "game"){
if(GAME_MANAGER.state.stateType === "game" || GAME_MANAGER.state.stateType === "lobby"){
GAME_MANAGER.state.chatMessages = GAME_MANAGER.state.chatMessages.concat(packet.chatMessages);

for(let chatMessage of packet.chatMessages){
let audioSrc = chatMessageToAudio(chatMessage);
if(audioSrc)
Expand Down
3 changes: 3 additions & 0 deletions client/src/game/packet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ export type ToServerPacket = {
} | {
type: "setName",
name: string
} | {
type: "sendLobbyMessage",
text: string
} | {
type: "setLobbyName",
name: string
Expand Down
4 changes: 4 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ code, .code {
background: #a1a1a1;
}

::-webkit-scrollbar-corner {
background: transparent
}

.chat-menu-colors {
--background-color: #151f2e;
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import StartMenu from './menu/main/StartMenu';
import LoadingScreen from './menu/LoadingScreen';
import { deleteReconnectData, loadReconnectData } from './game/localStorage';

export type Theme = "player-list-menu-colors" | "will-menu-colors" | "role-specific-colors" | "graveyard-menu-colors" | "wiki-menu-colors" | null
export type Theme = "player-list-menu-colors" | "will-menu-colors" | "role-specific-colors" | "graveyard-menu-colors" | "wiki-menu-colors"

const ROOT = ReactDOM.createRoot(document.querySelector("#root")!);
const GAME_MANAGER: GameManager = createGameManager();
Expand Down
Loading

0 comments on commit b197300

Please sign in to comment.