diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 6c2b5fcff..d97a29e17 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -24,7 +24,7 @@ import { } from "../core/game/GameUpdates"; import { GameView, PlayerView } from "../core/game/GameView"; import { loadTerrainMap, TerrainMapData } from "../core/game/TerrainMapLoader"; -import { UserSettings } from "../core/game/UserSettings"; +import { userSettings } from "../core/game/UserSettings"; import { WorkerClient } from "../core/worker/WorkerClient"; import { InputHandler, MouseMoveEvent, MouseUpEvent } from "./InputHandler"; import { endGame, startGame, startTime } from "./LocalPersistantStats"; @@ -64,7 +64,6 @@ export function joinLobby( `joinging lobby: gameID: ${lobbyConfig.gameID}, clientID: ${lobbyConfig.clientID}`, ); - const userSettings: UserSettings = new UserSettings(); startGame(lobbyConfig.gameID, lobbyConfig.gameStartInfo?.config ?? {}); const transport = new Transport(lobbyConfig, eventBus); @@ -108,7 +107,7 @@ export async function createClientGame( lobbyConfig: LobbyConfig, eventBus: EventBus, transport: Transport, - userSettings: UserSettings, + userSettings, terrainLoad: Promise | null, ): Promise { if (lobbyConfig.gameStartInfo === undefined) { diff --git a/src/client/DarkModeButton.ts b/src/client/DarkModeButton.ts index 65071408f..1ab9e8ab0 100644 --- a/src/client/DarkModeButton.ts +++ b/src/client/DarkModeButton.ts @@ -1,19 +1,18 @@ import { LitElement, html } from "lit"; import { customElement, state } from "lit/decorators.js"; -import { UserSettings } from "../core/game/UserSettings"; +import { userSettings } from "../core/game/UserSettings"; @customElement("dark-mode-button") export class DarkModeButton extends LitElement { - private userSettings: UserSettings = new UserSettings(); - @state() private darkMode: boolean = this.userSettings.darkMode(); + @state() private darkMode: boolean = userSettings.darkMode(); createRenderRoot() { return this; } toggleDarkMode() { - this.userSettings.toggleDarkMode(); - this.darkMode = this.userSettings.darkMode(); + userSettings.toggleDarkMode(); + this.darkMode = userSettings.darkMode(); } render() { diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index aa6a225b6..3cb68d4ac 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -1,6 +1,6 @@ import { EventBus, GameEvent } from "../core/EventBus"; import { UnitView } from "../core/game/GameView"; -import { UserSettings } from "../core/game/UserSettings"; +import { userSettings } from "../core/game/UserSettings"; export class MouseUpEvent implements GameEvent { constructor( @@ -105,8 +105,6 @@ export class InputHandler { private readonly PAN_SPEED = 5; private readonly ZOOM_SPEED = 10; - private userSettings: UserSettings = new UserSettings(); - constructor( private canvas: HTMLCanvasElement, private eventBus: EventBus, @@ -306,7 +304,7 @@ export class InputHandler { return; } - if (!this.userSettings.leftClickOpensMenu() || event.shiftKey) { + if (!userSettings.leftClickOpensMenu() || event.shiftKey) { this.eventBus.emit(new MouseUpEvent(event.x, event.y)); } else { this.eventBus.emit(new ContextMenuEvent(event.clientX, event.clientY)); diff --git a/src/client/Main.ts b/src/client/Main.ts index 22bd98b65..56d5563ad 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -4,7 +4,7 @@ import { consolex } from "../core/Consolex"; import { GameRecord, GameStartInfo } from "../core/Schemas"; import { getServerConfigFromClient } from "../core/configuration/ConfigLoader"; import { GameType } from "../core/game/Game"; -import { UserSettings } from "../core/game/UserSettings"; +import { userSettings } from "../core/game/UserSettings"; import { joinLobby } from "./ClientGameRunner"; import "./DarkModeButton"; import { DarkModeButton } from "./DarkModeButton"; @@ -55,7 +55,6 @@ class Client { private joinModal: JoinPrivateLobbyModal; private publicLobby: PublicLobby; private googleAds: NodeListOf; - private userSettings: UserSettings = new UserSettings(); constructor() {} @@ -232,7 +231,7 @@ class Client { } }); - if (this.userSettings.darkMode()) { + if (userSettings.darkMode()) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); diff --git a/src/client/UserSettingModal.ts b/src/client/UserSettingModal.ts index cfd9d21c1..d70fa92d6 100644 --- a/src/client/UserSettingModal.ts +++ b/src/client/UserSettingModal.ts @@ -1,7 +1,7 @@ import { LitElement, html } from "lit"; import { customElement, query, state } from "lit/decorators.js"; import { translateText } from "../client/Utils"; -import { UserSettings } from "../core/game/UserSettings"; +import { userSettings } from "../core/game/UserSettings"; import "./components/baseComponents/setting/SettingKeybind"; import { SettingKeybind } from "./components/baseComponents/setting/SettingKeybind"; import "./components/baseComponents/setting/SettingNumber"; @@ -10,8 +10,6 @@ import "./components/baseComponents/setting/SettingToggle"; @customElement("user-setting") export class UserSettingModal extends LitElement { - private userSettings: UserSettings = new UserSettings(); - @state() private settingsMode: "basic" | "keybinds" = "basic"; @state() private keybinds: Record = {}; @@ -82,7 +80,7 @@ export class UserSettingModal extends LitElement { return; } - this.userSettings.set("settings.darkMode", enabled); + userSettings.setDarkMode(enabled); if (enabled) { document.documentElement.classList.add("dark"); @@ -97,7 +95,7 @@ export class UserSettingModal extends LitElement { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; - this.userSettings.set("settings.emojis", enabled); + userSettings.setEmojis(true); console.log("🤡 Emojis:", enabled ? "ON" : "OFF"); } @@ -106,7 +104,7 @@ export class UserSettingModal extends LitElement { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; - this.userSettings.set("settings.specialEffects", enabled); + userSettings.setFxLayer(true); console.log("💥 Special effects:", enabled ? "ON" : "OFF"); } @@ -115,7 +113,7 @@ export class UserSettingModal extends LitElement { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; - this.userSettings.set("settings.anonymousNames", enabled); + userSettings.setAnonymousNames(true); console.log("🙈 Anonymous Names:", enabled ? "ON" : "OFF"); } @@ -124,7 +122,7 @@ export class UserSettingModal extends LitElement { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; - this.userSettings.set("settings.leftClickOpensMenu", enabled); + userSettings.setLeftClickOpensMenu(true); console.log("🖱️ Left Click Opens Menu:", enabled ? "ON" : "OFF"); this.requestUpdate(); @@ -221,7 +219,7 @@ export class UserSettingModal extends LitElement { label="${translateText("user_setting.dark_mode_label")}" description="${translateText("user_setting.dark_mode_desc")}" id="dark-mode-toggle" - .checked=${this.userSettings.darkMode()} + .checked=${userSettings.darkMode()} @change=${(e: CustomEvent<{ checked: boolean }>) => this.toggleDarkMode(e)} > @@ -231,7 +229,7 @@ export class UserSettingModal extends LitElement { label="${translateText("user_setting.emojis_label")}" description="${translateText("user_setting.emojis_desc")}" id="emoji-toggle" - .checked=${this.userSettings.emojis()} + .checked=${userSettings.emojis()} @change=${this.toggleEmojis} > @@ -240,7 +238,7 @@ export class UserSettingModal extends LitElement { label="${translateText("user_setting.special_effects_label")}" description="${translateText("user_setting.special_effects_desc")}" id="special-effect-toggle" - .checked=${this.userSettings.fxLayer()} + .checked=${userSettings.fxLayer()} @change=${this.toggleFxLayer} > @@ -249,7 +247,7 @@ export class UserSettingModal extends LitElement { label="${translateText("user_setting.left_click_label")}" description="${translateText("user_setting.left_click_desc")}" id="left-click-toggle" - .checked=${this.userSettings.leftClickOpensMenu()} + .checked=${userSettings.leftClickOpensMenu()} @change=${this.toggleLeftClickOpensMenu} > @@ -258,7 +256,7 @@ export class UserSettingModal extends LitElement { label="${translateText("user_setting.anonymous_names_label")}" description="${translateText("user_setting.anonymous_names_desc")}" id="anonymous-names-toggle" - .checked=${this.userSettings.anonymousNames()} + .checked=${userSettings.anonymousNames()} @change=${this.toggleAnonymousNames} > diff --git a/src/client/graphics/layers/OptionsMenu.ts b/src/client/graphics/layers/OptionsMenu.ts index 56e71605a..584d0e86f 100644 --- a/src/client/graphics/layers/OptionsMenu.ts +++ b/src/client/graphics/layers/OptionsMenu.ts @@ -4,7 +4,7 @@ import { EventBus } from "../../../core/EventBus"; import { GameType } from "../../../core/game/Game"; import { GameUpdateType } from "../../../core/game/GameUpdates"; import { GameView } from "../../../core/game/GameView"; -import { UserSettings } from "../../../core/game/UserSettings"; +import { userSettings } from "../../../core/game/UserSettings"; import { AlternateViewEvent, RefreshGraphicsEvent } from "../../InputHandler"; import { PauseGameEvent } from "../../Transport"; import { Layer } from "./Layer"; @@ -44,7 +44,6 @@ const secondsToHms = (d: number): string => { export class OptionsMenu extends LitElement implements Layer { public game: GameView; public eventBus: EventBus; - private userSettings: UserSettings = new UserSettings(); @state() private showPauseButton: boolean = true; @@ -96,32 +95,32 @@ export class OptionsMenu extends LitElement implements Layer { } private onToggleEmojisButtonClick() { - this.userSettings.toggleEmojis(); + userSettings.toggleEmojis(); this.requestUpdate(); } private onToggleSpecialEffectsButtonClick() { - this.userSettings.toggleFxLayer(); + userSettings.toggleFxLayer(); this.requestUpdate(); } private onToggleDarkModeButtonClick() { - this.userSettings.toggleDarkMode(); + userSettings.toggleDarkMode(); this.requestUpdate(); this.eventBus.emit(new RefreshGraphicsEvent()); } private onToggleRandomNameModeButtonClick() { - this.userSettings.toggleRandomName(); + userSettings.toggleRandomName(); } private onToggleFocusLockedButtonClick() { - this.userSettings.toggleFocusLocked(); + userSettings.toggleFocusLocked(); this.requestUpdate(); } private onToggleLeftClickOpensMenu() { - this.userSettings.toggleLeftClickOpenMenu(); + userSettings.toggleLeftClickOpenMenu(); } init() { @@ -200,41 +199,36 @@ export class OptionsMenu extends LitElement implements Layer { ${button({ onClick: this.onToggleEmojisButtonClick, title: "Toggle Emojis", - children: "🙂: " + (this.userSettings.emojis() ? "On" : "Off"), + children: "🙂: " + (userSettings.emojis() ? "On" : "Off"), })} ${button({ onClick: this.onToggleSpecialEffectsButtonClick, title: "Toggle Special effects", - children: "💥: " + (this.userSettings.fxLayer() ? "On" : "Off"), + children: "💥: " + (userSettings.fxLayer() ? "On" : "Off"), })} ${button({ onClick: this.onToggleDarkModeButtonClick, title: "Dark Mode", - children: "🌙: " + (this.userSettings.darkMode() ? "On" : "Off"), + children: "🌙: " + (userSettings.darkMode() ? "On" : "Off"), })} ${button({ onClick: this.onToggleRandomNameModeButtonClick, title: "Random name mode", - children: - "🥷: " + (this.userSettings.anonymousNames() ? "On" : "Off"), + children: "🥷: " + (userSettings.anonymousNames() ? "On" : "Off"), })} ${button({ onClick: this.onToggleLeftClickOpensMenu, title: "Left click", children: "🖱️: " + - (this.userSettings.leftClickOpensMenu() - ? "Opens menu" - : "Attack"), + (userSettings.leftClickOpensMenu() ? "Opens menu" : "Attack"), })} diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts index ab570918e..98f73b583 100644 --- a/src/core/game/GameView.ts +++ b/src/core/game/GameView.ts @@ -32,9 +32,7 @@ import { } from "./GameUpdates"; import { TerraNulliusImpl } from "./TerraNulliusImpl"; import { UnitGrid } from "./UnitGrid"; -import { UserSettings } from "./UserSettings"; - -const userSettings: UserSettings = new UserSettings(); +import { userSettings } from "./UserSettings"; export class UnitView { public _wasUpdated = true; diff --git a/src/core/game/UserSettings.ts b/src/core/game/UserSettings.ts index c7005573c..7706887e3 100644 --- a/src/core/game/UserSettings.ts +++ b/src/core/game/UserSettings.ts @@ -1,70 +1,115 @@ export class UserSettings { - get(key: string, defaultValue: boolean): boolean { + private cache: Record; + + constructor() { + this.cache = { + emojis: this.getFromStorage("settings.emojis", true), + anonymousNames: this.getFromStorage("settings.anonymousNames", false), + specialEffects: this.getFromStorage("settings.specialEffects", true), + darkMode: this.getFromStorage("settings.darkMode", false), + leftClickOpensMenu: this.getFromStorage( + "settings.leftClickOpensMenu", + false, + ), + focusLocked: this.getFromStorage("settings.focusLocked", true), + }; + } + + private getFromStorage(key: string, defaultValue: boolean): boolean { const value = localStorage.getItem(key); - if (!value) return defaultValue; - if (value === "true") return true; - if (value === "false") return false; - return defaultValue; } - set(key: string, value: boolean) { + private setToStorage(key: string, value: boolean) { localStorage.setItem(key, value ? "true" : "false"); } emojis() { - return this.get("settings.emojis", true); + return this.cache.emojis; } anonymousNames() { - return this.get("settings.anonymousNames", false); + return this.cache.anonymousNames; } - fxLayer() { - return this.get("settings.specialEffects", true); + return this.cache.specialEffects; } - darkMode() { - return this.get("settings.darkMode", false); + return this.cache.darkMode; } - leftClickOpensMenu() { - return this.get("settings.leftClickOpensMenu", false); + return this.cache.leftClickOpensMenu; } - focusLocked() { return false; - // TODO: renable when performance issues are fixed. - this.get("settings.focusLocked", true); - } + } // Keep disabled if buggy toggleLeftClickOpenMenu() { - this.set("settings.leftClickOpensMenu", !this.leftClickOpensMenu()); + this.cache.leftClickOpensMenu = !this.cache.leftClickOpensMenu; + this.setToStorage( + "settings.leftClickOpensMenu", + this.cache.leftClickOpensMenu, + ); } toggleFocusLocked() { - this.set("settings.focusLocked", !this.focusLocked()); + this.cache.focusLocked = !this.cache.focusLocked; + this.setToStorage("settings.focusLocked", this.cache.focusLocked); } toggleEmojis() { - this.set("settings.emojis", !this.emojis()); + this.cache.emojis = !this.cache.emojis; + this.setToStorage("settings.emojis", this.cache.emojis); } toggleRandomName() { - this.set("settings.anonymousNames", !this.anonymousNames()); + this.cache.anonymousNames = !this.cache.anonymousNames; + this.setToStorage("settings.anonymousNames", this.cache.anonymousNames); } toggleFxLayer() { - this.set("settings.specialEffects", !this.fxLayer()); + this.cache.specialEffects = !this.cache.specialEffects; + this.setToStorage("settings.specialEffects", this.cache.specialEffects); } toggleDarkMode() { - this.set("settings.darkMode", !this.darkMode()); - if (this.darkMode()) { + this.cache.darkMode = !this.cache.darkMode; + this.setToStorage("settings.darkMode", this.cache.darkMode); + if (this.cache.darkMode) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } } + setEmojis(value: boolean) { + this.cache.emojis = value; + this.setToStorage("settings.emojis", value); + } + + setAnonymousNames(value: boolean) { + this.cache.anonymousNames = value; + this.setToStorage("settings.anonymousNames", value); + } + + setFxLayer(value: boolean) { + this.cache.specialEffects = value; + this.setToStorage("settings.specialEffects", value); + } + + setDarkMode(value: boolean) { + this.cache.darkMode = value; + this.setToStorage("settings.darkMode", value); + if (value) { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } + } + + setLeftClickOpensMenu(value: boolean) { + this.cache.leftClickOpensMenu = value; + this.setToStorage("settings.leftClickOpensMenu", value); + } } +export const userSettings = new UserSettings();