import { html, LitElement } from "lit"; import { customElement, state } from "lit/decorators.js"; import { DirectiveResult } from "lit/directive.js"; import { unsafeHTML, UnsafeHTMLDirective } from "lit/directives/unsafe-html.js"; import { EventBus } from "../../../core/EventBus"; import { MessageType } from "../../../core/game/Game"; import { DisplayMessageUpdate, GameUpdateType, } from "../../../core/game/GameUpdates"; import { GameView } from "../../../core/game/GameView"; import { onlyImages } from "../../../core/Util"; import { Layer } from "./Layer"; type ChatEvent = { description: string; unsafeDescription?: boolean; createdAt: number; highlight?: boolean; }; @customElement("chat-display") export class ChatDisplay extends LitElement implements Layer { public eventBus: EventBus; public game: GameView; private active = false; @state() private _hidden = false; @state() private newEvents = 0; @state() private chatEvents: ChatEvent[] = []; private toggleHidden() { this._hidden = !this._hidden; if (this._hidden) { this.newEvents = 0; } this.requestUpdate(); } private addEvent(event: ChatEvent) { this.chatEvents = [...this.chatEvents, event]; if (this._hidden) { this.newEvents++; } this.requestUpdate(); } private removeEvent(index: number) { this.chatEvents = [ ...this.chatEvents.slice(0, index), ...this.chatEvents.slice(index + 1), ]; } onDisplayMessageEvent(event: DisplayMessageUpdate) { if (event.messageType !== MessageType.CHAT) return; const myPlayer = this.game.myPlayer(); if ( event.playerID !== null && (!myPlayer || myPlayer.smallID() !== event.playerID) ) { return; } this.addEvent({ description: event.message, createdAt: this.game.ticks(), highlight: true, unsafeDescription: true, }); } init() {} tick() { // this.active = true; const updates = this.game.updatesSinceLastTick(); if (updates === null) return; const messages = updates[GameUpdateType.DisplayEvent] as | DisplayMessageUpdate[] | undefined; if (messages) { for (const msg of messages) { if (msg.messageType === MessageType.CHAT) { const myPlayer = this.game.myPlayer(); if ( msg.playerID !== null && (!myPlayer || myPlayer.smallID() !== msg.playerID) ) { continue; } this.chatEvents = [ ...this.chatEvents, { description: msg.message, unsafeDescription: true, createdAt: this.game.ticks(), }, ]; } } } if (this.chatEvents.length > 100) { this.chatEvents = this.chatEvents.slice(-100); } this.requestUpdate(); } private getChatContent( chat: ChatEvent, ): string | DirectiveResult { return chat.unsafeDescription ? unsafeHTML(onlyImages(chat.description)) : chat.description; } render() { if (!this.active) { return html``; } return html` Hide Chat ${this.newEvents} ${this.chatEvents.map( (chat) => html` ${this.getChatContent(chat)} `, )} `; } createRenderRoot() { return this; } }