diff --git a/resources/QuickChat.json b/resources/QuickChat.json new file mode 100644 index 000000000..2853a5fc5 --- /dev/null +++ b/resources/QuickChat.json @@ -0,0 +1,39 @@ +{ + "help": [ + { + "key": "troops", + "text": "Please give me troops!", + "requiresPlayer": false + }, + { "key": "gold", "text": "Please give me golds!", "requiresPlayer": false }, + { + "key": "no_attack", + "text": "Please don't attack me!", + "requiresPlayer": false + } + ], + "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 } + ], + "greet": [{ "key": "hello", "text": "Hello!", "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 + } + ] +} diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 38498c9fa..c4300c33d 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -107,6 +107,15 @@ export class SendDonateTroopsIntentEvent implements GameEvent { ) {} } +export class SendQuickChatEvent implements GameEvent { + constructor( + public readonly sender: PlayerView, + public readonly recipient: PlayerView, + public readonly quickChatKey: string, + public readonly variables: { [key: string]: string }, + ) {} +} + export class SendEmbargoIntentEvent implements GameEvent { constructor( public readonly sender: PlayerView, @@ -195,6 +204,7 @@ export class Transport { this.eventBus.on(SendDonateTroopsIntentEvent, (e) => this.onSendDonateTroopIntent(e), ); + this.eventBus.on(SendQuickChatEvent, (e) => this.onSendQuickChatIntent(e)); this.eventBus.on(SendEmbargoIntentEvent, (e) => this.onSendEmbargoIntent(e), ); @@ -454,6 +464,16 @@ export class Transport { }); } + private onSendQuickChatIntent(event: SendQuickChatEvent) { + this.sendIntent({ + type: "quick_chat", + clientID: this.lobbyConfig.clientID, + recipient: event.recipient.id(), + quickChatKey: event.quickChatKey, + variables: event.variables, + }); + } + private onSendEmbargoIntent(event: SendEmbargoIntentEvent) { this.sendIntent({ type: "embargo", diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index 6af009d13..a566c041b 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -7,6 +7,7 @@ import { GameStartingModal } from "../gameStartingModal"; import { TransformHandler } from "./TransformHandler"; import { UIState } from "./UIState"; import { BuildMenu } from "./layers/BuildMenu"; +import { ChatModal } from "./layers/ChatModal"; import { ControlPanel } from "./layers/ControlPanel"; import { EmojiTable } from "./layers/EmojiTable"; import { EventsDisplay } from "./layers/EventsDisplay"; @@ -120,6 +121,13 @@ export function createRenderer( playerPanel.eventBus = eventBus; playerPanel.emojiTable = emojiTable; + const chatModal = document.querySelector("chat-modal") as ChatModal; + if (!(chatModal instanceof ChatModal)) { + console.error("chat modal not found"); + } + chatModal.g = game; + chatModal.eventBus = eventBus; + const layers: Layer[] = [ new TerrainLayer(game), new TerritoryLayer(game, eventBus), diff --git a/src/client/graphics/layers/ChatModal.ts b/src/client/graphics/layers/ChatModal.ts index 2d4dc149a..cbc0e8ec4 100644 --- a/src/client/graphics/layers/ChatModal.ts +++ b/src/client/graphics/layers/ChatModal.ts @@ -1,31 +1,22 @@ import { LitElement, html } from "lit"; import { customElement, query } from "lit/decorators.js"; -const quickChatPhrases: Record< - string, - Array<{ text: string; requiresPlayer: boolean }> -> = { - help: [ - { text: "Please give me troops!", requiresPlayer: false }, - { text: "Please give me golds!", requiresPlayer: false }, - { text: "Please don't attack me!", requiresPlayer: false }, - ], - attack: [ - { text: "Attack [P1]!", requiresPlayer: true }, - { text: "Launch a MIRV at [P1]!", requiresPlayer: true }, - { text: "Focus fire on [P1]!", requiresPlayer: true }, - { text: "Let's finish off [P1]!", requiresPlayer: true }, - ], - defend: [{ text: "Defend [P1]!", requiresPlayer: true }], - greet: [{ text: "Hello!", requiresPlayer: false }], - misc: [ - { text: "Let’s go!", requiresPlayer: false }, - { text: "Nice strategy!", requiresPlayer: false }, - { text: "This game is fun!", requiresPlayer: false }, - { text: "When will my PR finally get merged...?", requiresPlayer: false }, - ], +import { GameView, PlayerView } from "../../../core/game/GameView"; + +import quickChatData from "../../../../resources/QuickChat.json"; +import { EventBus } from "../../../core/EventBus"; +import { SendQuickChatEvent } from "../../Transport"; + +type QuickChatPhrase = { + key: string; + text: string; + requiresPlayer: boolean; }; +type QuickChatPhrases = Record; + +const quickChatPhrases: QuickChatPhrases = quickChatData; + @customElement("chat-modal") export class ChatModal extends LitElement { @query("o-modal") private modalEl!: HTMLElement & { @@ -61,6 +52,13 @@ export class ChatModal extends LitElement { private selectedPhraseText: string | null = null; private selectedPlayer: string | null = null; private selectedPhraseTemplate: string | null = null; + private selectedQuickChatKey: string | null = null; + + private recipient: PlayerView; + private sender: PlayerView; + public eventBus: EventBus; + + public g: GameView; quickChatPhrases: Record< string, @@ -195,9 +193,13 @@ export class ChatModal extends LitElement { this.requestUpdate(); } - private selectPhrase(phrase: { text: string; requiresPlayer: boolean }) { + 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.requiresPlayerSelection = phrase.requiresPlayer; this.selectedPlayer = null; @@ -219,6 +221,23 @@ export class ChatModal extends LitElement { private sendChatMessage() { console.log("Sent message:", this.previewText); + console.log("Sender:", this.sender); + console.log("Recipient:", this.recipient); + console.log("Key:", this.selectedQuickChatKey); + + if (this.sender && this.recipient && this.selectedQuickChatKey) { + const variables = this.selectedPlayer ? { P1: this.selectedPlayer } : {}; + + this.eventBus.emit( + new SendQuickChatEvent( + this.sender, + this.recipient, + this.selectedQuickChatKey, + variables, + ), + ); + } + this.previewText = null; this.selectedCategory = null; this.requiresPlayerSelection = false; @@ -242,7 +261,24 @@ export class ChatModal extends LitElement { return [...filtered, ...others]; } - public open() { + private getFullQuickChatKey(category: string, phraseKey: string): string { + return `${category}.${phraseKey}`; + } + + public open(sender?: PlayerView, recipient?: PlayerView) { + if (sender && recipient) { + console.log("Sent message:", recipient); + console.log("Sent message:", sender); + const alivePlayerNames = this.g + .players() + .filter((p) => p.isAlive()) + .map((p) => p.data.name); + + console.log("Alive player names:", alivePlayerNames); + this.players = alivePlayerNames; + this.recipient = recipient; + this.sender = sender; + } this.modalEl?.open(); } @@ -255,9 +291,11 @@ export class ChatModal extends LitElement { this.modalEl?.close(); } - static open() { - const modal = new ChatModal(); - document.body.appendChild(modal); - modal.open(); + public setRecipient(value: PlayerView) { + this.recipient = value; + } + + public setSender(value: PlayerView) { + this.sender = value; } } diff --git a/src/client/graphics/layers/PlayerPanel.ts b/src/client/graphics/layers/PlayerPanel.ts index 763fdf570..a3cea95e7 100644 --- a/src/client/graphics/layers/PlayerPanel.ts +++ b/src/client/graphics/layers/PlayerPanel.ts @@ -133,6 +133,11 @@ export class PlayerPanel extends LitElement implements Layer { }); } + private handleChat(e: Event, sender: PlayerView, other: PlayerView) { + this.ctModal.open(sender, other); + this.hide(); + } + private handleTargetClick(e: Event, other: PlayerView) { e.stopPropagation(); this.eventBus.emit(new SendTargetPlayerIntentEvent(other.id())); @@ -286,7 +291,7 @@ export class PlayerPanel extends LitElement implements Layer {