Skip to content

@gameable/assets ​

Classes ​

AssetError ​

An asset operation that could not be completed.

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new AssetError(
   assetId, 
   message, 
   options?
): AssetError;

Build an asset error.

Parameters ​
ParameterTypeDescription
assetIdstringAsset id involved.
messagestringWhat went wrong.
options?ErrorOptionsStandard Error options, used to keep the cause.
Returns ​

AssetError

Overrides ​
ts
Error.constructor

Properties ​

assetId ​
ts
readonly assetId: string;

The id involved, when there is one.

code? ​
ts
readonly optional code?: string;

Stable diagnostic code when integrity verification fails.


ColliderFormatError ​

A collider buffer that could not be read.

The message always says what was expected and what was found, because the only realistic way to hit it is to hand the parser the wrong file.

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new ColliderFormatError(message): ColliderFormatError;

Build a collider format error.

Parameters ​
ParameterTypeDescription
messagestringWhat is wrong with the buffer.
Returns ​

ColliderFormatError

Overrides ​
ts
Error.constructor

GameAddressError ​

An unsafe game address and the reason it was refused.

Example ​

ts
import { GameAddressError, resolveGameAddress } from 'gameable/assets';
try { resolveGameAddress('javascript:alert(1)'); }
catch (error) { if (error instanceof GameAddressError) console.log(error.reason); }

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new GameAddressError(address, reason): GameAddressError;
Parameters ​
ParameterType
addressstring
reasonstring
Returns ​

GameAddressError

Overrides ​
ts
Error.constructor

Properties ​

address ​
ts
readonly address: string;

The refused address.

reason ​
ts
readonly reason: string;

Why the address is unsafe.


ManifestError ​

A manifest that failed validation.

path is a JSON-pointer-ish location such as assets[2].collider.radius, so the message alone is enough to find and fix the problem.

Example ​

ts
import { ManifestError, parseManifest } from 'gameable/assets';

try {
  parseManifest({ version: 1 });
} catch (err) {
  if (err instanceof ManifestError) console.error(err.path, err.message);
}

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new ManifestError(path, message): ManifestError;

Build a manifest validation error.

Parameters ​
ParameterTypeDescription
pathstringLocation of the offending value, for example assets[0].id.
messagestringWhat is wrong with it.
Returns ​

ManifestError

Overrides ​
ts
Error.constructor

Properties ​

path ​
ts
readonly path: string;

Location of the offending value inside the manifest.

Interfaces ​

AssetCollider ​

Static collision proxy registered with physics when the asset loads.

Properties ​

halfExtents? ​
ts
readonly optional halfExtents?: Vec3;

Box half extents. Required when shape is box.

height? ​
ts
readonly optional height?: number;

Capsule height. Required for capsule.

layer? ​
ts
readonly optional layer?: ColliderLayer;

Physics layer. Defaults to static.

offset? ​
ts
readonly optional offset?: Vec3;

Offset from the entity origin.

radius? ​
ts
readonly optional radius?: number;

Sphere or capsule radius. Required for sphere and capsule.

shape ​
ts
readonly shape: ColliderShape;

Collider shape.

src? ​
ts
readonly optional src?: string;

Path to collision geometry, for shapes that need their own mesh.


AssetEntry ​

One manifest entry.

Properties ​

aliases? ​
ts
readonly optional aliases?: readonly string[];

Previous ids that continue to resolve to this entry.

bakedLighting? ​
ts
readonly optional bakedLighting?: string;

A splat's baked lighting (a .light.bin the bake editor wrote for this very splat), drawn with it. Relative path or absolute URL like src. Only on splat entries.

collider? ​
ts
readonly optional collider?: AssetCollider;

Static collision proxy.

id ​
ts
readonly id: string;

Stable identifier used by game logic. Keep previous names in aliases.

lightProbes? ​
ts
readonly optional lightProbes?: string;

A splat's light probe grid (a .probes.json the bake editor wrote): the light at each place in it, which characters standing there are lit by. Relative path or absolute URL like src. Only on splat entries.

mutable? ​
ts
readonly optional mutable?: boolean;

Leave a remote source live when bundling (explicit opt-out from pinning).

