dungeon camp: createQuestBoard always returns null because GLTFLoader.load is async #1028

Closed
opened 2026-08-13 04:43:06 +00:00 by spikerj · 1 comment
Owner

Discovered while writing Wave 7 coverage for projects/spikersoft/src/app/_components/_games/dungeon-crawler/camp.ts.

createQuestBoard assigns questBoardRef only inside the GLTFLoader.load success/error callbacks, then immediately return questBoardRef. Because load is asynchronous, the returned handle is always null in production. createCamp therefore always reports questBoard: null.

Callers currently ignore the return value (dungeon-crawler.component.ts keeps only walls/torches) and animateQuestIndicator looks the board up by scene.getObjectByName("questBoard"), so gameplay is not broken. The collision wall is also missing from camp.walls until the callback fires, so the player can walk through the board for a frame (or forever if the GLB never loads).

Fix: return a THREE.Group placeholder synchronously, parent the loaded model into it, and push the collision mesh before returning — or make createCamp async.

Characterization: camp.create.spec.ts — "returns a null questBoard handle when GLB load stays pending (async gap)".

Discovered while writing Wave 7 coverage for `projects/spikersoft/src/app/_components/_games/dungeon-crawler/camp.ts`. `createQuestBoard` assigns `questBoardRef` only inside the `GLTFLoader.load` success/error callbacks, then immediately `return questBoardRef`. Because `load` is asynchronous, the returned handle is always `null` in production. `createCamp` therefore always reports `questBoard: null`. Callers currently ignore the return value (`dungeon-crawler.component.ts` keeps only `walls`/`torches`) and `animateQuestIndicator` looks the board up by `scene.getObjectByName("questBoard")`, so gameplay is not broken. The collision wall is also missing from `camp.walls` until the callback fires, so the player can walk through the board for a frame (or forever if the GLB never loads). Fix: return a `THREE.Group` placeholder synchronously, parent the loaded model into it, and push the collision mesh before returning — or make `createCamp` async. Characterization: `camp.create.spec.ts` — "returns a null questBoard handle when GLB load stays pending (async gap)".
Author
Owner

Resolved in spikersoft-angular PR #819 (merged to master). createQuestBoard returns a live Group before the async GLB load. Closing.

Resolved in spikersoft-angular [PR #819](https://git.spikersoft.com/spikerj/spikersoft-angular/pulls/819) (merged to `master`). createQuestBoard returns a live Group before the async GLB load. Closing.
Sign in to join this conversation.