create EventsDisplay file

This commit is contained in:
evanpelle
2024-09-20 13:14:46 -07:00
parent 828675f087
commit a0353066c9
11 changed files with 279 additions and 31 deletions
+3 -1
View File
@@ -8,6 +8,7 @@ import {UILayer} from "./layers/UILayer";
import {EventBus} from "../../core/EventBus";
import {TransformHandler} from "./TransformHandler";
import {Layer} from "./layers/Layer";
import {EventsDisplay} from "./layers/EventsDisplay";
export function createRenderer(game: Game, eventBus: EventBus, clientID: ClientID): GameRenderer {
@@ -18,7 +19,8 @@ export function createRenderer(game: Game, eventBus: EventBus, clientID: ClientI
new TerrainLayer(game),
new TerritoryLayer(game, eventBus),
new NameLayer(game, game.config().theme(), transformHandler, clientID),
new UILayer(eventBus, game, game.config().theme(), clientID, transformHandler)
new UILayer(eventBus, game, clientID, transformHandler),
new EventsDisplay(eventBus, game, clientID)
]
return new GameRenderer(game, eventBus, canvas, transformHandler, layers)
+167
View File
@@ -0,0 +1,167 @@
import {nullable} from "zod";
import {EventBus} from "../../../core/EventBus";
import {AllianceRequestEvent, AllianceRequestReplyEvent, Game} from "../../../core/game/Game";
import {ClientID} from "../../../core/Schemas";
import {Layer} from "./Layer";
interface Event {
description: string;
buttons?: {
text: string
className: string
action: () => void
}[];
highlight?: boolean;
}
export class EventsDisplay implements Layer {
private container: HTMLElement;
private events: Event[];
private tableContainer: HTMLDivElement;
constructor(private eventBus: EventBus, private game: Game, private clientID: ClientID) {
const element = document.getElementById("app");
element.style.zIndex = "1000"
if (!element) throw new Error(`Container element with id app not found`);
this.container = element;
this.events = [];
this.createTableContainer()
}
init() {
this.eventBus.on(AllianceRequestEvent, a => this.onAllianceRequestEvent(a))
this.eventBus.on(AllianceRequestReplyEvent, a => this.onAllianceRequestReplyEvent(a))
this.renderTable()
}
tick() {
}
private createTableContainer() {
this.tableContainer = document.createElement('div');
this.tableContainer.id = 'table-container';
this.tableContainer.style.position = 'fixed';
this.tableContainer.style.bottom = '0px'; // Distance from bottom
this.tableContainer.style.right = '0px'; // Distance from right
this.tableContainer.style.zIndex = '1000';
this.tableContainer.style.backgroundColor = 'rgba(255, 255, 255, 0.0)';
this.tableContainer.style.padding = '20px';
this.tableContainer.style.boxShadow = '0 0 10px rgba(0,0,0,0.0)';
document.body.appendChild(this.tableContainer);
this.tableContainer.style.minWidth = '400px'; // Set minimum width
}
shouldTransform(): boolean {
return false
}
onAllianceRequestEvent(event: AllianceRequestEvent): void {
const myPlayer = this.game.playerByClientID(this.clientID)
if (myPlayer == null) {
return
}
if (event.allianceRequest.recipient() != myPlayer) {
return
}
this.addEvent({
description: `${event.allianceRequest.requestor().name()} requests an alliance!`,
buttons: [
{
text: "Accept",
className: "btn",
action: () => alert('accepted'),
},
{
text: "Reject",
className: "btn btn-info",
action: () => alert('rejected'),
}
],
highlight: true
});
this.renderTable()
}
onAllianceRequestReplyEvent(event: AllianceRequestReplyEvent) {
const myPlayer = this.game.playerByClientID(this.clientID)
if (myPlayer == null) {
return
}
if (event.allianceRequest.requestor() != myPlayer) {
return
}
this.addEvent({
description: `${event.allianceRequest.recipient().name()} ${event.accepted ? "accepted" : "rejected"} your alliance request`,
highlight: true
});
this.renderTable()
}
addEvent(event: Event): void {
this.events.push(event);
}
removeEvent(index: number): void {
this.events.splice(index, 1);
}
updateEvent(index: number, event: Event): void {
this.events[index] = event;
}
render(): void { }
renderTable(): void {
let tableHtml = `
<table class="events-table">
<tbody>
`;
this.events.forEach((event, eventIndex) => {
tableHtml += `
<tr${event.highlight ? ' style="background-color: rgba(255, 255, 0, 0.1);"' : ''}>
<td>
${event.description}
${event.buttons ? '<br>' + event.buttons.map((btn, btnIndex) =>
`<button class="${btn.className}" data-event-index="${eventIndex}" data-button-index="${btnIndex}">${btn.text}</button>`
).join('') : ''}
</td>
</tr>
`;
});
tableHtml += `
</tbody>
</table>
`;
this.tableContainer.innerHTML = tableHtml;
// Add event listeners to buttons
this.tableContainer.querySelectorAll('button').forEach(button => {
button.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation(); // Prevent the event from reaching the canvas
const target = e.target as HTMLElement;
const eventIndex = parseInt(target.getAttribute('data-event-index') || '');
const buttonIndex = parseInt(target.getAttribute('data-button-index') || '');
if (!isNaN(eventIndex) && !isNaN(buttonIndex)) {
const event = this.events[eventIndex];
const buttonAction = event.buttons?.[buttonIndex]?.action;
if (buttonAction) {
buttonAction();
// Optionally, you might want to remove the event after the action is performed
this.removeEvent(eventIndex);
this.renderTable(); // Re-render the table if you remove the event
}
}
});
});
}
}
+8 -17
View File
@@ -3,13 +3,11 @@ import {EventBus, GameEvent} from "../../../core/EventBus";
import {WinEvent} from "../../../core/execution/WinCheckExecution";
import {AllianceRequest, AllianceRequestReplyEvent, Game, Player} from "../../../core/game/Game";
import {ClientID} from "../../../core/Schemas";
import {renderTroops} from "../Utils";
import winModalHtml from '../WinModal.html';
import {RightClickEvent} from "../../InputHandler";
import {Layer} from "./Layer";
import {TransformHandler} from "../TransformHandler";
export class SendAllianceRequestEvent implements GameEvent {
export class SendAllianceRequestUIEvent implements GameEvent {
constructor(
public readonly requestor: Player,
public readonly recipient: Player
@@ -28,7 +26,12 @@ export class UILayer implements Layer {
private customMenu = document.getElementById('customMenu');
constructor(private eventBus: EventBus, private game: Game, private theme: Theme, private clientID: ClientID, private transformHandler: TransformHandler) {
constructor(
private eventBus: EventBus,
private game: Game,
private clientID: ClientID,
private transformHandler: TransformHandler
) {
}
@@ -63,7 +66,6 @@ export class UILayer implements Layer {
this.initRightClickMenu()
this.eventBus.on(WinEvent, (e) => this.onWinEvent(e))
this.eventBus.on(RightClickEvent, (e) => this.onRightClick(e))
this.eventBus.on(AllianceRequestReplyEvent, (e) => this.onAllianceRequestReplyEvent(e))
}
initRightClickMenu() {
@@ -193,17 +195,6 @@ export class UILayer implements Layer {
this.showWinModal(event.winner)
}
onAllianceRequestReplyEvent(event: AllianceRequestReplyEvent) {
if (event.allianceRequest.requestor().clientID() == this.clientID) {
const recipient = event.allianceRequest.recipient().name()
if (event.accepted) {
alert(`${recipient} accepted your alliance request`)
} else {
alert(`${recipient} rejected your alliance request`)
}
}
}
showWinModal(winner: Player) {
if (this.winModal) {
const message = this.winModal.querySelector('#winMessage');
@@ -265,7 +256,7 @@ export class UILayer implements Layer {
label: "Request Alliance",
action: (): void => {
this.eventBus.emit(
new SendAllianceRequestEvent(myPlayer, owner)
new SendAllianceRequestUIEvent(myPlayer, owner)
)
},
}