mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:00:44 +00:00
Anonymized/hidden names on lobby preview (#2965)
Resolves #2962 ## Description: Anonymize lobby preview player names when “Hidden names” is enabled, using the same deterministic mapping as in-game. <img width="864" height="618" alt="スクリーンショット 2026-01-20 21 13 19" src="https://github.com/user-attachments/assets/30ebe155-c66e-49a5-8957-f8ec0a1ccd76" /> <img width="668" height="341" alt="スクリーンショット 2026-01-20 21 13 27" src="https://github.com/user-attachments/assets/6ef74d98-ea2f-4156-a321-306acf012672" /> ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: aotumuri Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
This commit is contained in:
@@ -653,6 +653,7 @@ export class HostLobbyModal extends BaseModal {
|
||||
.gameMode=${this.gameMode}
|
||||
.clients=${this.clients}
|
||||
.lobbyCreatorClientID=${this.lobbyCreatorClientID}
|
||||
.currentClientID=${this.lobbyCreatorClientID}
|
||||
.teamCount=${this.teamCount}
|
||||
.nationCount=${this.nationCount}
|
||||
.disableNations=${this.disableNations}
|
||||
|
||||
@@ -28,6 +28,7 @@ export class JoinPrivateLobbyModal extends BaseModal {
|
||||
@state() private gameConfig: GameConfig | null = null;
|
||||
@state() private lobbyCreatorClientID: string | null = null;
|
||||
@state() private currentLobbyId: string = "";
|
||||
@state() private currentClientID: string = "";
|
||||
@state() private nationCount: number = 0;
|
||||
|
||||
private playersInterval: NodeJS.Timeout | null = null;
|
||||
@@ -101,6 +102,7 @@ export class JoinPrivateLobbyModal extends BaseModal {
|
||||
.gameMode=${this.gameConfig?.gameMode ?? GameMode.FFA}
|
||||
.clients=${this.players}
|
||||
.lobbyCreatorClientID=${this.lobbyCreatorClientID}
|
||||
.currentClientID=${this.currentClientID}
|
||||
.teamCount=${this.gameConfig?.playerTeams ?? 2}
|
||||
.nationCount=${this.nationCount}
|
||||
.disableNations=${this.gameConfig?.disableNations ?? false}
|
||||
@@ -290,6 +292,7 @@ export class JoinPrivateLobbyModal extends BaseModal {
|
||||
this.hasJoined = false;
|
||||
this.message = "";
|
||||
this.currentLobbyId = "";
|
||||
this.currentClientID = "";
|
||||
this.nationCount = 0;
|
||||
|
||||
this.leaveLobbyOnClose = true;
|
||||
@@ -418,6 +421,7 @@ export class JoinPrivateLobbyModal extends BaseModal {
|
||||
this.showMessage(translateText("private_lobby.joined_waiting"));
|
||||
this.message = "";
|
||||
this.hasJoined = true;
|
||||
this.currentClientID = generateID();
|
||||
|
||||
// If the modal closes as part of joining the game, do not leave the lobby
|
||||
this.leaveLobbyOnClose = false;
|
||||
@@ -426,7 +430,7 @@ export class JoinPrivateLobbyModal extends BaseModal {
|
||||
new CustomEvent("join-lobby", {
|
||||
detail: {
|
||||
gameID: lobbyId,
|
||||
clientID: generateID(),
|
||||
clientID: this.currentClientID,
|
||||
} as JoinLobbyEvent,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
@@ -477,12 +481,13 @@ export class JoinPrivateLobbyModal extends BaseModal {
|
||||
return "version_mismatch";
|
||||
}
|
||||
|
||||
this.currentClientID = generateID();
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("join-lobby", {
|
||||
detail: {
|
||||
gameID: lobbyId,
|
||||
gameRecord: parsed.data,
|
||||
clientID: generateID(),
|
||||
clientID: this.currentClientID,
|
||||
} as JoinLobbyEvent,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
|
||||
@@ -15,7 +15,9 @@ import {
|
||||
} from "../../core/game/Game";
|
||||
import { getCompactMapNationCount } from "../../core/game/NationCreation";
|
||||
import { assignTeamsLobbyPreview } from "../../core/game/TeamAssignment";
|
||||
import { UserSettings } from "../../core/game/UserSettings";
|
||||
import { ClientInfo, TeamCountConfig } from "../../core/Schemas";
|
||||
import { createRandomName } from "../../core/Util";
|
||||
import { translateText } from "../Utils";
|
||||
|
||||
export interface TeamPreviewData {
|
||||
@@ -30,6 +32,7 @@ export class LobbyTeamView extends LitElement {
|
||||
@state() private teamPreview: TeamPreviewData[] = [];
|
||||
@state() private teamMaxSize: number = 0;
|
||||
@property({ type: String }) lobbyCreatorClientID: string = "";
|
||||
@property({ type: String }) currentClientID: string = "";
|
||||
@property({ attribute: "team-count" }) teamCount: TeamCountConfig = 2;
|
||||
@property({ type: Function }) onKickPlayer?: (clientID: string) => void;
|
||||
@property({ type: Number }) nationCount: number = 0;
|
||||
@@ -38,6 +41,7 @@ export class LobbyTeamView extends LitElement {
|
||||
|
||||
private theme: PastelTheme = new PastelTheme();
|
||||
@state() private showTeamColors: boolean = false;
|
||||
private userSettings: UserSettings = new UserSettings();
|
||||
|
||||
willUpdate(changedProperties: Map<string, any>) {
|
||||
// Recompute team preview when relevant properties change
|
||||
@@ -108,12 +112,14 @@ export class LobbyTeamView extends LitElement {
|
||||
${repeat(
|
||||
this.clients,
|
||||
(c) => c.clientID ?? c.username,
|
||||
(client) =>
|
||||
html`<div
|
||||
(client) => {
|
||||
const displayName = this.displayUsername(client);
|
||||
return html`<div
|
||||
class="px-2 py-1 rounded-sm bg-gray-700/70 mb-1 text-xs text-white"
|
||||
>
|
||||
${client.username}
|
||||
</div>`,
|
||||
${displayName}
|
||||
</div>`;
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col gap-3 md:gap-4 md:pr-1">
|
||||
@@ -151,9 +157,10 @@ export class LobbyTeamView extends LitElement {
|
||||
return html`${repeat(
|
||||
this.clients,
|
||||
(c) => c.clientID ?? c.username,
|
||||
(client) =>
|
||||
html`<span class="player-tag">
|
||||
<span class="text-white">${client.username}</span>
|
||||
(client) => {
|
||||
const displayName = this.displayUsername(client);
|
||||
return html`<span class="player-tag">
|
||||
<span class="text-white">${displayName}</span>
|
||||
${client.clientID === this.lobbyCreatorClientID
|
||||
? html`<span class="host-badge"
|
||||
>(${translateText("host_modal.host_badge")})</span
|
||||
@@ -163,13 +170,14 @@ export class LobbyTeamView extends LitElement {
|
||||
class="remove-player-btn"
|
||||
@click=${() => this.onKickPlayer?.(client.clientID)}
|
||||
aria-label=${translateText("host_modal.remove_player", {
|
||||
username: client.username,
|
||||
username: displayName,
|
||||
})}
|
||||
>
|
||||
×
|
||||
</button>`
|
||||
: html``}
|
||||
</span>`,
|
||||
</span>`;
|
||||
},
|
||||
)} `;
|
||||
}
|
||||
|
||||
@@ -207,11 +215,12 @@ export class LobbyTeamView extends LitElement {
|
||||
: repeat(
|
||||
preview.players,
|
||||
(p) => p.clientID ?? p.username,
|
||||
(p) =>
|
||||
html` <div
|
||||
(p) => {
|
||||
const displayName = this.displayUsername(p);
|
||||
return html` <div
|
||||
class="bg-gray-700/70 px-2 py-1 rounded-sm text-xs flex items-center justify-between"
|
||||
>
|
||||
<span class="truncate text-white">${p.username}</span>
|
||||
<span class="truncate text-white">${displayName}</span>
|
||||
${p.clientID === this.lobbyCreatorClientID
|
||||
? html`<span class="ml-2 text-[11px] text-green-300"
|
||||
>(${translateText("host_modal.host_badge")})</span
|
||||
@@ -223,14 +232,15 @@ export class LobbyTeamView extends LitElement {
|
||||
aria-label=${translateText(
|
||||
"host_modal.remove_player",
|
||||
{
|
||||
username: p.username,
|
||||
username: displayName,
|
||||
},
|
||||
)}
|
||||
>
|
||||
×
|
||||
</button>`
|
||||
: html``}
|
||||
</div>`,
|
||||
</div>`;
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -353,4 +363,18 @@ export class LobbyTeamView extends LitElement {
|
||||
}
|
||||
return getCompactMapNationCount(this.nationCount, this.isCompactMap);
|
||||
}
|
||||
|
||||
private displayUsername(client: ClientInfo): string {
|
||||
if (!this.userSettings.anonymousNames()) {
|
||||
return client.username;
|
||||
}
|
||||
|
||||
if (this.currentClientID && client.clientID === this.currentClientID) {
|
||||
return client.username;
|
||||
}
|
||||
|
||||
return (
|
||||
createRandomName(client.username, PlayerType.Human) ?? client.username
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user