poster? ​
ts
readonly optional poster?: string;

A still shown until a video's first frame (a cutscene's poster). Relative path or absolute URL like src. Only on video entries.

rig? ​
ts
readonly optional rig?: AssetRig;

Character rig configuration. Required when type is character.

sha256? ​
ts
readonly optional sha256?: string;

SHA-256 of immutable source bytes, verified before loading.

shadowSources? ​
ts
readonly optional shadowSources?: string;

A splat's shadow sources (a .shadows.json the bake editor wrote): where the shadows of what stands in the place fall from. Relative path or absolute URL like src. Only on splat entries.

src ​
ts
readonly src: string;

Relative path (resolved against baseUrl) or absolute URL.

tags? ​
ts
readonly optional tags?: readonly string[];

Free-form labels for grouping and preload policies.

type ​
ts
readonly type: AssetType;

What the host should load this as.


AssetLoaderContext ​

Everything a loader is given besides the URL.

Properties ​

bytes? ​
ts
readonly optional bytes?: ArrayBuffer;

Verified source bytes for pinned entries. Load these instead of fetching the URL again.

manifest ​
ts
readonly manifest: AssetManifest;

The manifest the entry came from.

registry ​
ts
readonly registry: AssetRegistry;

The registry doing the loading, for loaders that need sibling assets.

signal? ​
ts
readonly optional signal?: AbortSignal;

Abort signal, when the caller supplied one.


AssetLook ​

