Await name layer initialization before ticks

Make layer initialization awaitable and have GameRenderer wait for each layer init before input and worker ticks start. This prevents the Pixi NameLayer from seeing players before its async font, atlas, and renderer setup has completed.

Also store the AlternateViewEvent handler on NameLayer so destroy() can unsubscribe it, matching the existing resize listener cleanup and preventing torn-down instances from mutating state.
This commit is contained in:
scamiv
2026-05-09 15:30:10 +02:00
parent 01520f4b82
commit 28bae2d7eb
4 changed files with 13 additions and 8 deletions
+4 -4
View File
@@ -148,9 +148,9 @@ export function joinLobby(
terrainLoad,
terrainMapFileLoader,
)
.then((r) => {
.then(async (r) => {
currentGameRunner = r;
r.start();
await r.start();
})
.catch((e) => {
console.error("error creating client game", e);
@@ -373,7 +373,7 @@ export class ClientGameRunner {
endGame(record);
}
public start() {
public async start() {
this.soundManager.playBackgroundMusic();
console.log("starting client game");
@@ -410,7 +410,7 @@ export class ClientGameRunner {
this.doBreakAllianceUnderCursor.bind(this),
);
this.renderer.initialize();
await this.renderer.initialize();
this.input.initialize();
this.worker.start((gu: GameUpdateViewData | ErrorUpdate) => {
if (this.lobby.gameStartInfo === undefined) {
+4 -2
View File
@@ -353,9 +353,11 @@ export class GameRenderer {
this.context = context;
}
initialize() {
async initialize() {
this.eventBus.on(RedrawGraphicsEvent, () => this.redraw());
this.layers.forEach((l) => l.init?.());
for (const layer of this.layers) {
await layer.init?.();
}
// only append the canvas if it's not already in the document to avoid reparenting side-effects
if (!document.body.contains(this.canvas)) {
+1 -1
View File
@@ -1,5 +1,5 @@
export interface Layer {
init?: () => void;
init?: () => void | Promise<void>;
tick?: () => void;
// Optional hint to throttle expensive ticks by wall-clock.
// If omitted or <= 0, the layer ticks whenever GameRenderer ticks.
+4 -1
View File
@@ -90,6 +90,8 @@ export class NameLayer implements Layer {
private readonly pixiCanvas: HTMLCanvasElement =
document.createElement("canvas");
private readonly onWindowResize = () => this.resizeCanvas();
private readonly onAlternateViewHandler = (e: AlternateViewEvent) =>
this.onAlternateViewChange(e);
private renderer: PixiRenderer | null = null;
private rendererInitialized = false;
private rebuildPending = false;
@@ -114,7 +116,7 @@ export class NameLayer implements Layer {
this.rootStage.addChild(this.labelStage);
this.rootStage.position.set(0, 0);
this.eventBus.on(AlternateViewEvent, (e) => this.onAlternateViewChange(e));
this.eventBus.on(AlternateViewEvent, this.onAlternateViewHandler);
window.addEventListener("resize", this.onWindowResize);
await this.setupRenderer();
@@ -773,6 +775,7 @@ export class NameLayer implements Layer {
}
destroy() {
this.eventBus.off(AlternateViewEvent, this.onAlternateViewHandler);
window.removeEventListener("resize", this.onWindowResize);
for (const render of this.renders) {
render.container.destroy({ children: true });