Skip to content

Commit

Permalink
Introduce sfx volume and a overall mute button
Browse files Browse the repository at this point in the history
  • Loading branch information
gereon77 committed Feb 23, 2024
1 parent 9918eba commit fa494ef
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 113 deletions.
68 changes: 51 additions & 17 deletions agot-bg-game-server/src/client/GameClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,64 +57,86 @@ export default class GameClient {

this.authenticatedUser.settings.muted = value;
if (value == true) {
const oldVolumes = {
notificationsVolume: this.authenticatedUser.settings.notificationsVolume,
musicVolume: this.authenticatedUser.settings.musicVolume,
sfxVolume: this.authenticatedUser.settings.sfxVolume
};
localStorage.setItem('oldVolumes', JSON.stringify(oldVolumes));

this.authenticatedUser.settings.notificationsVolume = 0;
this.authenticatedUser.settings.musicVolume = 0;
this.authenticatedUser.settings.sfxVolume = 0;

this.sfxManager.muteAll();
} else {
const oldVolumesFromStorage = JSON.parse(localStorage.getItem('oldVolumes') || '{}');
this.authenticatedUser.settings.notificationsVolume = oldVolumesFromStorage.notificationsVolume ?? 1;
this.authenticatedUser.settings.musicVolume = oldVolumesFromStorage.musicVolume ?? 1;
this.authenticatedUser.settings.sfxVolume = oldVolumesFromStorage.sfxVolume ?? 1;

localStorage.removeItem('oldVolumes');

this.sfxManager.unmuteAll();
}

this.authenticatedUser.syncSettings();
}