How an exported studio character (aosrig-splat) is drawn, when the manifest says: the point shape ('size-aware', the engine's point while small on screen and the studio's once large; 'engine', three's own 2-sigma point; 'studio', the studio page's; 'full-opacity', the small-point rule alone) and where its colours add up ('stored', in the file's own space as the studio adds them; 'linear', in linear light). Nothing asked = 'size-aware' and 'stored', chosen by Isaac on the looks sheet of 30 Sep 2026; a manifest entry overrides the package's own look, and the bridge's extras override both.

Properties ​

blend? ​
ts
readonly optional blend?: "stored" | "linear";
pointShape? ​
ts
readonly optional pointShape?: "engine" | "studio" | "full-opacity" | "size-aware";

AssetManifest ​

A parsed, validated assets.json.

Properties ​

assets ​
ts
readonly assets: readonly AssetEntry[];

Every asset the game can reference.

baseUrl ​
ts
readonly baseUrl: string;

Prefix joined to every relative src.

exclude? ​
ts
readonly optional exclude?: readonly string[];

Files never bundled, as globs relative to the manifest folder.

include? ​
ts
readonly optional include?: readonly string[];

Extra files to bundle, as globs relative to the manifest folder.

version ​
ts
readonly version: 1;

Manifest schema version. 1 is the only value today.


AssetProgress ​

One step of a AssetRegistry.preload run.

Properties ​

error? ​
ts
readonly optional error?: unknown;

The failure, when ok is false.

id ​
ts
readonly id: string;

Id that just finished.

loaded ​
ts
readonly loaded: number;

Entries finished so far, including failures.

ok ​
ts
readonly ok: boolean;

Whether the entry loaded successfully.

total ​
ts
readonly total: number;

Entries in this run.


AssetRegistry ​

Resolves ids to handles, entries, URLs and loaded objects.

Properties ​

ids ​
ts
readonly ids: readonly string[];

Every declared id, in manifest order.

manifest ​
ts
readonly manifest: AssetManifest;

The manifest this registry was built from.

Methods ​

add() ​
ts
add(more): string[];

Add another manifest's entries while the engine runs: a world package, or anything else that arrives after the game's own manifest was read.

Each entry gets the next handle, so every handle already given out stays what it was, and each src resolves against the added manifest's own baseUrl. An id the registry already holds keeps its first entry and is returned among the skipped, so loading the same world twice is harmless.

Parameters ​
ParameterTypeDescription
moreAssetManifestA parsed manifest (parseManifest).
Returns ​

string[]

The ids that were already declared and were left as they were.

dispose() ​
ts
dispose(): void;

Drop every cached object and in-flight promise.

Returns ​

void

Nothing.

entry() ​
ts
entry(idOrHandle): AssetEntry | undefined;

The manifest entry for an id or a handle.

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberAsset id or handle.
Returns ​

AssetEntry | undefined

The entry, or undefined when unknown.

get() ​
ts
get(idOrHandle): unknown;

The already-loaded object for an id.

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberAsset id or handle.
Returns ​

unknown

The object, or undefined when it is not loaded yet.

hasLoader() ​
ts
hasLoader(type): boolean;

Whether a loader is registered for a type.

Parameters ​
ParameterTypeDescription
typestringAsset type.
Returns ​

boolean

True when a loader exists.

idOf() ​
ts
idOf(handle): string | undefined;

The id behind a handle.

Parameters ​
ParameterTypeDescription
handlenumberHandle from resolve.
Returns ​

string | undefined

The id, or undefined for 0 and out-of-range handles.

load() ​
ts
load(idOrHandle): Promise<unknown>;

Load an asset, or return the promise for one already loading or loaded.

Repeat calls for the same id share one promise — the in-flight one while it is loading, then the resolved one forever after — so a hot path may call this every frame without allocating. An unknown id rejects with a shared AssetError, which is deliberately the same error object every time.

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberAsset id or handle.
Returns ​

Promise<unknown>

The loaded object.

onProgress() ​
ts
onProgress(cb): () => void;

Subscribe to preload progress.

Parameters ​
ParameterTypeDescription
cb(progress) => voidCalled once per finished entry.
Returns ​

An unsubscribe function.

() => void

poster() ​
ts
poster(idOrHandle): string | undefined;

The resolved URL of a video entry's poster (the still shown until its first frame).

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberAsset id or handle.
Returns ​

string | undefined

The URL, or undefined when unknown or when the entry has no poster.

preload() ​
ts
preload(tag?): Promise<void>;

Load every asset, or every asset carrying tag.

Parameters ​
ParameterTypeDescription
tag?stringOptional tag filter.
Returns ​

Promise<void>

Resolves once the whole set has settled.

registerLoader() ​
ts
registerLoader(type, loader): void;

Register (or replace) the loader for an asset type.

This is how gameable/splat and gameable/character add the splat and character types without core depending on them.

Parameters ​
ParameterTypeDescription
typestringAsset type the loader handles.
loaderAssetLoaderThe loader.
Returns ​

void

Nothing.

resolve() ​
ts
resolve(id): number;

The stable handle for an id.

Parameters ​
ParameterTypeDescription
idstringAsset id.
Returns ​

number

A 1-based handle, or 0 when the id is not declared.

url() ​
ts
url(idOrHandle): string | undefined;

The resolved URL for an id or a handle.

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberAsset id or handle.
Returns ​

string | undefined

The URL, or undefined when unknown.

urlFor() ​
ts
urlFor(idOrHandle, path): string | undefined;

A path resolved as an entry's src is: against the baseUrl of the manifest the entry came from. For a file named beside an asset (a splat's bakedLighting).

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberAsset id or handle.
pathstringRelative path or absolute URL.
Returns ​

string | undefined

The URL, or undefined when the asset is unknown.


AssetRig ​

Character rig configuration.

Properties ​

backend ​
ts
readonly backend: RigBackend;

Which backend drives the character.

'skinned' means src is itself a glTF/GLB carrying JOINTS_0/WEIGHTS_0 and its animations, so no AssetRig.pack is involved.

clips? ​
ts
readonly optional clips?: readonly string[];

More clip files the character plays besides its own (aosrig-splat version 2: files of its clips.json format), each resolved like pack: beside src, or absolute.

controlNames? ​
ts
readonly optional controlNames?: readonly string[];

Ordered rig control names; the index is the wire format.

expressionSpace? ​
ts
readonly optional expressionSpace?: ExpressionSpace;

Layout of the expression vector.

height? ​
ts
readonly optional height?: number;

The character's real height, metres, floor to the crown of its own points (hair and all). The studio makes every character about 1.75 m tall; a game that knows the person's height says it here, and the engine draws the character at it: its points, its joints, its physics body, its shadow and its measures all at that scale. Absent: as exported.

light? ​
ts
readonly optional light?: string;

