import { useEffect, useState } from "react";
import {
dispatch,
useGameId,
useIsMuted,
usePlayerName,
} from "../../../domain/gameStore";
import { usePlayers } from "../../../hooks/useGameInfo";
import styles from "./KillFeed.module.css";
import hitmarker from "../../../assets/hitmarker.svg";
import hitsound from "../../../assets/hitsound.wav";
// okay, in an ideal world this would be part of the game store or something
// and it would get properly managed by reactive state
// but also, this totally works as is, and the only downside is it might potentially grow too big
// but that only happens if someone plays that many gun games without ever leaving the window
const shownItems = new Set();
const KillFeed = () => {
const muted = useIsMuted();
const playerName = usePlayerName();
const gameId = useGameId();
const players = usePlayers();
useEffect(() => {
if (players?.find(({ currentRound }) => currentRound === null)) {
dispatch.goToSummary();
}
}, [players]);
const [shownItemsState, setShownItemsState] = useState(shownItems);
const [display, setDisplay] = useState([]);
useEffect(() => {
const toDisplay =
players
?.filter(({ name }) => name !== playerName)
?.flatMap(({ name, guesses }) =>
Object.entries(guesses).map(([round, { score }]) => ({
name,
round,
score,
}))
)
?.filter(
({ name, round }) =>
!shownItemsState.has(`${gameId}-${name}-${round}`)
) ?? [];
setDisplay(toDisplay);
const timeout = setTimeout(() => {
toDisplay.forEach(({ name, round }) => {
shownItems.add(`${gameId}-${name}-${round}`);
});
setShownItemsState(new Set(shownItems));
}, 5000);
return () => {
clearTimeout(timeout);
};
}, [shownItemsState, gameId, players, playerName]);
useEffect(() => {
if (!muted) {
display.forEach(() => {
const audio = new Audio(hitsound);
audio.volume = 0.5;
// delay up to half a second so overlapping sounds better
const delayedPlay = () =>
setTimeout(() => audio.play(), Math.random() * 500);
audio.addEventListener("canplaythrough", delayedPlay);
// clean up after ourselves in the hopes that the browser actually deletes this audio element
audio.addEventListener("ended", () =>
audio.removeEventListener("canplaythrough", delayedPlay)
);
});
}
}, [display, muted]);
return (
<>
{display.map(() => (
))}