Merge branch 'worktree-relationship-system'

This commit is contained in:
root
2026-03-07 17:03:58 +00:00
2 changed files with 31 additions and 25 deletions
+6 -7
View File
@@ -130,13 +130,12 @@ export class GameScene extends Phaser.Scene {
}).setScrollFactor(0).setDepth(1000);
this.updateModeText();
// Spawn initial entities
this.spawnEntities(this.worldState.entities);
// Listen for state updates
this.client.onStateUpdate = (update: StateUpdate) => {
this.handleStateUpdate(update);
};
// Spawn initial entities, then listen for state updates
this.spawnEntities(this.worldState.entities).then(() => {
this.client.onStateUpdate = (update: StateUpdate) => {
this.handleStateUpdate(update);
};
});
this.client.onPlayerLeft = (_data) => {
// Entity removal will be handled by next state update
+25 -18
View File
@@ -15,7 +15,7 @@ function appearanceKey(appearance: Appearance): string {
export class CharacterCompositor {
private scene: Phaser.Scene;
private loadedImages: Set<string> = new Set();
private loadingImages: Map<string, Promise<void>> = new Map();
constructor(scene: Phaser.Scene) {
this.scene = scene;
@@ -35,33 +35,32 @@ export class CharacterCompositor {
// Already composited
if (this.scene.textures.exists(key)) return key;
// Collect all image paths needed
const imagesToLoad: { key: string; path: string }[] = [];
// Collect all image keys needed and ensure each is loaded
const skinKey = `skin_${appearance.skinId}`;
if (!this.scene.textures.exists(skinKey) && !this.loadedImages.has(skinKey)) {
imagesToLoad.push({ key: skinKey, path: this.skinPath(appearance.skinId) });
this.loadedImages.add(skinKey);
const pendingLoads: Promise<void>[] = [];
if (!this.scene.textures.exists(skinKey)) {
if (!this.loadingImages.has(skinKey)) {
this.loadingImages.set(skinKey, this.loadImage(skinKey, this.skinPath(appearance.skinId)));
}
pendingLoads.push(this.loadingImages.get(skinKey)!);
}
for (const slot of ACCESSORY_SLOTS) {
const fileId = appearance.accessories[slot];
if (!fileId) continue;
const accKey = `acc_${slot}_${fileId}`;
if (!this.scene.textures.exists(accKey) && !this.loadedImages.has(accKey)) {
imagesToLoad.push({ key: accKey, path: this.accessoryPath(slot, fileId) });
this.loadedImages.add(accKey);
if (!this.scene.textures.exists(accKey)) {
if (!this.loadingImages.has(accKey)) {
this.loadingImages.set(accKey, this.loadImage(accKey, this.accessoryPath(slot, fileId)));
}
pendingLoads.push(this.loadingImages.get(accKey)!);
}
}
// Load any missing images
if (imagesToLoad.length > 0) {
await new Promise<void>((resolve) => {
for (const img of imagesToLoad) {
this.scene.load.image(img.key, img.path);
}
this.scene.load.once('complete', resolve);
this.scene.load.start();
});
// Wait for all pending loads to complete
if (pendingLoads.length > 0) {
await Promise.all(pendingLoads);
}
// Composite onto offscreen canvas
@@ -96,6 +95,14 @@ export class CharacterCompositor {
return key;
}
private loadImage(key: string, path: string): Promise<void> {
return new Promise<void>((resolve) => {
this.scene.load.image(key, path);
this.scene.load.once(`filecomplete-image-${key}`, () => resolve());
this.scene.load.start();
});
}
getKey(appearance: Appearance): string {
return appearanceKey(appearance);
}