A lighter copy of the same character (aosrig-splat: its character.json, resolved like pack): drawn first, so the character stands sooner, src taking over once it is down, or all a phone loads. The character bridge's loading order does this by itself.

look? ​
ts
readonly optional look?: AssetLook;

How an aosrig-splat character is drawn, when the game says (see AssetLook).

motion? ​
ts
readonly optional motion?: string | false;

How an aosrig-splat character moves: false turns the movement system off for this character (it walks by the clips' blend, as before); a path names its own motion set (a soma-motion file, text or the compact binary), resolved like pack, when its character.json does not. Absent: the package's own set if it names one, laid over the engine's shared set.

pack? ​
ts
readonly optional pack?: string;

Path to the baked .aosrig pack. Required when backend is gnm.

vertexCount? ​
ts
readonly optional vertexCount?: number;

Vertices the rig stage produces per frame.


AudioLoaderOptions ​

Options accepted by createAudioLoader.

Extended by ​

Properties ​

fetch? ​
ts
readonly optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

fetch implementation. Defaults to the global one.

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputURL | RequestInfo
init?RequestInit
Returns ​

Promise<Response>

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputstring | URL | Request
init?RequestInit
Returns ​

Promise<Response>


ColliderMesh ​

A triangle mesh: flat positions plus flat triangle indices.

Properties ​

indices ​
ts
readonly indices: Uint32Array;

Triangle indices into positions. Length is a multiple of three.

positions ​
ts
readonly positions: Float32Array;

Vertex positions in metres, flattened x y z. Length is 3 * vertexCount.


CreateAssetRegistryOptions ​

Options accepted by createAssetRegistry.

Properties ​

loaders? ​
ts
readonly optional loaders?: Readonly<Record<string, AssetLoader>>;

Loaders by asset type. More can be added later with registerLoader.

manifest ​
ts
readonly manifest: AssetManifest;

The validated manifest.

signal? ​
ts
readonly optional signal?: AbortSignal;

Abort signal handed to every loader.


DefaultLoaderOptions ​

Options accepted by createDefaultLoaders.

Extends ​

Properties ​

dracoDecoderPath? ​
ts
readonly optional dracoDecoderPath?: string;

Directory holding draco_decoder.js / .wasm, served by your app.

Defaults to DEFAULT_DRACO_DECODER_PATH. Copy the files from three/examples/jsm/libs/draco/ into your public/ directory, or point this at a CDN.

Inherited from ​

GltfLoaderOptions.dracoDecoderPath

fetch? ​
ts
readonly optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

fetch implementation. Defaults to the global one.

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputURL | RequestInfo
init?RequestInit
Returns ​

Promise<Response>

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputstring | URL | Request
init?RequestInit
Returns ​

Promise<Response>

Inherited from ​

AudioLoaderOptions.fetch

ktx2TranscoderPath? ​
ts
readonly optional ktx2TranscoderPath?: string;

Directory holding the Basis Universal transcoder. When omitted, KTX2 textures are not supported and no KTX2Loader is constructed.

Inherited from ​

GltfLoaderOptions.ktx2TranscoderPath

renderer? ​
ts
readonly optional renderer?: WebGPURenderer;

An initialised renderer. Required for KTX2: detectSupport needs to know which compressed texture formats the backend exposes.

Inherited from ​

GltfLoaderOptions.renderer


DefaultLoaders ​

The default loader set plus the handle needed to release three's workers.

Properties ​

loaders ​
ts
readonly loaders: Record<string, AssetLoader>;

Pass straight to createAssetRegistry({ loaders }).

Methods ​

dispose() ​
ts
dispose(): void;

Terminate any worker pools the loaders started.

Returns ​

void

Nothing.


ExpressionSegment ​

A named contiguous span of an expression vector.

Properties ​

length ​
ts
readonly length: number;

Number of components in the span.

name ​
ts
readonly name: string;

Segment name, for example left_eye.

offset ​
ts
readonly offset: number;

First index of the span.


ExpressionSpace ​

Layout of the expression vector a character rig consumes.

Properties ​

arkitMap? ​
ts
readonly optional arkitMap?: string;

Path to an ARKit-52 to this-space mapping, when kind is not arkit52.

dim ​
ts
readonly dim: number;

Number of components in the vector.

kind ​
ts
readonly kind: ExpressionSpaceKind;

Which well-known expression space this is.

names? ​
ts
readonly optional names?: readonly string[];

Optional per-component names.

segments? ​
ts
readonly optional segments?: readonly ExpressionSegment[];

Optional named spans of the vector.


GltfLoaderHandle ​

A gltf loader plus the handles needed to release its workers.

Properties ​

load ​
ts
readonly load: AssetLoader;

Register this under the gltf asset type.

Methods ​

dispose() ​
ts
dispose(): void;

Terminate the Draco and KTX2 worker pools.

Returns ​

void

Nothing.


GltfLoaderOptions ​

Options accepted by createGltfLoader.

Extended by ​

Properties ​

dracoDecoderPath? ​
ts
readonly optional dracoDecoderPath?: string;

Directory holding draco_decoder.js / .wasm, served by your app.

Defaults to DEFAULT_DRACO_DECODER_PATH. Copy the files from three/examples/jsm/libs/draco/ into your public/ directory, or point this at a CDN.

ktx2TranscoderPath? ​
ts
readonly optional ktx2TranscoderPath?: string;

Directory holding the Basis Universal transcoder. When omitted, KTX2 textures are not supported and no KTX2Loader is constructed.

renderer? ​
ts
readonly optional renderer?: WebGPURenderer;

An initialised renderer. Required for KTX2: detectSupport needs to know which compressed texture formats the backend exposes.


LoadManifestOptions ​

Options accepted by loadManifest.

Extends ​

Properties ​

baseUrl? ​
ts
readonly optional baseUrl?: string;

Fallback baseUrl when the manifest does not declare one.

Inherited from ​

ParseManifestOptions.baseUrl

fetch? ​
ts
readonly optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

fetch implementation. Defaults to the global one.

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputURL | RequestInfo
init?RequestInit
Returns ​

Promise<Response>

Call Signature ​
ts
(input, init?): Promise<Response>;

MDN Reference

Parameters ​
ParameterType
inputstring | URL | Request
init?RequestInit
Returns ​

Promise<Response>

signal? ​
ts
readonly optional signal?: AbortSignal;

Abort signal forwarded to fetch.


ParseColliderOptions ​

Options for parseCollider.

Properties ​

validate? ​
ts
readonly optional validate?: boolean;

Walk the index array and reject an index that points past the last vertex.

The scan is O(indexCount) on the asset-loading path, and it catches exactly one thing: a corrupt or mis-generated file. That is a development concern, so it defaults to import.meta.env.DEV — true under vite dev, false in a production build — and to true wherever there is no import.meta.env at all (Node, vitest, a plain bundler), so the safe answer is the one you get by saying nothing.

Turning it off does not make a bad index safe: Jolt reads the array itself. It moves the check to the place that already has to do it.


ParseManifestOptions ​

Options accepted by parseManifest.

Extended by ​

Properties ​

baseUrl? ​
ts
readonly optional baseUrl?: string;

Fallback baseUrl when the manifest does not declare one.

Type Aliases ​

AssetLoader ​

ts
type AssetLoader = (url, entry, ctx) => Promise<unknown>;

Turns one asset entry into a loaded object.

One loader is registered per AssetEntry.type. What it resolves to is the loader's business: gltf yields a GLTF, audio an ArrayBuffer, splat and character whatever their packages define.

Parameters ​

ParameterType
urlstring
entryAssetEntry
ctxAssetLoaderContext

Returns ​

Promise<unknown>


AssetLoaderMap ​

ts
type AssetLoaderMap = Readonly<Record<string, AssetLoader>>;

Loaders keyed by asset type.


AssetType ​

ts
type AssetType = "splat" | "gltf" | "character" | "audio" | "video";

What the host should load an entry as. video is a clip the page plays over the stage (a cutscene): the host never decodes it itself, a <video> does.


ColliderLayer ​

ts
type ColliderLayer = "static" | "dynamic" | "trigger";

Physics layer a collider belongs to.


ColliderShape ​

ts
type ColliderShape = "mesh" | "box" | "sphere" | "capsule" | "convex-hull" | "heightfield";

Collision proxy shapes understood by the physics module.


ExpressionSpaceKind ​

ts
type ExpressionSpaceKind = "arkit52" | "gnm" | "gnm68";

Coordinate space a character's expression vector is expressed in.


RigBackend ​

ts
type RigBackend = "orl" | "gnm" | "skinned" | "aosrig-splat";

Which RigBackend drives a character.

orl and gnm are splat head rigs and need a baked pack; skinned is a whole body — a glTF/GLB with JOINTS_0/WEIGHTS_0 and its clips embedded, so it needs no pack at all.


Vec3 ​

ts
type Vec3 = readonly [number, number, number];

A three-component vector, as written in the manifest.

Variables ​

DEFAULT_DRACO_DECODER_PATH ​

ts
const DEFAULT_DRACO_DECODER_PATH: "/draco/" = '/draco/';

Where DRACOLoader looks for its decoder, when none is configured.


PACKAGE ​

ts
const PACKAGE: "@gameable/assets";

Package identity marker.

Example ​

ts
import { PACKAGE } from 'gameable/assets';

console.log(PACKAGE); // 'gameable/assets'

SITE_ROOTS ​

ts
const SITE_ROOTS: readonly string[];

Site-root mounts for rooms, visit and talk services and the dev server's local characters. Like Unreal's /Script/ versus /Game/, these belong to the host, rather than a published game's folder.

Example ​

ts
import { SITE_ROOTS } from 'gameable/assets';
console.log(SITE_ROOTS.includes('services'));

Functions ​

assetUrl() ​

ts
function assetUrl(id): string;

Resolve an id or alias using the most recently created live asset registry.

Parameters ​

ParameterTypeDescription
idstringManifest asset id.

Returns ​

string

Its game-root-aware URL; throws when the registry or id is missing.

Example ​

ts
import { assetUrl } from 'gameable';
const response = await fetch(assetUrl('arena'));
console.log(response.ok);

createAssetRegistry() ​

ts
function createAssetRegistry(options): AssetRegistry;

Build an asset registry over a validated manifest.

Parameters ​

ParameterTypeDescription
optionsCreateAssetRegistryOptionsManifest, loaders and an optional abort signal.

Returns ​

AssetRegistry

The registry.

Example ​

ts
import { createAssetRegistry, parseManifest } from 'gameable/assets';

const manifest = parseManifest({
  version: 1,
  baseUrl: 'assets/',
  assets: [{ id: 'shot', type: 'audio', src: 'sfx/shot.ogg', tags: ['sfx'] }],
});
const assets = createAssetRegistry({ manifest, loaders: {} });
console.log(assets.resolve('shot')); // 1
console.log(assets.resolve('nope')); // 0

createAudioLoader() ​

ts
function createAudioLoader(options?): AssetLoader;

Build the audio asset loader.

It resolves to the raw ArrayBuffer. Turning that into an AudioBuffer is gameable/audio's job, because decoding needs an AudioContext and the registry must stay usable without one.

Parameters ​

ParameterTypeDescription
optionsAudioLoaderOptionsfetch override.

Returns ​

AssetLoader

An asset loader resolving to an ArrayBuffer.

Example ​

ts
import { createAssetRegistry, createAudioLoader, parseManifest } from 'gameable/assets';

const manifest = parseManifest({ version: 1, assets: [{ id: 'shot', type: 'audio', src: 'shot.ogg' }] });
const assets = createAssetRegistry({ manifest, loaders: { audio: createAudioLoader() } });
const bytes = (await assets.load('shot')) as ArrayBuffer;
console.log(bytes.byteLength > 0);

createDefaultLoaders() ​

ts
function createDefaultLoaders(options?): DefaultLoaders;

The loaders createEngine registers: gltf and audio.

Parameters ​

ParameterTypeDescription
optionsDefaultLoaderOptionsDraco/KTX2 paths and a fetch override.

Returns ​

DefaultLoaders

The loader map and its dispose.

Example ​

ts
import { createAssetRegistry, createDefaultLoaders, parseManifest } from 'gameable/assets';

const defaults = createDefaultLoaders({ dracoDecoderPath: '/draco/' });
const manifest = parseManifest({ version: 1, assets: [] });
const assets = createAssetRegistry({ manifest, loaders: defaults.loaders });
console.log(assets.hasLoader('audio')); // true

createGltfLoader() ​

ts
function createGltfLoader(options?): GltfLoaderHandle;

Build the gltf asset loader.

The underlying GLTFLoader, DRACOLoader and optional KTX2Loader are constructed lazily, on the first asset that needs them.

Parameters ​

ParameterTypeDescription
optionsGltfLoaderOptionsDraco decoder path, optional KTX2 transcoder path and renderer.

Returns ​

GltfLoaderHandle

The loader function and its dispose.

Example ​

ts
import { createAssetRegistry, createGltfLoader, parseManifest } from 'gameable/assets';

const gltf = createGltfLoader({ dracoDecoderPath: '/draco/' });
const manifest = parseManifest({ version: 1, assets: [{ id: 'rock', type: 'gltf', src: 'rock.glb' }] });
const assets = createAssetRegistry({ manifest, loaders: { gltf: gltf.load } });
console.log(assets.hasLoader('gltf')); // true

encodeCollider() ​

ts
function encodeCollider(positions, indices): ArrayBuffer;

Write an arena.collider.bin buffer.

The exact inverse of parseCollider: parseCollider(encodeCollider(p, i)) returns p and i unchanged, up to f32 rounding of the positions.

Parameters ​

ParameterTypeDescription
positionsArrayLike<number>Vertex positions in metres, flattened x y z.
indicesArrayLike<number>Triangle indices into positions.

Returns ​

ArrayBuffer

The encoded file, ready to write to disk.

Throws ​

When positions is not a whole number of vertices, indices is not a whole number of triangles, or an index is out of range.

Example ​

ts
import { encodeCollider, parseCollider } from 'gameable/assets';

// A single 1 m triangle on the floor.
const file = encodeCollider([0, 0, 0, 1, 0, 0, 0, 0, 1], [0, 1, 2]);
console.log(file.byteLength); // 8 + 9 * 4 + 3 * 4 = 56
console.log(parseCollider(file).indices.length); // 3

findEntry() ​

ts
function findEntry(manifest, id): AssetEntry | undefined;

Look an entry up by id.

The lookup table is built once per manifest object and cached against it, so this is a Map hit rather than a scan after the first call.

Parameters ​

ParameterTypeDescription
manifestAssetManifestManifest to search.
idstringAsset id.

Returns ​

AssetEntry | undefined

The entry, or undefined when the id is unknown.

Example ​

ts
import { findEntry, parseManifest } from 'gameable/assets';

const manifest = parseManifest({ version: 1, assets: [{ id: 'shot', type: 'audio', src: 'a.ogg' }] });
console.log(findEntry(manifest, 'shot')?.src); // 'a.ogg'

gameRoot() ​

ts
function gameRoot(): string;

The game's folder, as an absolute URL ending in /, or / without a page.

Returns ​

string

The override, document folder, location folder, or /, in that order.

Example ​

ts
import { gameRoot } from 'gameable/assets';
console.log(gameRoot());

gameUrl() ​

ts
function gameUrl(address): string;

Sanitize and resolve a game file address, safely repeatable on its own output. game:x uses the game folder; /x is its legacy spelling. Bundler URLs already under the game folder and site service mounts retain their paths. Relative paths and http(s), data, blob and protocol-relative URLs are unchanged. File URLs are also unchanged when no browser page exists.

Parameters ​

ParameterTypeDescription
addressstringA game file address.

Returns ​

string

The resolved address.

Throws ​

For controls, backslashes, unsafe schemes or paths escaping the game folder.

Example ​

ts
import { resolveGameAddress } from 'gameable/assets';
const response = await fetch(resolveGameAddress('game:worlds/attic/world.json'));
console.log(response.ok);

joinUrl() ​

ts
function joinUrl(baseUrl, src): string;

Join a base prefix and a relative source path. In the browser, exactly / means the game's document directory, so the same manifest works at the origin root and under a published site's prefix. Other prefixes and Node resolution keep their usual meaning.

Parameters ​

ParameterTypeDescription
baseUrlstringPrefix; may be empty, a path, or an absolute URL.
srcstringEntry src.

Returns ​

string

The joined URL.

Example ​

ts
import { joinUrl } from 'gameable/assets';

console.log(joinUrl('https://cdn.example/a/b/', '../c.glb')); // 'https://cdn.example/a/c.glb'

loadManifest() ​

ts
function loadManifest(url, options?): Promise<AssetManifest>;

Fetch and validate an assets.json.

When the document omits baseUrl, it defaults to the manifest's own directory, exactly as the JSON Schema says.

Parameters ​

ParameterTypeDescription
urlstringWhere the manifest lives.
optionsLoadManifestOptionsfetch override, abort signal and baseUrl fallback.

Returns ​

Promise<AssetManifest>

The validated manifest.

Example ​

ts
import { loadManifest } from 'gameable/assets';

const manifest = await loadManifest('assets/assets.json');
console.log(manifest.assets.length);

parseCollider() ​

ts
function parseCollider(buffer, options?): ColliderMesh;

Read an arena.collider.bin buffer.

The header is always validated — counts and total length — so a mesh that parses has the right number of bytes in it. The per-index range scan is the one part that costs time proportional to the file, so it follows ParseColliderOptions.validate.

Parameters ​

ParameterTypeDescription
bufferArrayBuffer | ArrayBufferView<ArrayBufferLike>The file contents, as an ArrayBuffer or any view over one.
optionsParseColliderOptionsSee ParseColliderOptions.

Returns ​

ColliderMesh

The vertex positions and triangle indices, as views over buffer.

Throws ​

When the buffer is truncated, the index count is not a multiple of three, or (when validating) an index is out of range.

Example ​

ts
import { encodeCollider, parseCollider } from 'gameable/assets';

const bytes = encodeCollider([0, 0, 0, 1, 0, 0, 0, 0, 1], [0, 1, 2]);
const { positions, indices } = parseCollider(bytes);
console.log(positions.length / 3, indices.length / 3); // 3 1

parseManifest() ​

ts
function parseManifest(json, options?): AssetManifest;

Parse and validate an assets.json document.

Every failure throws a ManifestError naming the exact path, and the first failure wins: a manifest is either completely valid or rejected.

Parameters ​

ParameterTypeDescription
jsonunknownThe parsed JSON document.
optionsParseManifestOptionsFallback baseUrl when the manifest omits one.

Returns ​

AssetManifest

A frozen, validated manifest.

Example ​

ts
import { parseManifest } from 'gameable/assets';

const manifest = parseManifest({
  version: 1,
  baseUrl: 'assets/',
  assets: [{ id: 'arena', type: 'splat', src: 'arena.spz', tags: ['world'] }],
});
console.log(manifest.assets[0]?.id); // 'arena'

resolveAssetUrl() ​

ts
function resolveAssetUrl(manifest, entry): string;

Resolve an entry's src against the manifest's baseUrl.

Absolute URLs (https://…, data:…) and protocol-relative URLs (//host/x) are returned untouched, as are root-relative paths (/x.glb) when baseUrl is itself relative. When baseUrl carries a scheme, resolution goes through URL, so ../ segments collapse correctly.

Parameters ​

ParameterTypeDescription
manifestAssetManifestManifest supplying baseUrl.
entrystring | AssetEntryAn entry, or the id of one.

Returns ​

string

The absolute or root-relative URL to fetch.

Example ​

ts
import { parseManifest, resolveAssetUrl } from 'gameable/assets';

const manifest = parseManifest({
  version: 1,
  baseUrl: 'assets',
  assets: [{ id: 'arena', type: 'splat', src: 'arena.spz' }],
});
console.log(resolveAssetUrl(manifest, 'arena')); // 'assets/arena.spz'

setGameRoot() ​

ts
function setGameRoot(root): void;

Override the game folder for a host, worker or test. Pass null to clear it. Relative roots resolve against the current page.

Parameters ​

ParameterTypeDescription
rootstring | nullThe folder, or null to use the page again.

Returns ​

void

Example ​

ts
import { setGameRoot } from 'gameable/assets';
setGameRoot('https://cdn.example/games/demo/site/');
setGameRoot(null);

References ​

resolveGameAddress ​

Renames and re-exports gameUrl