mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:00:43 +00:00
MLS for Quick Chat (#686)
## Description: <img width="842" alt="スクリーンショット 2025-05-09 17 51 27" src="https://github.com/user-attachments/assets/b9a2cb5b-74d2-4c07-aed2-01d719de6eb4" /> MLS ## Please complete the following: - [x] I have added screenshots for all UI updates - [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
This commit is contained in:
@@ -2,222 +2,180 @@
|
||||
"help": [
|
||||
{
|
||||
"key": "troops",
|
||||
"text": "Please give me troops!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "gold",
|
||||
"text": "Please give me gold!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "no_attack",
|
||||
"text": "Please don't attack me!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "sorry_attack",
|
||||
"text": "Sorry, I didn’t mean to attack.",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "alliance",
|
||||
"text": "Alliance?",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "help_defend",
|
||||
"text": "Help me defend against [P1]!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "team_up",
|
||||
"text": "Let’s team up against [P1]!",
|
||||
"requiresPlayer": true
|
||||
}
|
||||
],
|
||||
"attack": [
|
||||
{
|
||||
"key": "attack",
|
||||
"text": "Attack [P1]!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "mirv",
|
||||
"text": "Launch a MIRV at [P1]!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "focus",
|
||||
"text": "Focus fire on [P1]!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "finish",
|
||||
"text": "Let's finish off [P1]!",
|
||||
"requiresPlayer": true
|
||||
}
|
||||
],
|
||||
"defend": [
|
||||
{
|
||||
"key": "defend",
|
||||
"text": "Defend [P1]!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "dont_attack",
|
||||
"text": "Don’t attack [P1]!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "ally",
|
||||
"text": "[P1] is my ally!",
|
||||
"requiresPlayer": true
|
||||
}
|
||||
],
|
||||
"greet": [
|
||||
{
|
||||
"key": "hello",
|
||||
"text": "Hello!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "good_luck",
|
||||
"text": "Good luck!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "have_fun",
|
||||
"text": "Have fun!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "gg",
|
||||
"text": "GG!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "nice_to_meet",
|
||||
"text": "Nice to meet you!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "well_played",
|
||||
"text": "Well played!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "hi_again",
|
||||
"text": "Hi again!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "bye",
|
||||
"text": "Bye!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "thanks",
|
||||
"text": "Thanks!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "oops",
|
||||
"text": "Oops, wrong button!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "trust_me",
|
||||
"text": "You can trust me. Promise!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "trust_broken",
|
||||
"text": "I trusted you...",
|
||||
"requiresPlayer": false
|
||||
}
|
||||
],
|
||||
"misc": [
|
||||
{
|
||||
"key": "go",
|
||||
"text": "Let’s go!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "strategy",
|
||||
"text": "Nice strategy!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "fun",
|
||||
"text": "This game is fun!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "pr",
|
||||
"text": "When will my PR finally get merged...?",
|
||||
"requiresPlayer": false
|
||||
}
|
||||
],
|
||||
"warnings": [
|
||||
{
|
||||
"key": "strong",
|
||||
"text": "[P1] is strong.",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "weak",
|
||||
"text": "[P1] is weak.",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "mirv_soon",
|
||||
"text": "[P1] can launch a MIRV soon!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "number1_warning",
|
||||
"text": "The #1 player will win soon unless we team up!",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "stalemate",
|
||||
"text": "Let's make peace. This is a stalemate, we will both lose.",
|
||||
"requiresPlayer": false
|
||||
},
|
||||
{
|
||||
"key": "has_allies",
|
||||
"text": "[P1] has many allies.",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "no_allies",
|
||||
"text": "[P1] has no allies.",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "betrayed",
|
||||
"text": "[P1] betrayed their ally!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "getting_big",
|
||||
"text": "[P1] is growing too fast!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "danger_base",
|
||||
"text": "[P1] is unprotected!",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "saving_for_mirv",
|
||||
"text": "[P1] is saving up to launch a MIRV.",
|
||||
"requiresPlayer": true
|
||||
},
|
||||
{
|
||||
"key": "mirv_ready",
|
||||
"text": "[P1] has enough gold to launch a MIRV!",
|
||||
"requiresPlayer": true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -246,5 +246,78 @@
|
||||
"move_right_desc": "Move the camera to the right",
|
||||
"reset": "Reset",
|
||||
"unbind": "Unbind"
|
||||
},
|
||||
"chat": {
|
||||
"title": "Quick Chat",
|
||||
"to": "Sent {user}: {msg}",
|
||||
"from": "From {user}: {msg}",
|
||||
"category": "Category",
|
||||
"phrase": "Phrase",
|
||||
"player": "Player",
|
||||
"send": "Send",
|
||||
"search": "Search player...",
|
||||
"build": "Build your message...",
|
||||
"cat": {
|
||||
"help": "Help",
|
||||
"attack": "Attack",
|
||||
"defend": "Defend",
|
||||
"greet": "Greetings",
|
||||
"misc": "Miscellaneous",
|
||||
"warnings": "Warnings"
|
||||
},
|
||||
"help": {
|
||||
"troops": "Please give me troops!",
|
||||
"gold": "Please give me gold!",
|
||||
"no_attack": "Please don't attack me!",
|
||||
"sorry_attack": "Sorry, I didn’t mean to attack.",
|
||||
"alliance": "Alliance?",
|
||||
"help_defend": "Help me defend against [P1]!",
|
||||
"team_up": "Let’s team up against [P1]!"
|
||||
},
|
||||
"attack": {
|
||||
"attack": "Attack [P1]!",
|
||||
"mirv": "Launch a MIRV at [P1]!",
|
||||
"focus": "Focus fire on [P1]!",
|
||||
"finish": "Let's finish off [P1]!"
|
||||
},
|
||||
"defend": {
|
||||
"defend": "Defend [P1]!",
|
||||
"dont_attack": "Don’t attack [P1]!",
|
||||
"ally": "[P1] is my ally!"
|
||||
},
|
||||
"greet": {
|
||||
"hello": "Hello!",
|
||||
"good_luck": "Good luck!",
|
||||
"have_fun": "Have fun!",
|
||||
"gg": "GG!",
|
||||
"nice_to_meet": "Nice to meet you!",
|
||||
"well_played": "Well played!",
|
||||
"hi_again": "Hi again!",
|
||||
"bye": "Bye!",
|
||||
"thanks": "Thanks!",
|
||||
"oops": "Oops, wrong button!",
|
||||
"trust_me": "You can trust me. Promise!",
|
||||
"trust_broken": "I trusted you..."
|
||||
},
|
||||
"misc": {
|
||||
"go": "Let’s go!",
|
||||
"strategy": "Nice strategy!",
|
||||
"fun": "This game is fun!",
|
||||
"pr": "When will my PR finally get merged...?"
|
||||
},
|
||||
"warnings": {
|
||||
"strong": "[P1] is strong.",
|
||||
"weak": "[P1] is weak.",
|
||||
"mirv_soon": "[P1] can launch a MIRV soon!",
|
||||
"number1_warning": "The #1 player will win soon unless we team up!",
|
||||
"stalemate": "Let's make peace. This is a stalemate, we will both lose.",
|
||||
"has_allies": "[P1] has many allies.",
|
||||
"no_allies": "[P1] has no allies.",
|
||||
"betrayed": "[P1] betrayed their ally!",
|
||||
"getting_big": "[P1] is growing too fast!",
|
||||
"danger_base": "[P1] is unprotected!",
|
||||
"saving_for_mirv": "[P1] is saving up to launch a MIRV.",
|
||||
"mirv_ready": "[P1] has enough gold to launch a MIRV!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,5 +239,78 @@
|
||||
"continental": "大陸",
|
||||
"regional": "地域",
|
||||
"fantasy": "その他"
|
||||
},
|
||||
"chat": {
|
||||
"title": "クイックチャット",
|
||||
"category": "カテゴリ",
|
||||
"phrase": "フレーズ",
|
||||
"player": "プレイヤー",
|
||||
"to": "{user}に送信: {msg}",
|
||||
"from": "{user}から着信: {msg}",
|
||||
"send": "送信",
|
||||
"search": "プレイヤーを検索...",
|
||||
"build": "チャットを作成...",
|
||||
"cat": {
|
||||
"help": "支援要請",
|
||||
"attack": "攻撃",
|
||||
"defend": "防御",
|
||||
"greet": "挨拶",
|
||||
"misc": "その他",
|
||||
"warnings": "警告"
|
||||
},
|
||||
"help": {
|
||||
"troops": "援軍をください!",
|
||||
"gold": "お金をください!",
|
||||
"no_attack": "攻撃しないでください!",
|
||||
"sorry_attack": "ごめん、攻撃するつもりはなかった。",
|
||||
"alliance": "同盟を組みませんか?",
|
||||
"help_defend": "[P1] からの防衛を手伝って!",
|
||||
"team_up": "[P1] に対抗して協力しよう!"
|
||||
},
|
||||
"attack": {
|
||||
"attack": "[P1] を攻撃しよう!",
|
||||
"mirv": "[P1] にMIRVを撃とう!",
|
||||
"focus": "[P1] に集中攻撃しよう!",
|
||||
"finish": "[P1] を仕留めよう!"
|
||||
},
|
||||
"defend": {
|
||||
"defend": "[P1] を守って!",
|
||||
"dont_attack": "[P1] を攻撃しないで!",
|
||||
"ally": "[P1] は味方だ!"
|
||||
},
|
||||
"greet": {
|
||||
"hello": "こんにちは!",
|
||||
"good_luck": "頑張って!",
|
||||
"have_fun": "楽しもう!",
|
||||
"gg": "GG!",
|
||||
"nice_to_meet": "よろしく!",
|
||||
"well_played": "ナイスプレイ!",
|
||||
"hi_again": "また会ったね!",
|
||||
"bye": "バイバイ!",
|
||||
"thanks": "ありがとう!",
|
||||
"oops": "あっ、間違えた!",
|
||||
"trust_me": "信じてくれ、本当だ!",
|
||||
"trust_broken": "信じてたのに..."
|
||||
},
|
||||
"misc": {
|
||||
"go": "行こう!",
|
||||
"strategy": "いい作戦だ!",
|
||||
"fun": "このゲーム楽しい!",
|
||||
"pr": "わたしのPRいつマージされるんだろう...?"
|
||||
},
|
||||
"warnings": {
|
||||
"strong": "[P1] は強い。",
|
||||
"weak": "[P1] は弱い。",
|
||||
"mirv_soon": "[P1] がもうすぐMIRVを撃つぞ!",
|
||||
"number1_warning": "1位のプレイヤーが勝ちそうだ、協力しよう!",
|
||||
"stalemate": "和平しよう。膠着状態だ、両方負ける。",
|
||||
"has_allies": "[P1] には味方が多い。",
|
||||
"no_allies": "[P1] には味方がいない。",
|
||||
"betrayed": "[P1] は味方を裏切った!",
|
||||
"getting_big": "[P1] の勢力が急拡大中!",
|
||||
"danger_base": "[P1] の本拠地が無防備だ!",
|
||||
"saving_for_mirv": "[P1] はMIRVのために貯金してる。",
|
||||
"mirv_ready": "[P1] はMIRVを撃てるだけの金を持ってる!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import { GameView, PlayerView } from "../../../core/game/GameView";
|
||||
import quickChatData from "../../../../resources/QuickChat.json";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { SendQuickChatEvent } from "../../Transport";
|
||||
import { translateText } from "../../Utils";
|
||||
|
||||
type QuickChatPhrase = {
|
||||
key: string;
|
||||
text: string;
|
||||
requiresPlayer: boolean;
|
||||
};
|
||||
|
||||
@@ -58,12 +58,12 @@ export class ChatModal extends LitElement {
|
||||
};
|
||||
|
||||
private categories = [
|
||||
{ id: "help", name: "Help" },
|
||||
{ id: "attack", name: "Attack" },
|
||||
{ id: "defend", name: "Defend" },
|
||||
{ id: "greet", name: "Greetings" },
|
||||
{ id: "misc", name: "Miscellaneous" },
|
||||
{ id: "warnings", name: "Warnings" },
|
||||
{ id: "help" },
|
||||
{ id: "attack" },
|
||||
{ id: "defend" },
|
||||
{ id: "greet" },
|
||||
{ id: "misc" },
|
||||
{ id: "warnings" },
|
||||
];
|
||||
|
||||
private getPhrasesForCategory(categoryId: string) {
|
||||
@@ -83,10 +83,10 @@ export class ChatModal extends LitElement {
|
||||
|
||||
const displayPlayers = [...filteredPlayers, ...otherPlayers];
|
||||
return html`
|
||||
<o-modal title="Quick Chat">
|
||||
<o-modal title="${translateText("chat.title")}">
|
||||
<div class="chat-columns">
|
||||
<div class="chat-column">
|
||||
<div class="column-title">Category</div>
|
||||
<div class="column-title">${translateText("chat.category")}</div>
|
||||
${this.categories.map(
|
||||
(category) => html`
|
||||
<button
|
||||
@@ -96,7 +96,7 @@ export class ChatModal extends LitElement {
|
||||
: ""}"
|
||||
@click=${() => this.selectCategory(category.id)}
|
||||
>
|
||||
${category.name}
|
||||
${translateText(`chat.cat.${category.id}`)}
|
||||
</button>
|
||||
`,
|
||||
)}
|
||||
@@ -105,13 +105,18 @@ export class ChatModal extends LitElement {
|
||||
${this.selectedCategory
|
||||
? html`
|
||||
<div class="chat-column">
|
||||
<div class="column-title">Phrase</div>
|
||||
<div class="column-title">
|
||||
${translateText("chat.phrase")}
|
||||
</div>
|
||||
<div class="phrase-scroll-area">
|
||||
${this.getPhrasesForCategory(this.selectedCategory).map(
|
||||
(phrase) => html`
|
||||
<button
|
||||
class="chat-option-button ${this
|
||||
.selectedPhraseText === phrase.text
|
||||
.selectedPhraseText ===
|
||||
translateText(
|
||||
`chat.${this.selectedCategory}.${phrase.key}`,
|
||||
)
|
||||
? "selected"
|
||||
: ""}"
|
||||
@click=${() => this.selectPhrase(phrase)}
|
||||
@@ -127,12 +132,14 @@ export class ChatModal extends LitElement {
|
||||
${this.requiresPlayerSelection || this.selectedPlayer
|
||||
? html`
|
||||
<div class="chat-column">
|
||||
<div class="column-title">Player</div>
|
||||
<div class="column-title">
|
||||
${translateText("chat.player")}
|
||||
</div>
|
||||
|
||||
<input
|
||||
class="player-search-input"
|
||||
type="text"
|
||||
placeholder="Search player..."
|
||||
placeholder="${translateText("chat.search")}"
|
||||
.value=${this.playerSearchQuery}
|
||||
@input=${this.onPlayerSearchInput}
|
||||
/>
|
||||
@@ -158,7 +165,9 @@ export class ChatModal extends LitElement {
|
||||
</div>
|
||||
|
||||
<div class="chat-preview">
|
||||
${this.previewText || "Build your message..."}
|
||||
${this.previewText
|
||||
? translateText(this.previewText)
|
||||
: translateText("chat.build")}
|
||||
</div>
|
||||
<div class="chat-send">
|
||||
<button
|
||||
@@ -166,7 +175,7 @@ export class ChatModal extends LitElement {
|
||||
@click=${this.sendChatMessage}
|
||||
?disabled=${!this.previewText}
|
||||
>
|
||||
Send
|
||||
${translateText("chat.send")}
|
||||
</button>
|
||||
</div>
|
||||
</o-modal>
|
||||
@@ -183,20 +192,24 @@ export class ChatModal extends LitElement {
|
||||
}
|
||||
|
||||
private selectPhrase(phrase: QuickChatPhrase) {
|
||||
this.selectedPhraseTemplate = phrase.text;
|
||||
this.selectedPhraseText = phrase.text;
|
||||
this.selectedQuickChatKey = this.getFullQuickChatKey(
|
||||
this.selectedCategory!,
|
||||
phrase.key,
|
||||
);
|
||||
this.previewText = phrase.text;
|
||||
this.selectedPhraseTemplate = translateText(
|
||||
`chat.${this.selectedCategory}.${phrase.key}`,
|
||||
);
|
||||
this.selectedPhraseText = translateText(
|
||||
`chat.${this.selectedCategory}.${phrase.key}`,
|
||||
);
|
||||
this.previewText = `chat.${this.selectedCategory}.${phrase.key}`;
|
||||
this.requiresPlayerSelection = phrase.requiresPlayer;
|
||||
this.selectedPlayer = null;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private renderPhrasePreview(phrase: { text: string }) {
|
||||
return phrase.text.replace("[P1]", "___"); // 仮表示
|
||||
private renderPhrasePreview(phrase: { key: string }) {
|
||||
return translateText(`chat.${this.selectedCategory}.${phrase.key}`);
|
||||
}
|
||||
|
||||
private selectPlayer(player: string) {
|
||||
@@ -270,6 +283,7 @@ export class ChatModal extends LitElement {
|
||||
this.recipient = recipient;
|
||||
this.sender = sender;
|
||||
}
|
||||
this.requestUpdate();
|
||||
this.modalEl?.open();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
AllianceRequestUpdate,
|
||||
AttackUpdate,
|
||||
BrokeAllianceUpdate,
|
||||
DisplayChatMessageUpdate,
|
||||
DisplayMessageUpdate,
|
||||
EmojiUpdate,
|
||||
GameUpdateType,
|
||||
@@ -33,6 +34,8 @@ import { onlyImages } from "../../../core/Util";
|
||||
import { renderTroops } from "../../Utils";
|
||||
import { GoToPlayerEvent, GoToUnitEvent } from "./Leaderboard";
|
||||
|
||||
import { translateText } from "../../Utils";
|
||||
|
||||
interface Event {
|
||||
description: string;
|
||||
unsafeDescription?: boolean;
|
||||
@@ -77,6 +80,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
|
||||
private updateMap = new Map([
|
||||
[GameUpdateType.DisplayEvent, (u) => this.onDisplayMessageEvent(u)],
|
||||
[GameUpdateType.DisplayChatEvent, (u) => this.onDisplayChatEvent(u)],
|
||||
[GameUpdateType.AllianceRequest, (u) => this.onAllianceRequestEvent(u)],
|
||||
[
|
||||
GameUpdateType.AllianceRequestReply,
|
||||
@@ -187,6 +191,34 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
});
|
||||
}
|
||||
|
||||
onDisplayChatEvent(event: DisplayChatMessageUpdate) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (
|
||||
event.playerID === null ||
|
||||
!myPlayer ||
|
||||
myPlayer.smallID() !== event.playerID
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const baseMessage = translateText(`chat.${event.category}.${event.key}`);
|
||||
const translatedMessage = baseMessage.replace(
|
||||
/\[([^\]]+)\]/g,
|
||||
(_, key) => event.variables?.[key] || `[${key}]`,
|
||||
);
|
||||
|
||||
this.addEvent({
|
||||
description: translateText(event.isFrom ? "chat.from" : "chat.to", {
|
||||
user: event.recipient,
|
||||
msg: translatedMessage,
|
||||
}),
|
||||
createdAt: this.game.ticks(),
|
||||
highlight: true,
|
||||
type: MessageType.CHAT,
|
||||
unsafeDescription: false,
|
||||
});
|
||||
}
|
||||
|
||||
onAllianceRequestEvent(update: AllianceRequestUpdate) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || update.recipientID !== myPlayer.smallID()) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import quickChatData from "../../../resources/QuickChat.json";
|
||||
import { consolex } from "../Consolex";
|
||||
import { Execution, Game, MessageType, Player, PlayerID } from "../game/Game";
|
||||
import { Execution, Game, Player, PlayerID } from "../game/Game";
|
||||
|
||||
export class QuickChatExecution implements Execution {
|
||||
private sender: Player;
|
||||
@@ -38,16 +37,22 @@ export class QuickChatExecution implements Execution {
|
||||
tick(ticks: number): void {
|
||||
const message = this.getMessageFromKey(this.quickChatKey, this.variables);
|
||||
|
||||
this.mg.displayMessage(
|
||||
`${this.sender.name()}: ${message}`,
|
||||
MessageType.CHAT,
|
||||
this.mg.displayChat(
|
||||
message[1],
|
||||
message[0],
|
||||
this.variables,
|
||||
this.recipient.id(),
|
||||
true,
|
||||
this.recipient.name(),
|
||||
);
|
||||
|
||||
this.mg.displayMessage(
|
||||
`You sent to ${this.recipient.name()}: ${message}`,
|
||||
MessageType.CHAT,
|
||||
this.mg.displayChat(
|
||||
message[1],
|
||||
message[0],
|
||||
this.variables,
|
||||
this.sender.id(),
|
||||
false,
|
||||
this.recipient.name(),
|
||||
);
|
||||
|
||||
consolex.log(
|
||||
@@ -72,27 +77,8 @@ export class QuickChatExecution implements Execution {
|
||||
private getMessageFromKey(
|
||||
fullKey: string,
|
||||
vars: Record<string, string>,
|
||||
): string {
|
||||
// Key for translation
|
||||
const [category, key] = fullKey.split(".");
|
||||
const phrases = quickChatData[category];
|
||||
|
||||
if (!phrases) {
|
||||
consolex.warn(`QuickChat: Unknown category '${category}'`);
|
||||
return `[${fullKey}]`;
|
||||
}
|
||||
|
||||
const phraseObj = phrases.find((p) => p.key === key);
|
||||
if (!phraseObj) {
|
||||
consolex.warn(
|
||||
`QuickChat: Key '${key}' not found in category '${category}'`,
|
||||
);
|
||||
return `[${fullKey}]`;
|
||||
}
|
||||
|
||||
return phraseObj.text.replace(
|
||||
/\[(\w+)\]/g,
|
||||
(_, p1) => vars[p1] || `[${p1}]`,
|
||||
);
|
||||
): string[] {
|
||||
const translated = fullKey.split(".");
|
||||
return translated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,6 +509,15 @@ export interface Game extends GameMap {
|
||||
playerID: PlayerID | null,
|
||||
): void;
|
||||
|
||||
displayChat(
|
||||
message: string,
|
||||
category: string,
|
||||
variables: Record<string, string>,
|
||||
playerID: PlayerID | null,
|
||||
isFrom: boolean,
|
||||
recipient: string,
|
||||
): void;
|
||||
|
||||
// Nations
|
||||
nations(): Nation[];
|
||||
|
||||
|
||||
@@ -606,6 +606,28 @@ export class GameImpl implements Game {
|
||||
});
|
||||
}
|
||||
|
||||
displayChat(
|
||||
message: string,
|
||||
category: string,
|
||||
variables: Record<string, string> = {},
|
||||
playerID: PlayerID | null,
|
||||
isFrom: boolean | null = null,
|
||||
recipient: string,
|
||||
): void {
|
||||
let id = null;
|
||||
if (playerID != null) {
|
||||
id = this.player(playerID).smallID();
|
||||
}
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.DisplayChatEvent,
|
||||
key: message,
|
||||
category: category,
|
||||
variables: variables,
|
||||
playerID: id,
|
||||
isFrom: isFrom,
|
||||
recipient: recipient,
|
||||
});
|
||||
}
|
||||
addUnit(u: Unit) {
|
||||
this.unitGrid.addUnit(u);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export enum GameUpdateType {
|
||||
Unit,
|
||||
Player,
|
||||
DisplayEvent,
|
||||
DisplayChatEvent,
|
||||
AllianceRequest,
|
||||
AllianceRequestReply,
|
||||
BrokeAlliance,
|
||||
@@ -48,6 +49,7 @@ export type GameUpdate =
|
||||
| BrokeAllianceUpdate
|
||||
| AllianceExpiredUpdate
|
||||
| DisplayMessageUpdate
|
||||
| DisplayChatMessageUpdate
|
||||
| TargetPlayerUpdate
|
||||
| EmojiUpdate
|
||||
| WinUpdate
|
||||
@@ -157,6 +159,16 @@ export interface DisplayMessageUpdate {
|
||||
playerID: number | null;
|
||||
}
|
||||
|
||||
export type DisplayChatMessageUpdate = {
|
||||
type: GameUpdateType.DisplayChatEvent;
|
||||
key: string;
|
||||
category: string;
|
||||
variables?: Record<string, string>;
|
||||
playerID: number | null;
|
||||
isFrom: boolean;
|
||||
recipient: string;
|
||||
};
|
||||
|
||||
export interface WinUpdate {
|
||||
type: GameUpdateType.Win;
|
||||
allPlayersStats: AllPlayersStats;
|
||||
|
||||
Reference in New Issue
Block a user