get musicMuted(): boolean {
get notificationsVolume(): number {
if (!this.authenticatedUser) {
throw new Error("Game client must have an authenticated user");
}

return this.authenticatedUser.settings.musicMuted;
return this.authenticatedUser.settings.notificationsVolume;
}

set musicMuted(value: boolean) {
set notificationsVolume(value: number) {
if (!this.authenticatedUser) {
throw new Error("Game client must have an authenticated user");
}

this.authenticatedUser.settings.musicMuted = value;
if (value == true) {
this.authenticatedUser.settings.musicVolume = 0;
}
this.authenticatedUser.settings.notificationsVolume = value;
this.setCurrentMutedState(value);

this.authenticatedUser.syncSettings();
}

get notificationsVolume(): number {
get musicVolume(): number {
if (!this.authenticatedUser) {
throw new Error("Game client must have an authenticated user");
}

return this.authenticatedUser.settings.notificationsVolume;
return this.authenticatedUser.settings.musicVolume;
}

set notificationsVolume(value: number) {
set musicVolume(value: number) {
if (!this.authenticatedUser) {
throw new Error("Game client must have an authenticated user");
}

this.authenticatedUser.settings.notificationsVolume = value;
this.authenticatedUser.settings.muted = value == 0;
this.authenticatedUser.settings.musicVolume = value;
this.setCurrentMutedState(value);

this.authenticatedUser.syncSettings();
}

get musicVolume(): number {
get sfxVolume(): number {
if (!this.authenticatedUser) {
throw new Error("Game client must have an authenticated user");
}

return this.authenticatedUser.settings.musicVolume;
return this.authenticatedUser.settings.sfxVolume;
}

set musicVolume(value: number) {
set sfxVolume(value: number) {
if (!this.authenticatedUser) {
throw new Error("Game client must have an authenticated user");
}

this.authenticatedUser.settings.musicVolume = value;
this.authenticatedUser.settings.musicMuted = value == 0;
this.authenticatedUser.settings.sfxVolume = value;
this.setCurrentMutedState(value);

this.authenticatedUser.syncSettings();
}

Expand All @@ -134,6 +156,18 @@ export default class GameClient {
}
}

private setCurrentMutedState(value: number): void {
if (!this.authenticatedUser) {
return;
}

if (value > 0) {
this.authenticatedUser.settings.muted = false;
} else if (this.musicVolume == 0 && this.notificationsVolume == 0 && this.sfxVolume == 0) {
this.authenticatedUser.settings.muted = true;
}
}

constructor(authData: AuthData) {
this.authData = authData;
}
Expand Down
102 changes: 57 additions & 45 deletions agot-bg-game-server/src/client/IngameComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ import settingsKnobsImage from "../../public/images/icons/settings-knobs.svg";
import hourglassImage from "../../public/images/icons/hourglass.svg";
import mammothImage from "../../public/images/icons/mammoth.svg";
import spikedDragonHeadImage from "../../public/images/icons/spiked-dragon-head.svg";
import megaphoneImage from "../../public/images/icons/megaphone.svg";
import speakerImage from "../../public/images/icons/speaker.svg";
import speakerOffImage from "../../public/images/icons/speaker-off.svg";
import musicalNotesImage from "../../public/images/icons/musical-notes.svg";
import cardRandomImage from "../../public/images/icons/card-random.svg";
import podiumWinnerImage from "../../public/images/icons/podium-winner.svg";
import House from "../common/ingame-game-state/game-data-structure/House";
Expand Down Expand Up @@ -281,23 +280,49 @@ export default class IngameComponent extends Component<IngameComponentProps> {
return null;
}

return <OverlayTrigger
overlay={this.renderGameControlsPopover()}
placement="auto"
trigger="click"
rootClose
>
<div className="clickable btn btn-sm btn-secondary p-1" style={{
position: "fixed",
right: this.user?.settings.responsiveLayout ? "auto" : "4px",
left: this.user?.settings.responsiveLayout ? "4px" : "auto",
top: "45px",
padding: "4px",
borderStyle: "none" }}
return <>
<OverlayTrigger
overlay={this.renderGameControlsPopover()}
placement="auto"
trigger="click"
rootClose
>
<img src={settingsKnobsImage} width={24} />
</div>
</OverlayTrigger>;
<div className="clickable btn btn-sm btn-secondary" style={{
position: "fixed",
right: this.user?.settings.responsiveLayout ? "auto" : "4px",
left: this.user?.settings.responsiveLayout ? "4px" : "auto",
top: "45px",
padding: "4px",
borderStyle: "none" }}
>
<img src={settingsKnobsImage} width={24} />
</div>
</OverlayTrigger>
<button type="button" className="btn btn-sm btn-secondary"
onClick={() => this.gameClient.muted = !this.gameClient.muted}
style={{
position: "fixed",
right: this.user?.settings.responsiveLayout ? "auto" : "4px",
left: this.user?.settings.responsiveLayout ? "4px" : "auto",
top: "85px",
paddingBottom: "4px",
paddingTop: "4px",
paddingLeft: "2px",
paddingRight: "4px"
}}
>
<OverlayTrigger
placement="auto"
overlay={<Tooltip id="mute-tooltip">
{this.gameClient.muted
? "Unmute"
: "Mute"}
</Tooltip>}
>
<img src={this.gameClient.muted ? speakerOffImage : speakerImage} width={24} />
</OverlayTrigger>
</button>
</>;
}

renderTracksPopoverButton(tracks: InfluenceTrackDetails[]): ReactNode {
Expand Down Expand Up @@ -563,41 +588,27 @@ export default class IngameComponent extends Component<IngameComponentProps> {
return <Row className={this.mapScrollbarEnabled ? "flex-footer mt-2" : "mt-2"} id="game-controls">
<Col xs="auto">
<div className="btn btn-outline-light btn-sm">
<OverlayTrigger
overlay={this.renderGameControlsPopover()}
placement="top"
trigger="click"
rootClose
>
<img src={settingsKnobsImage} width={32} />
</OverlayTrigger>
</div>
</Col>
<Col xs="auto">
<button type="button" className="btn btn-outline-light btn-sm" onClick={() => this.gameClient.muted = !this.gameClient.muted}>
<OverlayTrigger
placement="auto"
overlay={<Tooltip id="mute-tooltip">
{this.gameClient.muted
? "Unmute notifications"
: "Mute notifications"}
</Tooltip>}
overlay={this.renderGameControlsPopover()}
placement="top"
trigger="click"
rootClose
>
<img src={this.gameClient.muted ? speakerOffImage : megaphoneImage} width={32} />
<img src={settingsKnobsImage} width={32} />
</OverlayTrigger>
</button>
</div>
</Col>
<Col xs="auto">
<button type="button" className="btn btn-outline-light btn-sm" onClick={() => this.gameClient.musicMuted = !this.gameClient.musicMuted}>
<button type="button" className="btn btn-outline-light btn-sm" onClick={() => this.gameClient.muted = !this.gameClient.muted}>
<OverlayTrigger
placement="auto"
overlay={<Tooltip id="mute-tooltip">
{this.gameClient.musicMuted
? "Unmute music and sound effects"
: "Mute music and sound effects"}
{this.gameClient.muted
? "Unmute"
: "Mute"}
</Tooltip>}
>
<img src={this.gameClient.musicMuted ? speakerOffImage : musicalNotesImage} width={32} />
<img src={this.gameClient.muted ? speakerOffImage : speakerImage} width={32} />
</OverlayTrigger>
</button>
</Col>
Expand All @@ -614,7 +625,8 @@ export default class IngameComponent extends Component<IngameComponentProps> {
return <Popover id="game-controls-popover" style={{ maxWidth: "100%", borderColor: "white"}}>
<Col className="m-2 p-2">
<VolumeSliderComponent volume={this.gameClient.notificationsVolume * 100} name="Notifications" onVolumeChange={(val) => this.gameClient.sfxManager.notificationVolumeChanged(val / 100)}/>
<VolumeSliderComponent volume={this.gameClient.musicVolume * 100} name="Music and Sfx" onVolumeChange={(val) => this.gameClient.sfxManager.musicVolumeChanged(val / 100)}/>
<VolumeSliderComponent volume={this.gameClient.musicVolume * 100} name="Music" onVolumeChange={(val) => this.gameClient.sfxManager.musicVolumeChanged(val / 100)}/>
<VolumeSliderComponent volume={this.gameClient.sfxVolume * 100} name="Sfx" onVolumeChange={(val) => this.gameClient.sfxManager.sfxVolumeChanged(val / 100)}/>
{this.authenticatedPlayer && <Row className="justify-content-center mt-3">
<Col xs="auto">
<button type="button"
Expand Down Expand Up @@ -1610,7 +1622,7 @@ export default class IngameComponent extends Component<IngameComponentProps> {
this.ingame.onVoteStarted = null;
}

componentDidUpdate(_prevProps: Readonly<IngameComponentProps>, _prevState: Readonly<{}>, _snapshot?: any): void {
componentDidUpdate(_prevProps: Readonly<IngameComponentProps>, _prevState: Readonly<any>, _snapshot?: any): void {
if (this.currentOpenedTab == "note") {
this.unseenNotes = false;
}
Expand Down
44 changes: 28 additions & 16 deletions agot-bg-game-server/src/client/LobbyComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import ChatComponent from "./chat-client/ChatComponent";
import GameSettingsComponent from "./GameSettingsComponent";
import User from "../server/User";
import ConditionalWrap from "./utils/ConditionalWrap";
import { Badge, OverlayTrigger, Spinner } from "react-bootstrap";
import { Badge, OverlayTrigger, Popover, Spinner } from "react-bootstrap";
import Tooltip from "react-bootstrap/Tooltip";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {faTimes} from "@fortawesome/free-solid-svg-icons/faTimes";
Expand All @@ -25,13 +25,15 @@ import { observable } from "mobx";
import DebouncedPasswordComponent from "./utils/DebouncedPasswordComponent";
import { faCheck, faLock } from "@fortawesome/free-solid-svg-icons";
import { setBoltonIconImage, setStarkIconImage } from "./houseIconImages";
import megaphoneImage from "../../public/images/icons/megaphone.svg";
import settingsKnobsImage from "../../public/images/icons/settings-knobs.svg";
import speakerImage from "../../public/images/icons/speaker.svg";
import speakerOffImage from "../../public/images/icons/speaker-off.svg";
import musicalNotesImage from "../../public/images/icons/musical-notes.svg";
import getUserLinkOrLabel from "./utils/getIngameUserLinkOrLabel";
// @ts-expect-error Somehow ts complains that this module cannot be found while it is
import ScrollToBottom from "react-scroll-to-bottom";
import _ from "lodash";
import VolumeSliderComponent from "./utils/VolumeSliderComponent";
import { OverlayChildren } from "react-bootstrap/esm/Overlay";


interface LobbyComponentProps {
Expand Down Expand Up @@ -213,29 +215,26 @@ export default class LobbyComponent extends Component<LobbyComponentProps> {
overlay={
<Tooltip id="mute-tooltip">
{this.props.gameClient.muted
? "Unmute notifications"
: "Mute notifications"}
? "Unmute"
: "Mute"}
</Tooltip>
}
>
<img src={this.props.gameClient.muted ? speakerOffImage : megaphoneImage} height={26} />
<img src={this.props.gameClient.muted ? speakerOffImage : speakerImage} height={26} />
</OverlayTrigger>
</button>
</Col>
<Col xs="auto">
<button type="button" className="btn btn-outline-light btn-sm" onClick={() => this.props.gameClient.musicMuted = !this.props.gameClient.musicMuted}>
<div className="btn btn-outline-light btn-sm">
<OverlayTrigger
overlay={
<Tooltip id="mute-tooltip">
{this.props.gameClient.musicMuted
? "Unmute music"
: "Mute music"}
</Tooltip>
}
overlay={this.renderVolumeControlPopover()}
placement="top"
trigger="click"
rootClose
>
<img src={this.props.gameClient.musicMuted ? speakerOffImage : musicalNotesImage} height={26} />
<img src={settingsKnobsImage} height={26} />
</OverlayTrigger>
</button>
</div>
</Col>
</Row>
</Card.Body>
Expand All @@ -245,6 +244,19 @@ export default class LobbyComponent extends Component<LobbyComponentProps> {
</>;
}

renderVolumeControlPopover(): OverlayChildren {
return <Popover id="game-controls-popover" style={{ maxWidth: "100%", borderColor: "white"}}>
<Col className="m-2 p-2">
<VolumeSliderComponent volume={this.props.gameClient.notificationsVolume * 100} name="Notifications"
onVolumeChange={(val) => this.props.gameClient.sfxManager.notificationVolumeChanged(val / 100)} />
<VolumeSliderComponent volume={this.props.gameClient.musicVolume * 100} name="Music"
onVolumeChange={(val) => this.props.gameClient.sfxManager.musicVolumeChanged(val / 100)} />
<VolumeSliderComponent volume={this.props.gameClient.sfxVolume * 100} name="Sfx"
onVolumeChange={(val) => this.props.gameClient.sfxManager.sfxVolumeChanged(val / 100)} />
</Col>
</Popover>;
}

renderPasswordInput(): ReactNode {
const isOwner = this.props.gameClient.isRealOwner();
return <Row className="justify-content-center mt-0">
Expand Down
Loading

0 comments on commit fa494ef

Please sign in to comment.