mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 15:40:43 +00:00
Fixed quick chat text injection (#1144)
https://github.com/openfrontio/OpenFrontIO/issues/1035 Fixes #1035 - [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 - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors regression is found: .w. --------- Co-authored-by: Scott Anderson <scottanderson@users.noreply.github.com> Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
@@ -111,7 +111,7 @@ export class SendQuickChatEvent implements GameEvent {
|
||||
constructor(
|
||||
public readonly recipient: PlayerView,
|
||||
public readonly quickChatKey: string,
|
||||
public readonly variables: { [key: string]: string },
|
||||
public readonly target?: PlayerID,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ export class Transport {
|
||||
clientID: this.lobbyConfig.clientID,
|
||||
recipient: event.recipient.id(),
|
||||
quickChatKey: event.quickChatKey,
|
||||
variables: event.variables,
|
||||
target: event.target,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -29,16 +29,16 @@ export class ChatModal extends LitElement {
|
||||
return this;
|
||||
}
|
||||
|
||||
private players: string[] = [];
|
||||
private players: PlayerView[] = [];
|
||||
|
||||
private playerSearchQuery: string = "";
|
||||
private previewText: string | null = null;
|
||||
private requiresPlayerSelection: boolean = false;
|
||||
private selectedCategory: string | null = null;
|
||||
private selectedPhraseText: string | null = null;
|
||||
private selectedPlayer: string | null = null;
|
||||
private selectedPhraseTemplate: string | null = null;
|
||||
private selectedQuickChatKey: string | null = null;
|
||||
private selectedPlayer: PlayerView | null = null;
|
||||
|
||||
private recipient: PlayerView;
|
||||
private sender: PlayerView;
|
||||
@@ -71,17 +71,6 @@ export class ChatModal extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
const sortedPlayers = [...this.players].sort((a, b) => a.localeCompare(b));
|
||||
|
||||
const filteredPlayers = sortedPlayers.filter((player) =>
|
||||
player.toLowerCase().includes(this.playerSearchQuery),
|
||||
);
|
||||
|
||||
const otherPlayers = sortedPlayers.filter(
|
||||
(player) => !player.toLowerCase().includes(this.playerSearchQuery),
|
||||
);
|
||||
|
||||
const displayPlayers = [...filteredPlayers, ...otherPlayers];
|
||||
return html`
|
||||
<o-modal title="${translateText("chat.title")}">
|
||||
<div class="chat-columns">
|
||||
@@ -154,7 +143,7 @@ export class ChatModal extends LitElement {
|
||||
: ""}"
|
||||
@click=${() => this.selectPlayer(player)}
|
||||
>
|
||||
${player}
|
||||
${player.name()}
|
||||
</button>
|
||||
`,
|
||||
)}
|
||||
@@ -188,7 +177,6 @@ export class ChatModal extends LitElement {
|
||||
this.selectedPhraseText = null;
|
||||
this.previewText = null;
|
||||
this.requiresPlayerSelection = false;
|
||||
this.selectedPlayer = null;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
@@ -205,7 +193,6 @@ export class ChatModal extends LitElement {
|
||||
);
|
||||
this.previewText = `chat.${this.selectedCategory}.${phrase.key}`;
|
||||
this.requiresPlayerSelection = phrase.requiresPlayer;
|
||||
this.selectedPlayer = null;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
@@ -213,10 +200,10 @@ export class ChatModal extends LitElement {
|
||||
return translateText(`chat.${this.selectedCategory}.${phrase.key}`);
|
||||
}
|
||||
|
||||
private selectPlayer(player: string) {
|
||||
private selectPlayer(player: PlayerView) {
|
||||
if (this.previewText) {
|
||||
this.previewText =
|
||||
this.selectedPhraseTemplate?.replace("[P1]", player) ?? null;
|
||||
this.selectedPhraseTemplate?.replace("[P1]", player.name()) ?? null;
|
||||
this.selectedPlayer = player;
|
||||
this.requiresPlayerSelection = false;
|
||||
this.requestUpdate();
|
||||
@@ -230,15 +217,11 @@ export class ChatModal extends LitElement {
|
||||
console.log("Key:", this.selectedQuickChatKey);
|
||||
|
||||
if (this.sender && this.recipient && this.selectedQuickChatKey) {
|
||||
const variables: Record<string, string> = this.selectedPlayer
|
||||
? { P1: this.selectedPlayer }
|
||||
: {};
|
||||
|
||||
this.eventBus.emit(
|
||||
new SendQuickChatEvent(
|
||||
this.recipient,
|
||||
this.selectedQuickChatKey,
|
||||
variables,
|
||||
this.selectedPlayer?.id(),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -257,13 +240,15 @@ export class ChatModal extends LitElement {
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private getSortedFilteredPlayers(): string[] {
|
||||
const sorted = [...this.players].sort((a, b) => a.localeCompare(b));
|
||||
private getSortedFilteredPlayers(): PlayerView[] {
|
||||
const sorted = [...this.players].sort((a, b) =>
|
||||
a.name().localeCompare(b.name()),
|
||||
);
|
||||
const filtered = sorted.filter((p) =>
|
||||
p.toLowerCase().includes(this.playerSearchQuery),
|
||||
p.name().toLowerCase().includes(this.playerSearchQuery),
|
||||
);
|
||||
const others = sorted.filter(
|
||||
(p) => !p.toLowerCase().includes(this.playerSearchQuery),
|
||||
(p) => !p.name().toLowerCase().includes(this.playerSearchQuery),
|
||||
);
|
||||
return [...filtered, ...others];
|
||||
}
|
||||
@@ -276,13 +261,10 @@ export class ChatModal extends LitElement {
|
||||
if (sender && recipient) {
|
||||
console.log("Sent message:", recipient);
|
||||
console.log("Sent message:", sender);
|
||||
const alivePlayerNames = this.g
|
||||
this.players = this.g
|
||||
.players()
|
||||
.filter((p) => p.isAlive() && !(p.data.playerType === PlayerType.Bot))
|
||||
.map((p) => p.data.name);
|
||||
.filter((p) => p.isAlive() && p.data.playerType !== PlayerType.Bot);
|
||||
|
||||
console.log("Alive player names:", alivePlayerNames);
|
||||
this.players = alivePlayerNames;
|
||||
this.recipient = recipient;
|
||||
this.sender = sender;
|
||||
}
|
||||
@@ -295,7 +277,6 @@ export class ChatModal extends LitElement {
|
||||
this.selectedPhraseText = null;
|
||||
this.previewText = null;
|
||||
this.requiresPlayerSelection = false;
|
||||
this.selectedPlayer = null;
|
||||
this.modalEl?.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -212,10 +212,20 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
const baseMessage = translateText(`chat.${event.category}.${event.key}`);
|
||||
const translatedMessage = baseMessage.replace(
|
||||
/\[([^\]]+)\]/g,
|
||||
(_, key) => event.variables?.[key] || `[${key}]`,
|
||||
);
|
||||
let translatedMessage = baseMessage;
|
||||
if (event.target) {
|
||||
try {
|
||||
const targetPlayer = this.game.player(event.target);
|
||||
const targetName = targetPlayer?.name() ?? event.target;
|
||||
translatedMessage = baseMessage.replace("[P1]", targetName);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`Failed to resolve player for target ID '${event.target}'`,
|
||||
e,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.addEvent({
|
||||
description: translateText(event.isFrom ? "chat.from" : "chat.to", {
|
||||
|
||||
+1
-1
@@ -287,7 +287,7 @@ export const QuickChatIntentSchema = BaseIntentSchema.extend({
|
||||
type: z.literal("quick_chat"),
|
||||
recipient: ID,
|
||||
quickChatKey: QuickChatKeySchema,
|
||||
variables: z.record(SafeString).optional(),
|
||||
target: ID.optional(),
|
||||
});
|
||||
|
||||
const IntentSchema = z.union([
|
||||
|
||||
@@ -118,7 +118,7 @@ export class Executor {
|
||||
playerID,
|
||||
intent.recipient,
|
||||
intent.quickChatKey,
|
||||
intent.variables ?? {},
|
||||
intent.target,
|
||||
);
|
||||
default:
|
||||
throw new Error(`intent type ${intent} not found`);
|
||||
|
||||
@@ -12,7 +12,7 @@ export class QuickChatExecution implements Execution {
|
||||
private senderID: PlayerID,
|
||||
private recipientID: PlayerID,
|
||||
private quickChatKey: string,
|
||||
private variables: Record<string, string>,
|
||||
private target: PlayerID | undefined,
|
||||
) {}
|
||||
|
||||
init(mg: Game, ticks: number): void {
|
||||
@@ -35,12 +35,12 @@ export class QuickChatExecution implements Execution {
|
||||
}
|
||||
|
||||
tick(ticks: number): void {
|
||||
const message = this.getMessageFromKey(this.quickChatKey, this.variables);
|
||||
const message = this.getMessageFromKey(this.quickChatKey);
|
||||
|
||||
this.mg.displayChat(
|
||||
message[1],
|
||||
message[0],
|
||||
this.variables,
|
||||
this.target,
|
||||
this.recipient.id(),
|
||||
true,
|
||||
this.sender.name(),
|
||||
@@ -49,7 +49,7 @@ export class QuickChatExecution implements Execution {
|
||||
this.mg.displayChat(
|
||||
message[1],
|
||||
message[0],
|
||||
this.variables,
|
||||
this.target,
|
||||
this.sender.id(),
|
||||
false,
|
||||
this.recipient.name(),
|
||||
@@ -74,10 +74,7 @@ export class QuickChatExecution implements Execution {
|
||||
return false;
|
||||
}
|
||||
|
||||
private getMessageFromKey(
|
||||
fullKey: string,
|
||||
vars: Record<string, string>,
|
||||
): string[] {
|
||||
private getMessageFromKey(fullKey: string): string[] {
|
||||
const translated = fullKey.split(".");
|
||||
return translated;
|
||||
}
|
||||
|
||||
@@ -595,7 +595,7 @@ export interface Game extends GameMap {
|
||||
displayChat(
|
||||
message: string,
|
||||
category: string,
|
||||
variables: Record<string, string>,
|
||||
target: PlayerID | undefined,
|
||||
playerID: PlayerID | null,
|
||||
isFrom: boolean,
|
||||
recipient: string,
|
||||
|
||||
@@ -629,7 +629,7 @@ export class GameImpl implements Game {
|
||||
displayChat(
|
||||
message: string,
|
||||
category: string,
|
||||
variables: Record<string, string> = {},
|
||||
target: PlayerID | undefined,
|
||||
playerID: PlayerID | null,
|
||||
isFrom: boolean,
|
||||
recipient: string,
|
||||
@@ -642,7 +642,7 @@ export class GameImpl implements Game {
|
||||
type: GameUpdateType.DisplayChatEvent,
|
||||
key: message,
|
||||
category: category,
|
||||
variables: variables,
|
||||
target: target,
|
||||
playerID: id,
|
||||
isFrom,
|
||||
recipient: recipient,
|
||||
|
||||
@@ -168,7 +168,7 @@ export type DisplayChatMessageUpdate = {
|
||||
type: GameUpdateType.DisplayChatEvent;
|
||||
key: string;
|
||||
category: string;
|
||||
variables?: Record<string, string>;
|
||||
target: string | undefined;
|
||||
playerID: number | null;
|
||||
isFrom: boolean;
|
||||
recipient: string;
|
||||
|
||||
Reference in New Issue
Block a user