mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-03 11:50:48 +00:00
builds
This commit is contained in:
@@ -10,7 +10,7 @@ import { and, bfs, dist, generateID, manhattanDist } from "../core/Util";
|
||||
import { SendAttackIntentEvent, SendSpawnIntentEvent, Transport } from "./Transport";
|
||||
import { createCanvas } from "./Utils";
|
||||
import { MessageType } from '../core/game/Game';
|
||||
import { DisplayMessageEvent } from '../core/game/Game';
|
||||
import { DisplayMessageUpdate } from '../core/game/Game';
|
||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||
import { consolex, initRemoteSender } from "../core/Consolex";
|
||||
import { getConfig, getServerConfig } from "../core/configuration/Config";
|
||||
|
||||
@@ -30,7 +30,9 @@ export class SendBreakAllianceIntentEvent implements GameEvent {
|
||||
|
||||
export class SendAllianceReplyIntentEvent implements GameEvent {
|
||||
constructor(
|
||||
public readonly allianceRequest: AllianceRequest,
|
||||
// The original alliance requestor
|
||||
public readonly requestor: Player,
|
||||
public readonly recipient: Player,
|
||||
public readonly accepted: boolean
|
||||
) { }
|
||||
}
|
||||
@@ -262,8 +264,8 @@ export class Transport {
|
||||
this.sendIntent({
|
||||
type: "allianceRequestReply",
|
||||
clientID: this.lobbyConfig.clientID,
|
||||
requestor: event.allianceRequest.requestor().id(),
|
||||
recipient: event.allianceRequest.recipient().id(),
|
||||
requestor: event.requestor.id(),
|
||||
recipient: event.recipient.id(),
|
||||
accept: event.accepted,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,8 +2,13 @@ import { LitElement, html, css } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import {
|
||||
AllianceRequestReplyUpdate,
|
||||
AllianceRequestUpdate,
|
||||
AllPlayers,
|
||||
DisplayMessageUpdate,
|
||||
EmojiUpdate,
|
||||
MessageType,
|
||||
TargetPlayerUpdate,
|
||||
} from "../../../core/game/Game";
|
||||
import { ClientID } from "../../../core/Schemas";
|
||||
import { Layer } from "./Layer";
|
||||
@@ -140,13 +145,6 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
init() {
|
||||
this.eventBus.on(AllianceRequestEvent, a => this.onAllianceRequestEvent(a));
|
||||
this.eventBus.on(AllianceRequestReplyEvent, a => this.onAllianceRequestReplyEvent(a));
|
||||
this.eventBus.on(DisplayMessageEvent, e => this.onDisplayMessageEvent(e));
|
||||
this.eventBus.on(BrokeAllianceEvent, e => this.onBrokeAllianceEvent(e));
|
||||
this.eventBus.on(AllianceExpiredEvent, e => this.onAllianceExpiredEvent(e));
|
||||
this.eventBus.on(TargetPlayerEvent, e => this.onTargetPlayerEvent(e));
|
||||
this.eventBus.on(EmojiMessageEvent, e => this.onEmojiMessageEvent(e));
|
||||
}
|
||||
|
||||
tick() {
|
||||
@@ -186,9 +184,9 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
|
||||
renderLayer(): void { }
|
||||
|
||||
onDisplayMessageEvent(event: DisplayMessageEvent) {
|
||||
onDisplayMessageEvent(event: DisplayMessageUpdate) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (event.playerID != null && (!myPlayer || myPlayer.id() !== event.playerID)) {
|
||||
if (event.playerID != null && (!myPlayer || myPlayer.smallID() !== event.playerID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -196,122 +194,137 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
description: event.message,
|
||||
createdAt: this.game.ticks(),
|
||||
highlight: true,
|
||||
type: event.type,
|
||||
type: event.messageType,
|
||||
unsafeDescription: true,
|
||||
});
|
||||
}
|
||||
|
||||
onAllianceRequestEvent(event: AllianceRequestEvent) {
|
||||
onAllianceRequestEvent(update: AllianceRequestUpdate) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || event.allianceRequest.recipient() !== myPlayer) {
|
||||
if (!myPlayer || update.recipientID !== myPlayer.smallID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestor = this.game.playerBySmallID(update.requestorID)
|
||||
const recipient = this.game.playerBySmallID(update.recipientID)
|
||||
|
||||
this.addEvent({
|
||||
description: `${event.allianceRequest.requestor().name()} requests an alliance!`,
|
||||
description: `${requestor.name()} requests an alliance!`,
|
||||
buttons: [
|
||||
{
|
||||
text: "Accept",
|
||||
className: "btn",
|
||||
action: () => this.eventBus.emit(new SendAllianceReplyIntentEvent(event.allianceRequest, true)),
|
||||
action: () => this.eventBus.emit(
|
||||
new SendAllianceReplyIntentEvent(requestor, recipient, true)
|
||||
),
|
||||
},
|
||||
{
|
||||
text: "Reject",
|
||||
className: "btn btn-info",
|
||||
action: () => this.eventBus.emit(new SendAllianceReplyIntentEvent(event.allianceRequest, false)),
|
||||
action: () => this.eventBus.emit(
|
||||
new SendAllianceReplyIntentEvent(requestor, recipient, false)
|
||||
),
|
||||
}
|
||||
],
|
||||
highlight: true,
|
||||
type: MessageType.INFO,
|
||||
createdAt: this.game.ticks(),
|
||||
onDelete: () => this.eventBus.emit(new SendAllianceReplyIntentEvent(event.allianceRequest, false))
|
||||
onDelete: () => this.eventBus.emit(
|
||||
new SendAllianceReplyIntentEvent(requestor, recipient, false)
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
onAllianceRequestReplyEvent(event: AllianceRequestReplyEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || event.allianceRequest.requestor() !== myPlayer) {
|
||||
return;
|
||||
}
|
||||
// onAllianceRequestReplyEvent(event: AllianceRequestReplyUpdate) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer || event.allianceRequest.requestor() !== myPlayer) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
this.addEvent({
|
||||
description: `${event.allianceRequest.recipient().name()} ${event.accepted ? "accepted" : "rejected"} your alliance request`,
|
||||
type: event.accepted ? MessageType.SUCCESS : MessageType.ERROR,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
// this.addEvent({
|
||||
// description: `${event.allianceRequest.recipient().name()} ${event.accepted ? "accepted" : "rejected"} your alliance request`,
|
||||
// type: event.accepted ? MessageType.SUCCESS : MessageType.ERROR,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
|
||||
onBrokeAllianceEvent(event: BrokeAllianceEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
// onBrokeAllianceEvent(event: BrokeAllianceEvent) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer) return;
|
||||
|
||||
if (!event.betrayed.isTraitor() && event.traitor === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `You broke your alliance with ${event.betrayed.name()}, making you a TRAITOR`,
|
||||
type: MessageType.ERROR,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
} else if (event.betrayed === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `${event.traitor.name()}, broke their alliance with you`,
|
||||
type: MessageType.ERROR,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (!event.betrayed.isTraitor() && event.traitor === myPlayer) {
|
||||
// this.addEvent({
|
||||
// description: `You broke your alliance with ${event.betrayed.name()}, making you a TRAITOR`,
|
||||
// type: MessageType.ERROR,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// } else if (event.betrayed === myPlayer) {
|
||||
// this.addEvent({
|
||||
// description: `${event.traitor.name()}, broke their alliance with you`,
|
||||
// type: MessageType.ERROR,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
onAllianceExpiredEvent(event: AllianceExpiredEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
// onAllianceExpiredEvent(event: AllianceExpiredEvent) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer) return;
|
||||
|
||||
const other = event.player1 === myPlayer ? event.player2 : event.player2 === myPlayer ? event.player1 : null;
|
||||
if (!other || !myPlayer.isAlive() || !other.isAlive()) return;
|
||||
// const other = event.player1 === myPlayer ? event.player2 : event.player2 === myPlayer ? event.player1 : null;
|
||||
// if (!other || !myPlayer.isAlive() || !other.isAlive()) return;
|
||||
|
||||
this.addEvent({
|
||||
description: `Your alliance with ${other.name()} expired`,
|
||||
type: MessageType.WARN,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
// this.addEvent({
|
||||
// description: `Your alliance with ${other.name()} expired`,
|
||||
// type: MessageType.WARN,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
|
||||
onTargetPlayerEvent(event: TargetPlayerEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || !myPlayer.isAlliedWith(event.player)) return;
|
||||
// onTargetPlayerEvent(event: TargetPlayerUpdate) {
|
||||
// const other = this.game.playerBySmallID(event.playerID)
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer || !myPlayer.isAlliedWith(other)) return;
|
||||
|
||||
this.addEvent({
|
||||
description: `${event.player.name()} requests you attack ${event.target.name()}`,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
// const target = this.game.playerBySmallID(event.targetID)
|
||||
|
||||
onEmojiMessageEvent(event: EmojiMessageEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
// this.addEvent({
|
||||
// description: `${other.name()} requests you attack ${target.name()}`,
|
||||
// type: MessageType.INFO,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
|
||||
if (event.message.recipient === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `${event.message.sender.displayName()}:${event.message.emoji}`,
|
||||
unsafeDescription: true,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
} else if (event.message.sender === myPlayer && event.message.recipient !== AllPlayers) {
|
||||
this.addEvent({
|
||||
description: `Sent ${event.message.recipient.displayName()}: ${event.message.emoji}`,
|
||||
unsafeDescription: true,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// onEmojiMessageEvent(update: EmojiUpdate) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer) return;
|
||||
|
||||
// const recipient = update.recipientID == AllPlayers ? AllPlayers : this.game.playerBySmallID(update.recipientID)
|
||||
// const sender = this.game.playerBySmallID(update.senderID)
|
||||
|
||||
// if (recipient == myPlayer) {
|
||||
// this.addEvent({
|
||||
// description: `${sender.displayName()}:${update.message}`,
|
||||
// unsafeDescription: true,
|
||||
// type: MessageType.INFO,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// } else if (sender === myPlayer && recipient !== AllPlayers) {
|
||||
// this.addEvent({
|
||||
// description: `Sent ${recipient.displayName()}: ${update.message}`,
|
||||
// unsafeDescription: true,
|
||||
// type: MessageType.INFO,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
render() {
|
||||
if (this.events.length === 0) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { colord, Colord } from "colord";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { Unit, UnitEvent, Cell, Game, Tile, UnitType } from "../../../core/game/Game";
|
||||
import { Unit, Cell, Game, Tile, UnitType } from "../../../core/game/Game";
|
||||
import { bfs, dist, euclDist } from "../../../core/Util";
|
||||
import { Layer } from "./Layer";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
@@ -70,7 +70,7 @@ export class StructureLayer implements Layer {
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.game.units().forEach(u => this.handleUnitRendering(new UnitEvent(u, u.tile())))
|
||||
this.game.units().forEach(u => this.handleUnitRendering(u))
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -83,7 +83,7 @@ export class StructureLayer implements Layer {
|
||||
this.context = this.canvas.getContext("2d", { alpha: true });
|
||||
this.canvas.width = this.game.width();
|
||||
this.canvas.height = this.game.height();
|
||||
this.game.units().forEach(u => this.handleUnitRendering(new UnitEvent(u, u.tile())))
|
||||
this.game.units().forEach(u => this.handleUnitRendering(u))
|
||||
}
|
||||
|
||||
renderLayer(context: CanvasRenderingContext2D) {
|
||||
@@ -100,15 +100,15 @@ export class StructureLayer implements Layer {
|
||||
return unitType in this.unitConfigs;
|
||||
}
|
||||
|
||||
private handleUnitRendering(event: UnitEvent) {
|
||||
const unitType = event.unit.type();
|
||||
private handleUnitRendering(unit: Unit) {
|
||||
const unitType = unit.type();
|
||||
if (!this.isUnitTypeSupported(unitType)) return;
|
||||
|
||||
if (event.unit.isActive() && this.seenUnits.has(event.unit)) {
|
||||
if (unit.isActive() && this.seenUnits.has(unit)) {
|
||||
// Already rendered, so don't do anything.
|
||||
return
|
||||
}
|
||||
if (!event.unit.isActive() && !this.seenUnits.has(event.unit)) {
|
||||
if (!unit.isActive() && !this.seenUnits.has(unit)) {
|
||||
// Has been deleted and render is cleared so don't do anything.
|
||||
return
|
||||
}
|
||||
@@ -119,14 +119,14 @@ export class StructureLayer implements Layer {
|
||||
if (!config || !unitImage) return;
|
||||
|
||||
// Clear previous rendering
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), config.borderRadius))
|
||||
bfs(unit.tile(), euclDist(unit.tile(), config.borderRadius))
|
||||
.forEach(t => this.clearCell(t.cell()));
|
||||
|
||||
if (!event.unit.isActive()) {
|
||||
this.seenUnits.delete(event.unit)
|
||||
if (!unit.isActive()) {
|
||||
this.seenUnits.delete(unit)
|
||||
return;
|
||||
}
|
||||
this.seenUnits.add(event.unit)
|
||||
this.seenUnits.add(unit)
|
||||
|
||||
// Create temporary canvas for icon processing
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
@@ -138,19 +138,19 @@ export class StructureLayer implements Layer {
|
||||
tempContext.drawImage(unitImage, 0, 0);
|
||||
const iconData = tempContext.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
||||
|
||||
const cell = event.unit.tile().cell();
|
||||
const cell = unit.tile().cell();
|
||||
const startX = cell.x - Math.floor(tempCanvas.width / 2);
|
||||
const startY = cell.y - Math.floor(tempCanvas.height / 2);
|
||||
|
||||
// Draw border and territory
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), config.borderRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
bfs(unit.tile(), euclDist(unit.tile(), config.borderRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(unit.owner().info()), 255));
|
||||
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), config.territoryRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 130));
|
||||
bfs(unit.tile(), euclDist(unit.tile(), config.territoryRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(unit.owner().info()), 130));
|
||||
|
||||
// Draw the icon
|
||||
this.renderIcon(iconData, startX, startY, tempCanvas.width, tempCanvas.height, event.unit);
|
||||
this.renderIcon(iconData, startX, startY, tempCanvas.width, tempCanvas.height, unit);
|
||||
}
|
||||
|
||||
private renderIcon(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PriorityQueue } from "@datastructures-js/priority-queue";
|
||||
import { Cell, Game, Player, PlayerType, Tile, TileEvent, UnitEvent, UnitType } from "../../../core/game/Game";
|
||||
import { Cell, Game, Player, PlayerType, Tile, Unit, UnitType, UnitUpdate } from "../../../core/game/Game";
|
||||
import { PseudoRandom } from "../../../core/PseudoRandom";
|
||||
import { colord, Colord } from "colord";
|
||||
import { bfs, dist, euclDist, euclideanDist } from "../../../core/Util";
|
||||
@@ -197,19 +197,6 @@ export class TerritoryLayer implements Layer {
|
||||
this.imageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
|
||||
}
|
||||
|
||||
unitEvent(event: UnitEvent) {
|
||||
if (event.unit.type() == UnitType.DefensePost) {
|
||||
bfs(
|
||||
event.unit.tile(),
|
||||
dist(event.unit.tile(), this.game.config().defensePostRange())
|
||||
).forEach(t => {
|
||||
if (t.isBorder()) {
|
||||
this.enqueueTile(t)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
enqueueTile(tile: Tile) {
|
||||
this.tileToRenderQueue.push({ tile: tile, lastUpdate: this.game.ticks() + this.random.nextFloat(0, .5) })
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ enum Relationship {
|
||||
Enemy
|
||||
}
|
||||
|
||||
class UnitEvent {
|
||||
constructor(public unit: Unit, public oldTile: Tile) { }
|
||||
}
|
||||
|
||||
export class UnitLayer implements Layer {
|
||||
private canvas: HTMLCanvasElement;
|
||||
private context: CanvasRenderingContext2D;
|
||||
@@ -176,22 +180,22 @@ export class UnitLayer implements Layer {
|
||||
|
||||
}
|
||||
|
||||
private handleTradeShipEvent(unit: Unit) {
|
||||
const rel = this.relationship(unit)
|
||||
bfs(unit.oldTile, euclDist(unit.oldTile, 3)).forEach(t => {
|
||||
private handleTradeShipEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
bfs(event.oldTile, euclDist(event.oldTile, 3)).forEach(t => {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
if (unit.isActive()) {
|
||||
bfs(unit.tile(), dist(unit.tile(), 2))
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255));
|
||||
if (event.unit.isActive()) {
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 2))
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
if (unit.isActive()) {
|
||||
bfs(unit.tile(), dist(unit.tile(), 1))
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255));
|
||||
if (event.unit.isActive()) {
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 1))
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
}
|
||||
|
||||
private handleBoatEvent(event: Unit) {
|
||||
private handleBoatEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
if (!this.boatToTrail.has(event.unit)) {
|
||||
this.boatToTrail.set(event.unit, new Set<Tile>());
|
||||
|
||||
Reference in New Issue
Block a user