aboutsummaryrefslogtreecommitdiff
path: root/content-system
diff options
context:
space:
mode:
Diffstat (limited to 'content-system')
-rw-r--r--content-system/registry/registry.ts14
-rw-r--r--content-system/registry/singleton.ts25
2 files changed, 37 insertions, 2 deletions
diff --git a/content-system/registry/registry.ts b/content-system/registry/registry.ts
index 38f0a91..6910cab 100644
--- a/content-system/registry/registry.ts
+++ b/content-system/registry/registry.ts
@@ -62,18 +62,26 @@ export class ContentRegistry {
}
}
+/** Per-chunk callback used to advance a progress bar as loading proceeds. */
+export type ChunkProgressCallback = (loaded: number, total: number) => void
+
/**
* Populate a fresh registry from the supplied manifest. Fetches every
* chunk whose id begins with a world-content prefix; ignores unknown
* prefixes so the registry can grow without breaking older clients.
+ * Chunks load in parallel; the callback reports completion order, not
+ * start order.
*/
export async function populateFromManifest(
manifest: ContentManifest,
- baseUrl: string
+ baseUrl: string,
+ onProgress?: ChunkProgressCallback
): Promise<ContentRegistry> {
const registry = new ContentRegistry()
-
const entries = Object.entries(manifest.chunks)
+ const total = entries.length
+ let loaded = 0
+
await Promise.all(
entries.map(async ([chunkId]) => {
const { data } = await loadChunk(chunkId, manifest, baseUrl)
@@ -84,6 +92,8 @@ export async function populateFromManifest(
} else if (chunkId.startsWith('world/institutions/')) {
registry.addInstitution(data as unknown as InstitutionContent)
}
+ loaded += 1
+ onProgress?.(loaded, total)
})
)
diff --git a/content-system/registry/singleton.ts b/content-system/registry/singleton.ts
new file mode 100644
index 0000000..d8a556e
--- /dev/null
+++ b/content-system/registry/singleton.ts
@@ -0,0 +1,25 @@
+import type { ContentRegistry } from '@hollowdark/content-system/registry/registry'
+
+let instance: ContentRegistry | null = null
+
+/** Record the registry populated during session startup. */
+export function setContentRegistry(registry: ContentRegistry): void {
+ instance = registry
+}
+
+/**
+ * Access the shared content registry. Throws if called before the
+ * loading pipeline has populated it — simulation code should never run
+ * until initial load is complete.
+ */
+export function getContentRegistry(): ContentRegistry {
+ if (instance === null) {
+ throw new Error('Content registry not initialised. Initial load must complete first.')
+ }
+ return instance
+}
+
+/** True once the registry has been populated. */
+export function hasContentRegistry(): boolean {
+ return instance !== null
+}