@skewedaspect/sage 0.10.0-beta.2 → 0.10.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/behaviors/characterController.d.ts +58 -0
- package/dist/behaviors/physicsBody.d.ts +38 -0
- package/dist/behaviors/sound.d.ts +2 -2
- package/dist/classes/debugConsole.d.ts +8 -16
- package/dist/classes/gameEngine.d.ts +56 -94
- package/dist/classes/gameLevel.d.ts +23 -24
- package/dist/classes/level.d.ts +44 -53
- package/dist/classes/loggers/consoleBackend.d.ts +1 -1
- package/dist/classes/loggers/nullBackend.d.ts +1 -1
- package/dist/debug/builtins.d.ts +4 -6
- package/dist/engines/audio.d.ts +4 -7
- package/dist/engines/scene.d.ts +14 -73
- package/dist/entities/defineEntity.d.ts +7 -5
- package/dist/entities/entityPicking.d.ts +1 -1
- package/dist/entities/meshConfig.d.ts +11 -3
- package/dist/entities/nodeEntity.d.ts +15 -6
- package/dist/entities/nodePool.d.ts +1 -1
- package/dist/entities/nodeSimulation.d.ts +22 -11
- package/dist/entities/nodeSimulationContext.d.ts +4 -4
- package/dist/entities/standardMeshSource.d.ts +2 -2
- package/dist/events/payloads.d.ts +18 -23
- package/dist/handlers/collider.d.ts +7 -12
- package/dist/handlers/index.d.ts +13 -14
- package/dist/handlers/lod.d.ts +11 -9
- package/dist/handlers/occlusion.d.ts +8 -0
- package/dist/handlers/postProcessing.d.ts +7 -2
- package/dist/handlers/postProcessingFrameGraph.d.ts +7 -2
- package/dist/handlers/postProcessingPipeline.d.ts +4 -3
- package/dist/handlers/sound.d.ts +2 -4
- package/dist/handlers/trigger.d.ts +2 -4
- package/dist/handlers/visible.d.ts +4 -5
- package/dist/input/actionContext.d.ts +3 -1
- package/dist/input/bindings/delta.d.ts +2 -2
- package/dist/input/bindings/toggle.d.ts +2 -2
- package/dist/input/bindings/trigger.d.ts +2 -2
- package/dist/input/bindings/value.d.ts +2 -2
- package/dist/input/configuration.d.ts +3 -3
- package/dist/input/deliverAction.d.ts +1 -1
- package/dist/input/deviceReaders/gamepad.d.ts +2 -2
- package/dist/input/deviceReaders/keyboard.d.ts +2 -2
- package/dist/input/deviceReaders/mouse.d.ts +2 -2
- package/dist/input/inputCapture.d.ts +1 -1
- package/dist/input/readerFor.d.ts +3 -0
- package/dist/input/resolveBinding.d.ts +3 -3
- package/dist/interfaces/game.d.ts +19 -31
- package/dist/interfaces/level.d.ts +48 -51
- package/dist/interfaces/lifecycle.d.ts +3 -41
- package/dist/interfaces/logger.d.ts +0 -10
- package/dist/managers/asset.d.ts +10 -17
- package/dist/managers/audio.d.ts +10 -21
- package/dist/managers/colliderDebug.d.ts +7 -4
- package/dist/managers/game.d.ts +22 -83
- package/dist/managers/input.d.ts +11 -10
- package/dist/managers/level.d.ts +69 -132
- package/dist/managers/outline.d.ts +2 -2
- package/dist/managers/simulationSave.d.ts +16 -16
- package/dist/postProcessingFrameGraph-Dx3e6D33.js +93 -0
- package/dist/postProcessingFrameGraph-Dx3e6D33.js.map +1 -0
- package/dist/sage.d.ts +85 -81
- package/dist/sage.es.js +2067 -1829
- package/dist/sage.es.js.map +1 -1
- package/dist/utils/graphics.d.ts +3 -3
- package/dist/utils/logger.d.ts +3 -7
- package/dist/utils/physics.d.ts +9 -1
- package/dist/utils/timer.d.ts +1 -1
- package/dist/utils/vectors.d.ts +13 -10
- package/package.json +7 -8
- package/dist/classes/eventBus.d.ts +0 -141
- package/dist/events/index.d.ts +0 -2
- package/dist/events/types.d.ts +0 -17
- package/dist/handlers/occluder.d.ts +0 -13
- package/dist/postProcessingFrameGraph-C3Og4kaS.js +0 -78
- package/dist/postProcessingFrameGraph-C3Og4kaS.js.map +0 -1
- package/dist/sage.umd.js +0 -2
- package/dist/sage.umd.js.map +0 -1
- package/dist/utils/id.d.ts +0 -11
- package/dist/utils/stateMachine.d.ts +0 -43
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Christopher Case
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @skewedaspect/sage
|
|
2
|
+
|
|
3
|
+
The Babylon.js game engine: `NodeEntity` and `NodeSimulation` on top of `@skewedaspect/sage-core`'s entity
|
|
4
|
+
system, levels and their scenes, physics through Havok, the input system, audio, pooling, the parent-child
|
|
5
|
+
hierarchy, debug tooling, and the save manager.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install @skewedaspect/sage @babylonjs/core @babylonjs/havok @babylonjs/loaders
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Documentation: the site built from `site/docs` in https://gitlab.com/skewed-aspect/sage/sage
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Vector3, CharacterSurfaceInfo } from '@babylonjs/core';
|
|
2
|
+
import { Behavior } from '@skewedaspect/sage-core';
|
|
3
|
+
import { NodeBehaviorHooks, NodeEntity, Vector3State } from "../entities/nodeEntity.js";
|
|
4
|
+
/** A capsule height and a speed under a name (design/character.md#stances). */
|
|
5
|
+
export interface StanceConfig {
|
|
6
|
+
height: number;
|
|
7
|
+
radius: number;
|
|
8
|
+
/** Metres per second. */
|
|
9
|
+
speed: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CharacterControllerState {
|
|
12
|
+
/** How hard a game is asking to move right, -1 to 1. */
|
|
13
|
+
moveX: number;
|
|
14
|
+
/** How hard a game is asking to move forward, -1 to 1. */
|
|
15
|
+
moveZ: number;
|
|
16
|
+
wantsJump: boolean;
|
|
17
|
+
wantsSprint: boolean;
|
|
18
|
+
/** The stance a game is asking for, by name. */
|
|
19
|
+
wantsStance: string;
|
|
20
|
+
stances: Record<string, StanceConfig>;
|
|
21
|
+
/** Take the tallest stance's capsule from the mesh instead. */
|
|
22
|
+
measureCapsule: boolean;
|
|
23
|
+
/** What sprinting multiplies the current stance's speed by. */
|
|
24
|
+
sprintScale: number;
|
|
25
|
+
/** Upward metres per second a jump starts with. */
|
|
26
|
+
jumpSpeed: number;
|
|
27
|
+
/** How long a jump request survives, in fixed steps. */
|
|
28
|
+
jumpBufferSteps: number;
|
|
29
|
+
/** How long after leaving the ground a jump is still allowed, in fixed steps. */
|
|
30
|
+
coyoteSteps: number;
|
|
31
|
+
/** Metres per second. */
|
|
32
|
+
velocity: Vector3State;
|
|
33
|
+
/** The character's foot, not the middle of its capsule (design/character.md#state). */
|
|
34
|
+
position: Vector3State;
|
|
35
|
+
/** True only when the last step's support query answered `SUPPORTED`. */
|
|
36
|
+
grounded: boolean;
|
|
37
|
+
/** The stance the character is actually in, which names an entry in `stances`. */
|
|
38
|
+
stance: string;
|
|
39
|
+
}
|
|
40
|
+
export declare class CharacterControllerBehavior extends Behavior<CharacterControllerState, object, NodeEntity> implements NodeBehaviorHooks {
|
|
41
|
+
#private;
|
|
42
|
+
readonly defaults: CharacterControllerState;
|
|
43
|
+
onCreate(): void;
|
|
44
|
+
onMeshLoaded(): void;
|
|
45
|
+
onUpdate(duration: number): void;
|
|
46
|
+
onDestroy(): void;
|
|
47
|
+
/**
|
|
48
|
+
* The velocity the character wants this step, in world space, before the surface it is standing on is added
|
|
49
|
+
* (design/character.md#what-a-game-overrides). The jump is not this method's: an override answers for
|
|
50
|
+
* intent, and the behavior takes the jump around it.
|
|
51
|
+
*/
|
|
52
|
+
protected desiredVelocity(duration: number, surface: CharacterSurfaceInfo): Vector3;
|
|
53
|
+
/**
|
|
54
|
+
* Whether that stance's capsule fits where the character is standing
|
|
55
|
+
* (design/character.md#what-a-game-overrides).
|
|
56
|
+
*/
|
|
57
|
+
protected stanceFits(stance: string): boolean;
|
|
58
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Behavior } from '@skewedaspect/sage-core';
|
|
2
|
+
import { NodeBehaviorHooks, NodeEntity, QuaternionState, Vector3State } from "../entities/nodeEntity.js";
|
|
3
|
+
/** What a body's outline can be (design/physics.md#shapes). */
|
|
4
|
+
export type BodyShape = 'box' | 'sphere' | 'cylinder' | 'convex' | 'mesh' | 'compound';
|
|
5
|
+
/** Who decides where a body goes (design/physics.md#static-dynamic-and-kinematic). */
|
|
6
|
+
export type BodyMotion = 'static' | 'dynamic' | 'kinematic';
|
|
7
|
+
/** One child of a compound shape, placed relative to the entity's node. */
|
|
8
|
+
export interface CompoundPart {
|
|
9
|
+
shape: 'box' | 'sphere' | 'cylinder';
|
|
10
|
+
position: Vector3State;
|
|
11
|
+
rotation: QuaternionState;
|
|
12
|
+
/** Full size: a box's width, height, depth; a sphere's diameter in x; a cylinder's diameter in x, height in y. */
|
|
13
|
+
extents: Vector3State;
|
|
14
|
+
}
|
|
15
|
+
export interface PhysicsBodyState {
|
|
16
|
+
shape: BodyShape;
|
|
17
|
+
/** The children of a `compound` shape. Unused by every other shape. */
|
|
18
|
+
parts: CompoundPart[];
|
|
19
|
+
motion: BodyMotion;
|
|
20
|
+
/** In kilograms. */
|
|
21
|
+
mass: number;
|
|
22
|
+
friction: number;
|
|
23
|
+
restitution: number;
|
|
24
|
+
position: Vector3State;
|
|
25
|
+
rotation: QuaternionState;
|
|
26
|
+
/** Metres per second. */
|
|
27
|
+
velocity: Vector3State;
|
|
28
|
+
/** Radians per second. */
|
|
29
|
+
angularVelocity: Vector3State;
|
|
30
|
+
}
|
|
31
|
+
export declare class HavokPhysicsBodyBehavior extends Behavior<PhysicsBodyState, object, NodeEntity> implements NodeBehaviorHooks {
|
|
32
|
+
#private;
|
|
33
|
+
static readonly ops: readonly ["applyImpulse"];
|
|
34
|
+
readonly defaults: PhysicsBodyState;
|
|
35
|
+
onMeshLoaded(): void;
|
|
36
|
+
onDestroy(): void;
|
|
37
|
+
applyImpulse(impulse: Vector3State, location?: Vector3State): void;
|
|
38
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Behavior } from '@skewedaspect/sage-core';
|
|
2
|
-
import { NodeBehaviorHooks } from "../entities/nodeEntity.
|
|
2
|
+
import { NodeBehaviorHooks, NodeEntity } from "../entities/nodeEntity.js";
|
|
3
3
|
export interface SoundConfig {
|
|
4
4
|
url: string;
|
|
5
5
|
volume?: number;
|
|
@@ -11,7 +11,7 @@ export interface SoundConfig {
|
|
|
11
11
|
export interface SoundState {
|
|
12
12
|
sounds: Record<string, SoundConfig>;
|
|
13
13
|
}
|
|
14
|
-
export declare class SoundBehavior extends Behavior<SoundState> implements NodeBehaviorHooks {
|
|
14
|
+
export declare class SoundBehavior extends Behavior<SoundState, object, NodeEntity> implements NodeBehaviorHooks {
|
|
15
15
|
#private;
|
|
16
16
|
static readonly ops: readonly ["play", "stop"];
|
|
17
17
|
readonly defaults: SoundState;
|
|
@@ -1,23 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
interface DynamicGetter {
|
|
1
|
+
/** What `expose` takes to define a property that resolves fresh on every read. */
|
|
2
|
+
export interface DynamicGetter {
|
|
3
3
|
get: () => unknown;
|
|
4
4
|
}
|
|
5
|
-
export declare class DebugConsole
|
|
6
|
-
private
|
|
7
|
-
private _entries;
|
|
8
|
-
private _disposed;
|
|
5
|
+
export declare class DebugConsole {
|
|
6
|
+
#private;
|
|
9
7
|
constructor(namespaceName?: string);
|
|
10
|
-
|
|
8
|
+
/** Defines a property that resolves fresh on every read (design/debugging.md#debug-tooling). */
|
|
9
|
+
expose(name: string, getter: DynamicGetter): void;
|
|
10
|
+
/** Puts a value, a callable command included, on the namespace (design/debugging.md#debug-tooling). */
|
|
11
|
+
expose(name: string, value: unknown): void;
|
|
11
12
|
setNamespace(name: string): void;
|
|
12
13
|
get namespaceName(): string;
|
|
13
14
|
dispose(): void;
|
|
14
|
-
$teardown(): Promise<void>;
|
|
15
|
-
private _isDynamicGetter;
|
|
16
|
-
private _getNamespace;
|
|
17
|
-
private _assertNamespaceFree;
|
|
18
|
-
private _installNamespace;
|
|
19
|
-
private _removeNamespace;
|
|
20
|
-
private _defineGetter;
|
|
21
|
-
private _defineValue;
|
|
22
15
|
}
|
|
23
|
-
export {};
|
|
@@ -1,33 +1,32 @@
|
|
|
1
|
-
import { AbstractEngine,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { GameTimer } from "../utils/timer.d.ts";
|
|
1
|
+
import { AbstractEngine, Scene } from '@babylonjs/core';
|
|
2
|
+
import { EventBus, Unsubscribe } from '@skewedaspect/sage-core';
|
|
3
|
+
import { GameCanvas } from "../interfaces/game.js";
|
|
4
|
+
import { Disposable } from "../interfaces/lifecycle.js";
|
|
5
|
+
import { NodeEntityRegistry, NodeSimulation } from "../entities/nodeSimulation.js";
|
|
6
|
+
import { MeshLoader } from "../entities/nodeSimulationContext.js";
|
|
7
|
+
import { SceneEngine } from "../engines/scene.js";
|
|
8
|
+
import { AudioEngine } from "../engines/audio.js";
|
|
9
|
+
import { AssetManager } from "../managers/asset.js";
|
|
10
|
+
import { ColliderDebugManager } from "../managers/colliderDebug.js";
|
|
11
|
+
import { DebugConsole } from "./debugConsole.js";
|
|
12
|
+
import { GameManager } from "../managers/game.js";
|
|
13
|
+
import { InputManager } from "../managers/input.js";
|
|
14
|
+
import { LevelManager } from "../managers/level.js";
|
|
15
|
+
import { SimulationSaveManager } from "../managers/simulationSave.js";
|
|
16
|
+
import { AudioManager } from "../managers/audio.js";
|
|
17
|
+
import { LoggingUtility } from "../utils/logger.js";
|
|
18
|
+
import { GameTimer } from "../utils/timer.js";
|
|
20
19
|
/**
|
|
21
20
|
* Type definition for game lifecycle hook functions
|
|
22
21
|
*/
|
|
23
|
-
export type GameHook = (gameEngine: GameEngine) => Promise<void>;
|
|
24
|
-
/** Builds a NodeSimulation bound to a scene and a mesh source -- a fresh one
|
|
25
|
-
export type SimulationFactory = (scene: Scene, meshSource?:
|
|
22
|
+
export type GameHook<Registry extends NodeEntityRegistry = NodeEntityRegistry> = (gameEngine: GameEngine<Registry>) => Promise<void>;
|
|
23
|
+
/** Builds a NodeSimulation named and bound to a scene and a mesh source -- a fresh one for every level that loads. */
|
|
24
|
+
export type SimulationFactory<Registry extends NodeEntityRegistry = NodeEntityRegistry> = (scene: Scene, name: string, meshSource?: MeshLoader) => NodeSimulation<Registry>;
|
|
26
25
|
/**
|
|
27
26
|
* Interface representing the engines used in the game.
|
|
28
27
|
* All engines must implement Disposable for proper cleanup.
|
|
29
28
|
*/
|
|
30
|
-
interface Engines extends Record<string, Disposable | undefined> {
|
|
29
|
+
export interface Engines extends Record<string, Disposable | undefined> {
|
|
31
30
|
sceneEngine: SceneEngine;
|
|
32
31
|
audioEngine?: AudioEngine;
|
|
33
32
|
}
|
|
@@ -35,35 +34,34 @@ interface Engines extends Record<string, Disposable | undefined> {
|
|
|
35
34
|
* Interface representing the managers used in the game.
|
|
36
35
|
* All managers must implement Disposable for proper cleanup.
|
|
37
36
|
*/
|
|
38
|
-
interface Managers extends Record<string, Disposable | undefined> {
|
|
37
|
+
export interface Managers<Registry extends NodeEntityRegistry = NodeEntityRegistry> extends Record<string, Disposable | undefined> {
|
|
39
38
|
assetManager: AssetManager;
|
|
40
|
-
gameManager: GameManager
|
|
39
|
+
gameManager: GameManager<Registry>;
|
|
41
40
|
inputManager: InputManager;
|
|
42
|
-
levelManager: LevelManager
|
|
43
|
-
saveManager: SimulationSaveManager
|
|
41
|
+
levelManager: LevelManager<Registry>;
|
|
42
|
+
saveManager: SimulationSaveManager<Registry>;
|
|
44
43
|
audioManager?: AudioManager;
|
|
45
44
|
}
|
|
46
45
|
/**
|
|
47
46
|
* Interface representing the debug tools available on the engine.
|
|
48
47
|
*/
|
|
49
|
-
interface DebugTools {
|
|
48
|
+
export interface DebugTools {
|
|
50
49
|
colliders: ColliderDebugManager;
|
|
51
50
|
console: DebugConsole | null;
|
|
52
51
|
expose(name: string, value: unknown): void;
|
|
53
52
|
}
|
|
54
53
|
/**
|
|
55
|
-
* Central hub that owns the render loop,
|
|
54
|
+
* Central hub that owns the render loop, the event bus, and all managers.
|
|
56
55
|
* Created via `createGameEngine()` in sage.ts.
|
|
57
56
|
*/
|
|
58
|
-
export declare class GameEngine {
|
|
57
|
+
export declare class GameEngine<Registry extends NodeEntityRegistry = NodeEntityRegistry> {
|
|
58
|
+
#private;
|
|
59
59
|
canvas: GameCanvas;
|
|
60
60
|
renderEngine: AbstractEngine;
|
|
61
|
-
|
|
62
|
-
managers: Managers;
|
|
61
|
+
managers: Managers<Registry>;
|
|
63
62
|
engines: Engines;
|
|
64
|
-
|
|
63
|
+
bus: EventBus;
|
|
65
64
|
logger: LoggingUtility;
|
|
66
|
-
simulation: NodeSimulation | null;
|
|
67
65
|
timer: GameTimer;
|
|
68
66
|
debug: DebugTools;
|
|
69
67
|
largeWorldRendering: boolean;
|
|
@@ -71,78 +69,42 @@ export declare class GameEngine {
|
|
|
71
69
|
private _stopped;
|
|
72
70
|
private _log;
|
|
73
71
|
private _buildSimulation;
|
|
74
|
-
private _beforeStartHook;
|
|
75
|
-
private _onStartHook;
|
|
76
|
-
private _onTeardownHook;
|
|
77
72
|
/**
|
|
78
73
|
* Creates an instance of GameEngine.
|
|
79
|
-
* @param canvas
|
|
80
|
-
* @param renderEngine
|
|
81
|
-
* @param physics
|
|
82
|
-
* @param eventBus
|
|
83
|
-
* @param logger
|
|
84
|
-
* @param timer
|
|
85
74
|
* @param buildSimulation - Builds a fresh simulation for a scene, once rebuildSimulation is called with one.
|
|
86
|
-
* @param engines
|
|
87
|
-
* @param managers
|
|
88
75
|
*/
|
|
89
|
-
constructor(canvas: GameCanvas, renderEngine: AbstractEngine,
|
|
76
|
+
constructor(canvas: GameCanvas, renderEngine: AbstractEngine, bus: EventBus, logger: LoggingUtility, timer: GameTimer, buildSimulation: SimulationFactory<Registry>, engines: Engines, managers: Managers<Registry>, largeWorldRendering: boolean | undefined, debug: DebugTools);
|
|
77
|
+
/** The simulation the engine holds: attached to the bus, stepped by the frame loop, and what a view reads. */
|
|
78
|
+
get simulation(): NodeSimulation<Registry> | null;
|
|
90
79
|
/**
|
|
91
|
-
* Builds a fresh NodeSimulation
|
|
92
|
-
* this once its own scene
|
|
93
|
-
* mesh through that source
|
|
80
|
+
* Builds a fresh NodeSimulation named `name` for the given scene and mesh source, handed this engine's bus and
|
|
81
|
+
* not yet bound. A level calls this once its own scene exists, naming the simulation after itself, so every
|
|
82
|
+
* NodeEntity it spawns gets a node in that scene and loads its mesh through that source; left unset, a spawned
|
|
83
|
+
* entity gets a node with no mesh (design/simulation.md#the-simulations-name).
|
|
94
84
|
*/
|
|
95
|
-
rebuildSimulation(scene: Scene, meshSource?:
|
|
85
|
+
rebuildSimulation(scene: Scene, name: string, meshSource?: MeshLoader): NodeSimulation<Registry>;
|
|
96
86
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
87
|
+
* Binds the engine to a simulation, or to none. The one bound before detaches from the bus and the new one
|
|
88
|
+
* attaches, carrying its entities' subscriptions and held emissions across
|
|
89
|
+
* (design/events.md#one-bus-per-engine).
|
|
100
90
|
*/
|
|
101
|
-
|
|
91
|
+
bindSimulation(simulation: NodeSimulation<Registry> | null): void;
|
|
92
|
+
/** Runs before the frame loop starts, awaited, in registration order (design/engine.md#lifecycle-hooks). */
|
|
93
|
+
onBeforeStart(hook: GameHook<Registry>): Unsubscribe;
|
|
94
|
+
/** Runs after the frame loop has started, awaited, in registration order. */
|
|
95
|
+
onStart(hook: GameHook<Registry>): Unsubscribe;
|
|
96
|
+
/** Runs before anything is disposed, awaited; a hook that throws is logged and does not stop the teardown. */
|
|
97
|
+
onTeardown(hook: GameHook<Registry>): Unsubscribe;
|
|
102
98
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* @throws Error if a hook is already registered
|
|
106
|
-
*/
|
|
107
|
-
onStart(hook: GameHook): void;
|
|
108
|
-
/**
|
|
109
|
-
* Register a function to be called when the game engine stops
|
|
110
|
-
* @param hook
|
|
111
|
-
* @throws Error if a hook is already registered
|
|
112
|
-
*/
|
|
113
|
-
onTeardown(hook: GameHook): void;
|
|
114
|
-
/**
|
|
115
|
-
* Subscribe to an event on the event bus.
|
|
116
|
-
*
|
|
117
|
-
* This is a convenience method that forwards to `eventBus.subscribe()`.
|
|
118
|
-
*
|
|
119
|
-
* @param eventType - Exact event type string, wildcard pattern (e.g. 'level:*'), or RegExp
|
|
120
|
-
* @param callback
|
|
121
|
-
* @returns A function that removes this subscription when called
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* // Subscribe to a specific event
|
|
125
|
-
* const unsub = engine.subscribe('level:complete', (event) => {
|
|
126
|
-
* console.log('Level complete:', event.payload.levelName);
|
|
127
|
-
* });
|
|
128
|
-
*
|
|
129
|
-
* // Subscribe to every level event
|
|
130
|
-
* engine.subscribe('level:*', (event) => {
|
|
131
|
-
* console.log('Level event:', event.type);
|
|
132
|
-
* });
|
|
133
|
-
*/
|
|
134
|
-
subscribe<T extends keyof LibraryEventPayloadMap & string>(eventType: T | WildcardPattern | RegExp, callback: GameEventCallback<T, LibraryEventPayloadMap>): Unsubscribe;
|
|
135
|
-
/**
|
|
136
|
-
* Start the engine: runs beforeStart hook, starts the game manager, then runs onStart hook.
|
|
99
|
+
* Starts the frame loop, with the before-start hooks ahead of it and the start hooks after. An engine that has
|
|
100
|
+
* stopped does not start again (design/architecture.md#teardown).
|
|
137
101
|
*/
|
|
138
102
|
start(): Promise<void>;
|
|
139
103
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* everything to release. Tearing down twice is the no-op.
|
|
104
|
+
* Tears the engine down in one order: the frame loop stops, the teardown hooks run, then the debug console, the
|
|
105
|
+
* managers, and the engines dispose. A failure in one disposal does not stop the rest, and the first one raised
|
|
106
|
+
* is raised again once everything else is disposed. Stopping twice changes nothing
|
|
107
|
+
* (design/architecture.md#teardown).
|
|
145
108
|
*/
|
|
146
109
|
stop(): Promise<void>;
|
|
147
110
|
}
|
|
148
|
-
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Quaternion, Scene, StaticSound, TransformNode, Vector3 } from '@babylonjs/core';
|
|
2
|
-
import { LevelConfig, LevelContext } from "../interfaces/level.
|
|
3
|
-
import { NodeEntity } from "../entities/nodeEntity.
|
|
4
|
-
import { NodeSimulation } from "../entities/nodeSimulation.
|
|
5
|
-
import { Level } from "./level.
|
|
2
|
+
import { LevelConfig, LevelContext } from "../interfaces/level.js";
|
|
3
|
+
import { NodeEntity } from "../entities/nodeEntity.js";
|
|
4
|
+
import { NodeEntityRegistry, NodeSimulation } from "../entities/nodeSimulation.js";
|
|
5
|
+
import { Level } from "./level.js";
|
|
6
6
|
/**
|
|
7
7
|
* Metadata collected from a spawn point node.
|
|
8
8
|
* Transforms are normalized to canonical Babylon space — the source level's __root__
|
|
@@ -23,10 +23,12 @@ interface EntityNodeData {
|
|
|
23
23
|
node: TransformNode;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* The level a game gets when it describes a scene in configuration instead of writing a `Level` subclass: it
|
|
27
|
+
* builds the scene its configuration names, in one fixed order, and spawns what the scene's own markers name
|
|
28
|
+
* (design/levels.md#gamelevel).
|
|
28
29
|
*/
|
|
29
|
-
export declare class GameLevel extends Level {
|
|
30
|
+
export declare class GameLevel<Registry extends NodeEntityRegistry = NodeEntityRegistry> extends Level<Registry> {
|
|
31
|
+
#private;
|
|
30
32
|
/** The level configuration */
|
|
31
33
|
protected _config: LevelConfig;
|
|
32
34
|
/** Collected spawn points from the scene */
|
|
@@ -39,20 +41,14 @@ export declare class GameLevel extends Level {
|
|
|
39
41
|
protected _levelSounds: Map<string, StaticSound>;
|
|
40
42
|
/** Sounds that were playing before deactivation (for resume on activate) */
|
|
41
43
|
private _playingSoundsBeforeDeactivate;
|
|
42
|
-
|
|
43
|
-
* Create a GameLevel from a configuration object
|
|
44
|
-
*
|
|
45
|
-
* @param config
|
|
46
|
-
* @param context
|
|
47
|
-
*/
|
|
48
|
-
constructor(config: LevelConfig, context: LevelContext);
|
|
44
|
+
constructor(config: LevelConfig, context: LevelContext<Registry>);
|
|
49
45
|
get config(): LevelConfig;
|
|
50
46
|
get spawnedEntities(): readonly NodeEntity[];
|
|
51
47
|
/**
|
|
52
48
|
* The simulation this level built its scene against: the one its own spawns and despawns go through,
|
|
53
49
|
* whichever simulation the engine holds at the time. Throws before `buildScene` has bound one.
|
|
54
50
|
*/
|
|
55
|
-
protected get simulation(): NodeSimulation
|
|
51
|
+
protected get simulation(): NodeSimulation<Registry>;
|
|
56
52
|
/**
|
|
57
53
|
* Build the scene by loading assets, processing node metadata, and spawning entities.
|
|
58
54
|
*/
|
|
@@ -78,13 +74,15 @@ export declare class GameLevel extends Level {
|
|
|
78
74
|
*/
|
|
79
75
|
private _createEnvironmentTexture;
|
|
80
76
|
private _getFileExtension;
|
|
77
|
+
private _attachableCanvas;
|
|
81
78
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
79
|
+
* An entry whose key names an imported camera overrides it, and one whose key names none creates a camera
|
|
80
|
+
* of the type it declares. With no camera configuration at all, the first imported camera activates.
|
|
84
81
|
*/
|
|
85
82
|
private _processCameras;
|
|
86
83
|
/**
|
|
87
|
-
* Create a
|
|
84
|
+
* Create a camera of the type an entry declares, or nothing for an entry that cannot be built, which is
|
|
85
|
+
* logged and skipped (design/levels.md#the-load-sequence).
|
|
88
86
|
*/
|
|
89
87
|
private _createCamera;
|
|
90
88
|
/**
|
|
@@ -92,12 +90,12 @@ export declare class GameLevel extends Level {
|
|
|
92
90
|
*/
|
|
93
91
|
private _applyCameraConfig;
|
|
94
92
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
93
|
+
* Lights override and create by key the way cameras do. With no light configuration at all, imported
|
|
94
|
+
* lights are left as they are.
|
|
97
95
|
*/
|
|
98
96
|
private _processLights;
|
|
99
97
|
/**
|
|
100
|
-
* Create a
|
|
98
|
+
* Create a light of the type an entry declares.
|
|
101
99
|
*/
|
|
102
100
|
private _createLight;
|
|
103
101
|
/**
|
|
@@ -117,6 +115,7 @@ export declare class GameLevel extends Level {
|
|
|
117
115
|
* Walk all transform nodes and meshes, normalizing glTF metadata and dispatching to property handlers.
|
|
118
116
|
*/
|
|
119
117
|
private _processNodeProperties;
|
|
118
|
+
private _warnUnhandledProperties;
|
|
120
119
|
/**
|
|
121
120
|
* Check a node's metadata for spawn/entity markers and run any registered property handlers.
|
|
122
121
|
*/
|
|
@@ -150,8 +149,8 @@ export declare class GameLevel extends Level {
|
|
|
150
149
|
*/
|
|
151
150
|
private _spawnEntityNode;
|
|
152
151
|
/**
|
|
153
|
-
* Create
|
|
154
|
-
*
|
|
152
|
+
* Create the sounds the configuration names, keeping each by name so it follows the level: paused on
|
|
153
|
+
* deactivation, played again on activation, disposed with the level (design/levels.md#level-sounds).
|
|
155
154
|
*/
|
|
156
155
|
private _processLevelSounds;
|
|
157
156
|
/**
|
|
@@ -167,6 +166,6 @@ export declare class GameLevel extends Level {
|
|
|
167
166
|
/**
|
|
168
167
|
* Dispose of this level's resources
|
|
169
168
|
*/
|
|
170
|
-
|
|
169
|
+
dispose(): Promise<void>;
|
|
171
170
|
}
|
|
172
171
|
export {};
|