Player can now disable emojis

This commit is contained in:
NewHappyRabbit
2025-02-13 21:27:52 +02:00
parent 0b9ab34b63
commit 08e1a7acf7
9 changed files with 141 additions and 38 deletions
+11 -4
View File
@@ -46,6 +46,7 @@ import { consolex, initRemoteSender } from "../core/Consolex";
import { getConfig, getServerConfig } from "../core/configuration/Config";
import { GameView, PlayerView } from "../core/game/GameView";
import { GameUpdateViewData } from "../core/game/GameUpdates";
import { UserSettings } from "../core/game/UserSettings";
export interface LobbyConfig {
flag: () => string;
@@ -75,6 +76,7 @@ export function joinLobby(
const serverConfig = getServerConfig();
const userSettings: UserSettings = new UserSettings();
let gameConfig: GameConfig = null;
if (lobbyConfig.gameType == GameType.Singleplayer) {
gameConfig = {
@@ -102,9 +104,13 @@ export function joinLobby(
if (message.type == "start") {
consolex.log("lobby: game started");
onjoin();
createClientGame(lobbyConfig, message.config, eventBus, transport).then(
(r) => r.start(),
);
createClientGame(
lobbyConfig,
message.config,
eventBus,
transport,
userSettings,
).then((r) => r.start());
}
};
transport.connect(onconnect, onmessage);
@@ -119,8 +125,9 @@ export async function createClientGame(
gameConfig: GameConfig,
eventBus: EventBus,
transport: Transport,
userSettings: UserSettings,
): Promise<ClientGameRunner> {
const config = getConfig(gameConfig);
const config = getConfig(gameConfig, userSettings);
const gameMap = await loadTerrainMap(gameConfig.gameMap);
const worker = new WorkerClient(
+1 -1
View File
@@ -322,7 +322,7 @@ export class NameLayer implements Layer {
emoji.recipientID == myPlayer?.smallID(),
);
if (emojis.length > 0) {
if (this.game.config().userSettings().emojis() && emojis.length > 0) {
if (!existingEmoji) {
const emojiDiv = document.createElement("div");
emojiDiv.setAttribute("data-icon", "emoji");
+76 -26
View File
@@ -6,11 +6,34 @@ import { GameType } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
import { Layer } from "./Layer";
import { GameUpdateType } from "../../../core/game/GameUpdates";
import { UserSettings } from "../../../core/game/UserSettings";
const button = ({
classes = "",
onClick = () => {},
title = "",
children,
}) => html`
<button
class="flex items-center justify-center p-1
bg-opacity-70 bg-gray-700 text-opacity-90 text-white
border-none rounded cursor-pointer
hover:bg-opacity-60 hover:bg-gray-600
transition-colors duration-200
text-sm lg:text-xl ${classes}"
@click=${onClick}
aria-label=${title}
title=${title}
>
${children}
</button>
`;
@customElement("options-menu")
export class OptionsMenu extends LitElement implements Layer {
public game: GameView;
public eventBus: EventBus;
private userSettings: UserSettings = new UserSettings();
@state()
private showPauseButton: boolean = true;
@@ -21,6 +44,9 @@ export class OptionsMenu extends LitElement implements Layer {
@state()
private timer: number = 0;
@state()
private showSettings: boolean = false;
private isVisible = false;
private hasWinner = false;
@@ -33,11 +59,26 @@ export class OptionsMenu extends LitElement implements Layer {
return this;
}
private onSettingsButtonClick() {
this.showSettings = !this.showSettings;
this.requestUpdate();
}
private onPauseButtonClick() {
this.isPaused = !this.isPaused;
this.eventBus.emit(new PauseGameEvent(this.isPaused));
}
private onToggleEmojisButtonClick() {
this.userSettings.toggleEmojis();
this.requestUpdate();
}
private onToggleDarkModeButtonClick() {
this.userSettings.toggleDarkMode();
this.requestUpdate();
}
init() {
console.log("init called from OptionsMenu");
this.showPauseButton =
@@ -71,20 +112,13 @@ export class OptionsMenu extends LitElement implements Layer {
<div
class="bg-opacity-60 bg-gray-900 p-1 lg:p-2 rounded-lg backdrop-blur-md"
>
<div class="flex items-center gap-1 lg:gap-2">
<button
class="${!this.showPauseButton ? "hidden" : ""}
w-8 h-8 lg:w-10 lg:h-10 flex items-center justify-center
bg-opacity-70 bg-gray-700 text-opacity-90 text-white
border-none rounded cursor-pointer
hover:bg-opacity-60 hover:bg-gray-600
transition-colors duration-200
text-sm lg:text-xl"
@click=${this.onPauseButtonClick}
aria-label="${this.isPaused ? "Resume game" : "Pause game"}"
>
${this.isPaused ? "▶" : "⏸"}
</button>
<div class="flex items-stretch gap-1 lg:gap-2">
${button({
classes: !this.showPauseButton ? "hidden" : "",
onClick: this.onPauseButtonClick,
title: this.isPaused ? "Resume game" : "Pause game",
children: this.isPaused ? "▶️" : "⏸",
})}
<div
class="w-14 h-8 lg:w-20 lg:h-10 flex items-center justify-center
bg-opacity-50 bg-gray-700 text-opacity-90 text-white
@@ -92,20 +126,36 @@ export class OptionsMenu extends LitElement implements Layer {
>
${this.timer}
</div>
<button
class="w-8 h-8 lg:w-10 lg:h-10 flex items-center justify-center
bg-opacity-70 bg-gray-700 text-opacity-90 text-white
border-none rounded cursor-pointer
hover:bg-opacity-60 hover:bg-gray-600
transition-colors duration-200
text-sm lg:text-xl"
@click=${this.onExitButtonClick}
aria-label="Exit game"
>
×
</button>
${button({
onClick: this.onExitButtonClick,
title: "Exit game",
children: "❌",
})}
${button({
onClick: this.onSettingsButtonClick,
title: "Settings",
children: "⚙️",
})}
</div>
</div>
<div
class="options-menu flex flex-wrap justify-around gap-y-3 mt-2 bg-opacity-60 bg-gray-900 p-1 lg:p-2 rounded-lg backdrop-blur-md ${!this
.showSettings
? "hidden"
: ""}"
>
${button({
onClick: this.onToggleEmojisButtonClick,
title: "Toggle Emojis",
children: "🙂: " + (this.userSettings.emojis() ? "On" : "Off"),
})}
<!-- ${button({
onClick: this.onToggleDarkModeButtonClick,
title: "Dark Mode",
children: "🌙: " + (this.userSettings.darkMode() ? "On" : "Off"),
})} -->
</div>
</div>
`;
}
+3 -1
View File
@@ -210,7 +210,9 @@
<top-bar></top-bar>
<player-panel></player-panel>
<div class="fixed right-0 top-0 z-50 flex flex-col w-32 sm:w-32 lg:w-48">
<div
class="flex flex-column gap-2 fixed right-0 top-0 z-50 flex flex-col w-32 sm:w-32 lg:w-48"
>
<options-menu></options-menu>
<player-info-overlay></player-info-overlay>
</div>
+3 -1
View File
@@ -24,6 +24,7 @@ import { createGame } from "./game/GameImpl";
import { loadTerrainMap as loadGameMap } from "./game/TerrainMapLoader";
import { ClientID, GameConfig, Turn } from "./Schemas";
import { GameUpdateViewData } from "./game/GameUpdates";
import { UserSettings } from "./game/UserSettings";
export async function createGameRunner(
gameID: string,
@@ -31,7 +32,8 @@ export async function createGameRunner(
clientID: ClientID,
callBack: (gu: GameUpdateViewData) => void,
): Promise<GameRunner> {
const config = getConfig(gameConfig);
const userSettings: UserSettings = new UserSettings();
const config = getConfig(gameConfig, userSettings);
const gameMap = await loadGameMap(gameConfig.gameMap);
const game = createGame(
gameMap.gameMap,
+8 -3
View File
@@ -20,20 +20,24 @@ import { DefaultConfig } from "./DefaultConfig";
import { DevConfig, DevServerConfig } from "./DevConfig";
import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { UserSettings } from "../game/UserSettings";
export enum GameEnv {
Dev,
Prod,
}
export function getConfig(gameConfig: GameConfig): Config {
export function getConfig(
gameConfig: GameConfig,
userSettings: UserSettings,
): Config {
const sc = getServerConfig();
switch (process.env.GAME_ENV) {
case "dev":
return new DevConfig(sc, gameConfig);
return new DevConfig(sc, gameConfig, userSettings);
case "preprod":
case "prod":
consolex.log("using prod config");
return new DefaultConfig(sc, gameConfig);
return new DefaultConfig(sc, gameConfig, userSettings);
default:
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`);
}
@@ -73,6 +77,7 @@ export interface Config {
spawnBots(): boolean;
creativeMode(): boolean;
numSpawnPhaseTurns(): number;
userSettings(): UserSettings;
startManpower(playerInfo: PlayerInfo): number;
populationIncreaseRate(player: Player | PlayerView): number;
+6
View File
@@ -14,6 +14,7 @@ import {
} from "../game/Game";
import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { UserSettings } from "../game/UserSettings";
import { GameConfig } from "../Schemas";
import { assertNever, within } from "../Util";
import { Config, ServerConfig, Theme } from "./Config";
@@ -35,6 +36,7 @@ export class DefaultConfig implements Config {
constructor(
private _serverConfig: ServerConfig,
private _gameConfig: GameConfig,
private _userSettings: UserSettings,
) {}
spawnImmunityDuration(): Tick {
return 5 * 10;
@@ -48,6 +50,10 @@ export class DefaultConfig implements Config {
return this._serverConfig;
}
userSettings(): UserSettings {
return this._userSettings;
}
difficultyModifier(difficulty: Difficulty): number {
switch (difficulty) {
case Difficulty.Easy:
+3 -2
View File
@@ -1,4 +1,5 @@
import { GameType, Player, PlayerInfo, UnitInfo, UnitType } from "../game/Game";
import { UserSettings } from "../game/UserSettings";
import { GameConfig } from "../Schemas";
import { ServerConfig } from "./Config";
import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
@@ -13,8 +14,8 @@ export class DevServerConfig extends DefaultServerConfig {
}
export class DevConfig extends DefaultConfig {
constructor(sc: ServerConfig, gc: GameConfig) {
super(sc, gc);
constructor(sc: ServerConfig, gc: GameConfig, us: UserSettings) {
super(sc, gc, us);
}
numSpawnPhaseTurns(): number {
+30
View File
@@ -0,0 +1,30 @@
export class UserSettings {
get(key: string, defaultValue: boolean) {
const value = localStorage.getItem(key);
if (!value) return defaultValue;
if (value === "true") return true;
if (value === "false") return false;
}
set(key: string, value: boolean) {
localStorage.setItem(key, value ? "true" : "false");
}
emojis() {
return this.get("settings.emojis", true);
}
darkMode() {
return this.get("settings.darkMode", false);
}
toggleEmojis() {
this.set("settings.emojis", !this.emojis());
}
toggleDarkMode() {
this.set("settings.darkMode", !this.darkMode());
}
}