diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts
index cfe48c30a..620820a57 100644
--- a/src/client/ClientGameRunner.ts
+++ b/src/client/ClientGameRunner.ts
@@ -225,12 +225,10 @@ export class ClientGameRunner {
private gameView: GameView,
) {
this.lastMessageTime = Date.now();
-
- this.eventBus.on(GoToPositionEvent, (e) => this.onGoToPosition(e));
- }
-
- private onGoToPosition(event: GoToPositionEvent) {
- this.eventBus.emit(new GoToPositionEvent(event.x, event.y));
+ // If forwarding is needed, emit a different event or handle directly
+ this.eventBus.on(GoToPositionEvent, (e) => {
+ // Handle position navigation here instead of re-emitting
+ });
}
private saveGame(update: WinUpdate) {
diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts
index d8d7c1a63..464d5e362 100644
--- a/src/client/graphics/GameRenderer.ts
+++ b/src/client/graphics/GameRenderer.ts
@@ -428,7 +428,7 @@ export class GameRenderer {
handleTransformState(false, isTransformActive); // Ensure context is clean after rendering
this.transformHandler.resetChanged();
- requestAnimationFrame(() => this.renderGame());
+ this.rafId = requestAnimationFrame(() => this.renderGame());
const duration = performance.now() - start;
const layerDurations = FrameProfiler.consume();
diff --git a/src/client/graphics/layers/ChatDisplay.ts b/src/client/graphics/layers/ChatDisplay.ts
index 920a4d114..40e5589ad 100644
--- a/src/client/graphics/layers/ChatDisplay.ts
+++ b/src/client/graphics/layers/ChatDisplay.ts
@@ -103,6 +103,8 @@ export class ChatDisplay extends LitElement implements Layer {
description: msg.message,
unsafeDescription: true,
createdAt: this.game.ticks(),
+ x: msg.x, // Transfer coordinates
+ y: msg.y, // Transfer coordinates
},
];
}
@@ -124,7 +126,6 @@ export class ChatDisplay extends LitElement implements Layer {
: chat.description;
}
- // ...
render() {
if (!this.active) {
return html``;
@@ -178,15 +179,16 @@ export class ChatDisplay extends LitElement implements Layer {
${chat.x !== undefined && chat.y !== undefined
? html`
-
this.eventBus.emit(
new GoToPositionEvent(chat.x!, chat.y!),
)}
>
${this.getChatContent(chat)}
-
+
`
: this.getChatContent(chat)}
|
diff --git a/src/client/graphics/layers/FxLayer.ts b/src/client/graphics/layers/FxLayer.ts
index 4556157b3..a50b03c8a 100644
--- a/src/client/graphics/layers/FxLayer.ts
+++ b/src/client/graphics/layers/FxLayer.ts
@@ -350,12 +350,19 @@ export class FxLayer implements Layer {
this.allFx.push(shockwave);
}
- private pingEventCleanup?: () => void;
destroy() {
- if (this.pingEventCleanup) {
- this.pingEventCleanup();
- this.pingEventCleanup = undefined;
+ // End all active effects
+ for (const fx of this.boatTargetFxByUnitId.values()) {
+ (fx as any).end?.();
}
+ for (const fx of this.nukeTargetFxByUnitId.values()) {
+ fx.end();
+ }
+
+ // Clear collections
+ this.allFx = [];
+ this.boatTargetFxByUnitId.clear();
+ this.nukeTargetFxByUnitId.clear();
}
async init() {
this.redraw();
diff --git a/src/client/graphics/layers/PingMarkerLayer.ts b/src/client/graphics/layers/PingMarkerLayer.ts
index f92701291..5d5640151 100644
--- a/src/client/graphics/layers/PingMarkerLayer.ts
+++ b/src/client/graphics/layers/PingMarkerLayer.ts
@@ -46,7 +46,7 @@ class Ping {
this.sprite = new PIXI.Sprite(texture);
this.sprite.anchor.set(0.5);
- const aspectRatio = texture.width / texture.height;
+ const aspectRatio = texture.height > 0 ? texture.width / texture.height : 1;
this.sprite.height = 24;
this.sprite.width = 24 * aspectRatio;
@@ -100,27 +100,26 @@ class Ping {
for (let i = 0; i < glowSteps; i++) {
const glowRadius = maxRad + i * 8; // Circles outside the main ring
const glowAlpha = 0.1 * dramaticPulse * (1 - i / glowSteps); // Fades out with distance
- this.circle.beginFill(staticColor.toRgb(), glowAlpha);
- this.circle.drawCircle(0, 0, glowRadius);
- this.circle.endFill();
+ this.circle.circle(0, 0, glowRadius).fill({
+ color: staticColor.toRgb(),
+ alpha: glowAlpha,
+ });
}
// --- Main Rings (as before) ---
// Outer static ring
- this.circle.stroke({
+ this.circle.circle(0, 0, maxRad).stroke({
width: 3,
color: staticColor.toRgb(),
alpha: 0.5 * dramaticPulse,
});
- this.circle.circle(0, 0, maxRad);
// Inner pulsing ring
- this.circle.stroke({
+ this.circle.circle(0, 0, currentRadius).stroke({
width: 6,
color: pulseColor.toRgb(),
alpha: overallFadeAlpha * dramaticPulse,
});
- this.circle.circle(0, 0, currentRadius);
}
destroy() {
@@ -172,6 +171,10 @@ export class PingMarkerLayer implements Layer {
destroy() {
this.eventBus.off(PingPlacedEvent, this.handlePingPlaced);
+ for (const ping of this.pings) {
+ ping.destroy();
+ }
+ this.pings = [];
window.removeEventListener("resize", this.resizeCanvas);
this.renderer?.destroy();
this.stage.destroy(true);
diff --git a/src/core/EventBus.ts b/src/core/EventBus.ts
index f5b2e5dbf..8a7057f67 100644
--- a/src/core/EventBus.ts
+++ b/src/core/EventBus.ts
@@ -5,8 +5,11 @@ export interface EventConstructor {
}
export class EventBus {
- private listeners: Map void>> =
- new Map();
+ private listeners: Map<
+ EventConstructor,
+ Array<{ id: number; callback: (event: GameEvent) => void }>
+ > = new Map();
+ private nextId = 0;
emit(event: T): void {
const eventConstructor = event.constructor as EventConstructor;
@@ -14,7 +17,7 @@ export class EventBus {
const callbacks = this.listeners.get(eventConstructor);
if (callbacks) {
for (const callback of callbacks) {
- callback(event);
+ callback.callback(event);
}
}
}
@@ -26,9 +29,20 @@ export class EventBus {
if (!this.listeners.has(eventType)) {
this.listeners.set(eventType, []);
}
- this.listeners.get(eventType)!.push(callback as (event: GameEvent) => void);
+ const id = this.nextId++;
+ this.listeners
+ .get(eventType)!
+ .push({ id, callback: callback as (event: GameEvent) => void });
- return () => this.off(eventType, callback);
+ return () => {
+ const callbacks = this.listeners.get(eventType);
+ if (callbacks) {
+ const index = callbacks.findIndex((item) => item.id === id);
+ if (index > -1) {
+ callbacks.splice(index, 1);
+ }
+ }
+ };
}
off(
@@ -37,7 +51,7 @@ export class EventBus {
): void {
const callbacks = this.listeners.get(eventType);
if (callbacks) {
- const index = callbacks.indexOf(callback as (event: GameEvent) => void);
+ const index = callbacks.findIndex((item) => item.callback === callback);
if (index > -1) {
callbacks.splice(index, 1);
}
diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts
index 4f4151ac2..2b650f561 100644
--- a/src/core/game/Game.ts
+++ b/src/core/game/Game.ts
@@ -413,7 +413,6 @@ export class PlayerInfo {
public readonly clientID: ClientID | null,
// TODO: make player id the small id
public readonly id: PlayerID,
- public readonly nation?: Nation | null,
) {
this.clan = getClanTag(name);
}
diff --git a/src/core/game/GameUpdates.ts b/src/core/game/GameUpdates.ts
index 7b083a329..aba7ef88e 100644
--- a/src/core/game/GameUpdates.ts
+++ b/src/core/game/GameUpdates.ts
@@ -5,6 +5,7 @@ import {
Gold,
MessageType,
NameViewData,
+ PingType,
PlayerID,
PlayerType,
Team,
@@ -266,10 +267,6 @@ export interface UnitIncomingUpdate {
messageType: MessageType;
playerID: number;
}
-
-import { PingType } from "./Ping";
-//...
-//...
export interface EmbargoUpdate {
type: GameUpdateType.EmbargoEvent;
event: "start" | "stop";