diff --git a/package-lock.json b/package-lock.json index cea861373..59adc6ea4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "express": "^4.21.1", "express-rate-limit": "^7.5.0", "fastpriorityqueue": "^0.7.5", + "howler": "^2.2.4", "intl-messageformat": "^10.7.16", "ip-anonymize": "^0.1.0", "jose": "^6.0.10", @@ -52,6 +53,7 @@ "@types/express": "^4.17.23", "@types/google-protobuf": "^3.15.12", "@types/hammerjs": "^2.0.46", + "@types/howler": "^2.2.12", "@types/jest": "^30.0.0", "@types/jquery": "^3.5.31", "@types/js-yaml": "^4.0.9", @@ -7131,6 +7133,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/howler": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/@types/howler/-/howler-2.2.12.tgz", + "integrity": "sha512-hy769UICzOSdK0Kn1FBk4gN+lswcj1EKRkmiDtMkUGvFfYJzgaDXmVXkSShS2m89ERAatGIPnTUlp2HhfkVo5g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -9509,7 +9518,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -12292,6 +12300,12 @@ "he": "bin/he" } }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==", + "license": "MIT" + }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -16221,7 +16235,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" diff --git a/package.json b/package.json index 7c48ce71e..88f3e860f 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@types/express": "^4.17.23", "@types/google-protobuf": "^3.15.12", "@types/hammerjs": "^2.0.46", + "@types/howler": "^2.2.12", "@types/jest": "^30.0.0", "@types/jquery": "^3.5.31", "@types/js-yaml": "^4.0.9", @@ -119,6 +120,7 @@ "express": "^4.21.1", "express-rate-limit": "^7.5.0", "fastpriorityqueue": "^0.7.5", + "howler": "^2.2.4", "intl-messageformat": "^10.7.16", "ip-anonymize": "^0.1.0", "jose": "^6.0.10", diff --git a/proprietary/sounds/music/evan.mp3 b/proprietary/sounds/music/evan.mp3 new file mode 100644 index 000000000..bbdf55acf Binary files /dev/null and b/proprietary/sounds/music/evan.mp3 differ diff --git a/proprietary/sounds/music/of2.mp3 b/proprietary/sounds/music/of2.mp3 new file mode 100644 index 000000000..8b41c3522 Binary files /dev/null and b/proprietary/sounds/music/of2.mp3 differ diff --git a/proprietary/sounds/music/of4.mp3 b/proprietary/sounds/music/of4.mp3 new file mode 100644 index 000000000..fc5693f6c Binary files /dev/null and b/proprietary/sounds/music/of4.mp3 differ diff --git a/proprietary/sounds/music/openfront.mp3 b/proprietary/sounds/music/openfront.mp3 new file mode 100644 index 000000000..2633fbf32 Binary files /dev/null and b/proprietary/sounds/music/openfront.mp3 differ diff --git a/proprietary/sounds/music/war.mp3 b/proprietary/sounds/music/war.mp3 new file mode 100644 index 000000000..244098f5d Binary files /dev/null and b/proprietary/sounds/music/war.mp3 differ diff --git a/proprietary/sounds/music/win.mp3 b/proprietary/sounds/music/win.mp3 new file mode 100644 index 000000000..c765e2b1d Binary files /dev/null and b/proprietary/sounds/music/win.mp3 differ diff --git a/resources/images/music.svg b/resources/images/music.svg new file mode 100644 index 000000000..45fd36b7a --- /dev/null +++ b/resources/images/music.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/resources/lang/en.json b/resources/lang/en.json index d8c0deb3f..6b9ed962b 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -360,7 +360,8 @@ "terrain_enabled": "Terrain view enabled", "terrain_disabled": "Terrain view disabled", "exit_game_label": "Exit Game", - "exit_game_info": "Return to main menu" + "exit_game_info": "Return to main menu", + "background_music_volume": "Background Music Volume" }, "chat": { "title": "Quick Chat", diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 376a5bcc2..3d38c9a34 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -47,6 +47,7 @@ import { } from "./Transport"; import { createCanvas } from "./Utils"; import { createRenderer, GameRenderer } from "./graphics/GameRenderer"; +import SoundManager from "./sound/SoundManager"; export interface LobbyConfig { serverConfig: ServerConfig; @@ -245,6 +246,7 @@ export class ClientGameRunner { } public start() { + SoundManager.playBackgroundMusic(); console.log("starting client game"); this.isActive = true; @@ -372,6 +374,7 @@ export class ClientGameRunner { } public stop() { + SoundManager.stopBackgroundMusic(); if (!this.isActive) return; this.isActive = false; diff --git a/src/client/graphics/layers/SettingsModal.ts b/src/client/graphics/layers/SettingsModal.ts index 72d4c6cf3..8c49995a4 100644 --- a/src/client/graphics/layers/SettingsModal.ts +++ b/src/client/graphics/layers/SettingsModal.ts @@ -9,11 +9,13 @@ import mouseIcon from "../../../../resources/images/MouseIconWhite.svg"; import ninjaIcon from "../../../../resources/images/NinjaIconWhite.svg"; import settingsIcon from "../../../../resources/images/SettingIconWhite.svg"; import treeIcon from "../../../../resources/images/TreeIconWhite.svg"; +import musicIcon from "../../../../resources/images/music.svg"; import { EventBus } from "../../../core/EventBus"; import { UserSettings } from "../../../core/game/UserSettings"; import { AlternateViewEvent, RefreshGraphicsEvent } from "../../InputHandler"; import { PauseGameEvent } from "../../Transport"; import { translateText } from "../../Utils"; +import SoundManager from "../../sound/SoundManager"; import { Layer } from "./Layer"; export class ShowSettingsModalEvent { @@ -45,6 +47,9 @@ export class SettingsModal extends LitElement implements Layer { wasPausedWhenOpened = false; init() { + SoundManager.setBackgroundMusicVolume( + this.userSettings.backgroundMusicVolume(), + ); this.eventBus.on(ShowSettingsModalEvent, (event) => { this.isVisible = event.isVisible; this.shouldPause = event.shouldPause; @@ -150,6 +155,13 @@ export class SettingsModal extends LitElement implements Layer { window.location.href = "/"; } + private onVolumeChange(event: Event) { + const volume = parseFloat((event.target as HTMLInputElement).value) / 100; + this.userSettings.setBackgroundMusicVolume(volume); + SoundManager.setBackgroundMusicVolume(volume); + this.requestUpdate(); + } + render() { if (!this.isVisible) { return null; @@ -187,6 +199,28 @@ export class SettingsModal extends LitElement implements Layer {