39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
|
|
import type { Vec3 } from "../math/Vec3"
|
||
|
|
import type { MeshBatch } from "../render/ChunkBuilder"
|
||
|
|
import type { Collider } from "../world/Collider"
|
||
|
|
|
||
|
|
/** Static content recipe. Concrete game prefabs implement this engine contract and
|
||
|
|
* are referenced as objects, never through a closed content-kind registry. */
|
||
|
|
export type Prefab<State> = {
|
||
|
|
position: (state: State) => Vec3
|
||
|
|
bakeNear: (state: State, batch: MeshBatch) => void
|
||
|
|
bakeFar?: (state: State, batch: MeshBatch) => void
|
||
|
|
collider?: (state: State) => Collider | null
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Type-erased placed prefab consumed during level compilation only. */
|
||
|
|
export type PlacedPrefab = {
|
||
|
|
position: Vec3
|
||
|
|
bakeNear: (batch: MeshBatch) => void
|
||
|
|
bakeFar?: (batch: MeshBatch) => void
|
||
|
|
collider: Collider | null
|
||
|
|
}
|
||
|
|
|
||
|
|
export namespace Prefab {
|
||
|
|
export function place<State>(
|
||
|
|
definition: Prefab<State>,
|
||
|
|
state: State,
|
||
|
|
): PlacedPrefab {
|
||
|
|
const bakeFar = definition.bakeFar
|
||
|
|
return {
|
||
|
|
position: definition.position(state),
|
||
|
|
bakeNear: (batch) => definition.bakeNear(state, batch),
|
||
|
|
bakeFar:
|
||
|
|
bakeFar === undefined
|
||
|
|
? undefined
|
||
|
|
: (batch) => bakeFar(state, batch),
|
||
|
|
collider: definition.collider?.(state) ?? null,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|