@vgai/engine 0.2.0
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 +202 -0
- package/README.md +35 -0
- package/package.json +55 -0
- package/src/adapter/authoring.ts +402 -0
- package/src/adapter/colyseus-networking-adapter.ts +72 -0
- package/src/adapter/first-party-systems.ts +103 -0
- package/src/adapter/game-adapter.ts +151 -0
- package/src/adapter/host-context.ts +77 -0
- package/src/adapter/index.ts +85 -0
- package/src/adapter/ingest/game-contract.ts +59 -0
- package/src/adapter/ingest/overlay-applier.ts +207 -0
- package/src/adapter/ingest/overlay-apply.ts +124 -0
- package/src/adapter/ingest/overlay-file.ts +126 -0
- package/src/adapter/ingest/overlay-report.ts +176 -0
- package/src/adapter/ingest/scene-capture.ts +307 -0
- package/src/adapter/ingest/upstream-pin.ts +52 -0
- package/src/adapter/loop-gate-report.ts +54 -0
- package/src/adapter/rapier-physics-adapter.ts +56 -0
- package/src/adapter/system-adapter.ts +154 -0
- package/src/adapter/transform.ts +18 -0
- package/src/adapter/vgai-scene-game-adapter.ts +886 -0
- package/src/adapter/world-kind.ts +34 -0
- package/src/ai/navigation.ts +164 -0
- package/src/animation/anim-graph-types.ts +56 -0
- package/src/animation/anim-graph.ts +406 -0
- package/src/animation/anim-system.ts +28 -0
- package/src/animation/blend-node.ts +119 -0
- package/src/animation/property-track.ts +178 -0
- package/src/animation/schema.ts +204 -0
- package/src/assets.ts +80 -0
- package/src/audio/ambient.ts +300 -0
- package/src/audio/impacts.ts +212 -0
- package/src/audio/index.ts +7 -0
- package/src/audio/movement.ts +140 -0
- package/src/audio/musical.ts +200 -0
- package/src/audio/ui-sounds.ts +171 -0
- package/src/audio/vehicle.ts +235 -0
- package/src/audio/weapons.ts +152 -0
- package/src/core/game-loop.ts +127 -0
- package/src/core/system-runner.ts +298 -0
- package/src/core/types.ts +58 -0
- package/src/dev/console-bridge.ts +83 -0
- package/src/dev/debug-draw.ts +80 -0
- package/src/dev/logger.ts +119 -0
- package/src/ecs/component-manager.ts +748 -0
- package/src/ecs/game-component.ts +147 -0
- package/src/ecs/hmr-swap-report.ts +65 -0
- package/src/input/input-manager.ts +439 -0
- package/src/input/input-types.ts +19 -0
- package/src/input/schema.ts +129 -0
- package/src/loader.ts +70 -0
- package/src/manifest/index.ts +24 -0
- package/src/manifest/load-file.ts +16 -0
- package/src/manifest/load.ts +378 -0
- package/src/manifest/schema.ts +375 -0
- package/src/physics/collision-system.ts +76 -0
- package/src/physics/physics-registry.ts +83 -0
- package/src/physics/transform-writer.ts +41 -0
- package/src/physics/trigger-dispatch.ts +97 -0
- package/src/react/game-state.tsx +172 -0
- package/src/render/auto-batcher.ts +169 -0
- package/src/render/render-batch-system.ts +268 -0
- package/src/render/render-features.ts +146 -0
- package/src/render/render-settings.ts +72 -0
- package/src/runtime/create-runtime.ts +1152 -0
- package/src/runtime/frame-selector-cache.ts +81 -0
- package/src/runtime/game.ts +1003 -0
- package/src/runtime/input-router.ts +213 -0
- package/src/runtime/mount-game.ts +269 -0
- package/src/runtime/mount-manifest.ts +361 -0
- package/src/runtime/scene-ui-bridge.ts +86 -0
- package/src/runtime/scene-ui-data.ts +119 -0
- package/src/runtime/state-bridge.ts +79 -0
- package/src/runtime/types.ts +196 -0
- package/src/scene/asset-loaders.ts +195 -0
- package/src/scene/asset-paths.ts +123 -0
- package/src/scene/asset-registry.ts +67 -0
- package/src/scene/collider-dimensions.ts +125 -0
- package/src/scene/component-registry.ts +40 -0
- package/src/scene/defaults.ts +164 -0
- package/src/scene/geometries/index.ts +7 -0
- package/src/scene/geometries/terrain.ts +42 -0
- package/src/scene/geometry-registry.ts +42 -0
- package/src/scene/instance-registry.ts +84 -0
- package/src/scene/instancers/grid.ts +38 -0
- package/src/scene/instancers/index.ts +7 -0
- package/src/scene/light-camera-factory.ts +97 -0
- package/src/scene/material-factory.ts +211 -0
- package/src/scene/material-registry.ts +73 -0
- package/src/scene/materials/index.ts +7 -0
- package/src/scene/materials/water.ts +56 -0
- package/src/scene/parse.ts +71 -0
- package/src/scene/particles-factory.ts +383 -0
- package/src/scene/scene-apply.ts +356 -0
- package/src/scene/scene-diff-schema.ts +115 -0
- package/src/scene/scene-diff-types.ts +29 -0
- package/src/scene/scene-loader.ts +1533 -0
- package/src/scene/scene-query.ts +63 -0
- package/src/scene/scene-types.ts +34 -0
- package/src/scene/scene-version.ts +40 -0
- package/src/scene/schema/animation.ts +95 -0
- package/src/scene/schema/audio.ts +25 -0
- package/src/scene/schema/camera.ts +21 -0
- package/src/scene/schema/collider.ts +69 -0
- package/src/scene/schema/entity-ref.ts +78 -0
- package/src/scene/schema/entity.ts +169 -0
- package/src/scene/schema/environment.ts +384 -0
- package/src/scene/schema/index.ts +95 -0
- package/src/scene/schema/instances.ts +35 -0
- package/src/scene/schema/joint.ts +26 -0
- package/src/scene/schema/light.ts +38 -0
- package/src/scene/schema/material.ts +113 -0
- package/src/scene/schema/mesh.ts +108 -0
- package/src/scene/schema/particles.ts +398 -0
- package/src/scene/schema/physics.ts +49 -0
- package/src/scene/schema/scene-file.ts +299 -0
- package/src/scene/schema/shadow.ts +24 -0
- package/src/scene/schema/spline.ts +21 -0
- package/src/scene/schema/tuples.ts +21 -0
- package/src/scene/schema/ui.ts +602 -0
- package/src/scene/user-data.ts +203 -0
- package/src/setup/setup-audio.ts +60 -0
- package/src/setup/setup-particles.ts +23 -0
- package/src/setup/setup-physics.ts +67 -0
- package/src/setup/setup-renderer.ts +529 -0
- package/src/types-n8ao.d.ts +37 -0
- package/src/types-realism-effects.d.ts +61 -0
- package/src/world2d/authoring-2d.ts +208 -0
- package/src/world2d/capture-to-scene2d.ts +52 -0
- package/src/world2d/collision-2d.ts +106 -0
- package/src/world2d/components-2d.ts +86 -0
- package/src/world2d/index.ts +66 -0
- package/src/world2d/ingest-iframe-2d.ts +255 -0
- package/src/world2d/ingest2d.ts +131 -0
- package/src/world2d/physics2d-registry.ts +49 -0
- package/src/world2d/pixi-game-adapter.ts +325 -0
- package/src/world2d/pixi-surface.ts +78 -0
- package/src/world2d/scene-capture-2d.ts +117 -0
- package/src/world2d/scene2d-loader.ts +308 -0
- package/src/world2d/schema/entity2d.ts +145 -0
- package/src/world2d/schema/physics2d.ts +53 -0
- package/src/world2d/schema/sprite.ts +71 -0
- package/src/world2d/schema/tilemap.ts +22 -0
- package/src/world2d/schema/tuples2d.ts +25 -0
- package/src/world2d/system-adapters-2d.ts +49 -0
- package/src/world2d/transform-writer-2d.ts +24 -0
- package/src/world2d/types.ts +55 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev-mode console bridge.
|
|
3
|
+
*
|
|
4
|
+
* Monkey-patches console.log / warn / error to also broadcast each message
|
|
5
|
+
* via `window.postMessage`. Any parent frame (IDE, editor, test harness) can
|
|
6
|
+
* listen for these messages — if nobody is listening they simply go nowhere.
|
|
7
|
+
*
|
|
8
|
+
* Also captures unhandled errors and promise rejections.
|
|
9
|
+
*
|
|
10
|
+
* Call once, as early as possible in the entry point:
|
|
11
|
+
*
|
|
12
|
+
* import { installConsoleBridge } from '@engine/dev/console-bridge';
|
|
13
|
+
* if (import.meta.env.DEV) installConsoleBridge();
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export interface ConsoleBridgeMessage {
|
|
17
|
+
type: 'console-bridge';
|
|
18
|
+
level: 'log' | 'warn' | 'error';
|
|
19
|
+
message: string;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const LEVELS = ['log', 'warn', 'error'] as const;
|
|
24
|
+
|
|
25
|
+
function post(level: ConsoleBridgeMessage['level'], message: string): void {
|
|
26
|
+
const msg: ConsoleBridgeMessage = {
|
|
27
|
+
type: 'console-bridge',
|
|
28
|
+
level,
|
|
29
|
+
message,
|
|
30
|
+
timestamp: Date.now(),
|
|
31
|
+
};
|
|
32
|
+
window.postMessage(msg, '*');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function stringify(args: unknown[]): string {
|
|
36
|
+
return args
|
|
37
|
+
.map((a) => {
|
|
38
|
+
if (typeof a === 'string') return a;
|
|
39
|
+
try {
|
|
40
|
+
return JSON.stringify(a);
|
|
41
|
+
} catch {
|
|
42
|
+
return String(a);
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
.join(' ');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let installed = false;
|
|
49
|
+
|
|
50
|
+
export function installConsoleBridge(): void {
|
|
51
|
+
// Idempotent: a second call must not double-patch console (which would
|
|
52
|
+
// double-post every message) nor add duplicate window listeners.
|
|
53
|
+
if (installed) return;
|
|
54
|
+
installed = true;
|
|
55
|
+
|
|
56
|
+
// Lazy import — avoid hard dep; if logger.ts isn't bundled the flag stays false
|
|
57
|
+
let getFlag: () => boolean = () => false;
|
|
58
|
+
import('./logger')
|
|
59
|
+
.then((m) => {
|
|
60
|
+
getFlag = () => m._engineLogActive;
|
|
61
|
+
})
|
|
62
|
+
.catch(() => {});
|
|
63
|
+
|
|
64
|
+
// Patch console methods
|
|
65
|
+
for (const level of LEVELS) {
|
|
66
|
+
const original = console[level].bind(console);
|
|
67
|
+
console[level] = (...args: unknown[]) => {
|
|
68
|
+
original(...args);
|
|
69
|
+
// Skip bridge posting when the engine logger is handling the message
|
|
70
|
+
// (it posts its own structured 'engine-log' message instead)
|
|
71
|
+
if (!getFlag()) post(level, stringify(args));
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Capture unhandled errors
|
|
76
|
+
window.addEventListener('error', (e) => {
|
|
77
|
+
post('error', e.message || String(e.error));
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
window.addEventListener('unhandledrejection', (e) => {
|
|
81
|
+
post('error', `Unhandled promise rejection: ${e.reason}`);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Debug drawing utilities for development.
|
|
5
|
+
*
|
|
6
|
+
* Draw lines, spheres, boxes, and arrows for visualizing
|
|
7
|
+
* physics colliders, raycasts, AI paths, etc.
|
|
8
|
+
*
|
|
9
|
+
* All debug objects are added to a dedicated group that can be toggled.
|
|
10
|
+
*/
|
|
11
|
+
export function createDebugDraw(scene: THREE.Scene) {
|
|
12
|
+
const group = new THREE.Group();
|
|
13
|
+
group.name = 'debug-draw';
|
|
14
|
+
scene.add(group);
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
/** Draw a line between two points */
|
|
18
|
+
line(from: THREE.Vector3, to: THREE.Vector3, color = 0x00ff00) {
|
|
19
|
+
const geometry = new THREE.BufferGeometry().setFromPoints([from, to]);
|
|
20
|
+
const material = new THREE.LineBasicMaterial({ color });
|
|
21
|
+
const line = new THREE.Line(geometry, material);
|
|
22
|
+
group.add(line);
|
|
23
|
+
return line;
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
/** Draw a wireframe sphere at a position */
|
|
27
|
+
sphere(center: THREE.Vector3, radius = 0.1, color = 0xff0000) {
|
|
28
|
+
const geo = new THREE.SphereGeometry(radius, 8, 8);
|
|
29
|
+
const mat = new THREE.MeshBasicMaterial({ color, wireframe: true });
|
|
30
|
+
const mesh = new THREE.Mesh(geo, mat);
|
|
31
|
+
mesh.position.copy(center);
|
|
32
|
+
group.add(mesh);
|
|
33
|
+
return mesh;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
/** Draw a wireframe box */
|
|
37
|
+
box(center: THREE.Vector3, size: THREE.Vector3, color = 0x00ffff) {
|
|
38
|
+
const geo = new THREE.BoxGeometry(size.x, size.y, size.z);
|
|
39
|
+
const mat = new THREE.MeshBasicMaterial({ color, wireframe: true });
|
|
40
|
+
const mesh = new THREE.Mesh(geo, mat);
|
|
41
|
+
mesh.position.copy(center);
|
|
42
|
+
group.add(mesh);
|
|
43
|
+
return mesh;
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
/** Draw an arrow (direction indicator) */
|
|
47
|
+
arrow(origin: THREE.Vector3, direction: THREE.Vector3, length = 1, color = 0xffff00) {
|
|
48
|
+
// Clone before normalize() — never mutate the caller's vector.
|
|
49
|
+
const dir = direction.clone().normalize();
|
|
50
|
+
const arrow = new THREE.ArrowHelper(dir, origin, length, color);
|
|
51
|
+
group.add(arrow);
|
|
52
|
+
return arrow;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/** Clear all debug drawings */
|
|
56
|
+
clear() {
|
|
57
|
+
while (group.children.length > 0) {
|
|
58
|
+
const child = group.children[0]!;
|
|
59
|
+
group.remove(child);
|
|
60
|
+
if (child instanceof THREE.Mesh || child instanceof THREE.Line) {
|
|
61
|
+
// Mesh, Line and LineSegments all own geometry + material.
|
|
62
|
+
child.geometry.dispose();
|
|
63
|
+
(child.material as THREE.Material).dispose();
|
|
64
|
+
} else if (child instanceof THREE.ArrowHelper) {
|
|
65
|
+
// ArrowHelper owns a line + cone; dispose() frees both.
|
|
66
|
+
child.dispose();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/** Toggle debug draw visibility */
|
|
72
|
+
set visible(v: boolean) {
|
|
73
|
+
group.visible = v;
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
get visible() {
|
|
77
|
+
return group.visible;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { BlankTransport, LogLayer, LogLevel } from 'loglayer';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Flag set while the engine logger is calling console.* so that the
|
|
5
|
+
* console-bridge and play-mode patches can skip re-forwarding.
|
|
6
|
+
* JS is single-threaded so this is safe.
|
|
7
|
+
*/
|
|
8
|
+
export let _engineLogActive = false;
|
|
9
|
+
|
|
10
|
+
const CONSOLE_MAP: Record<string, 'log' | 'warn' | 'error'> = {
|
|
11
|
+
trace: 'log',
|
|
12
|
+
debug: 'log',
|
|
13
|
+
info: 'log',
|
|
14
|
+
warn: 'warn',
|
|
15
|
+
error: 'error',
|
|
16
|
+
fatal: 'error',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const engineLog = new LogLayer({
|
|
20
|
+
transport: new BlankTransport({
|
|
21
|
+
shipToLogger: ({ logLevel, messages, data, hasData }) => {
|
|
22
|
+
const method = CONSOLE_MAP[logLevel] ?? 'log';
|
|
23
|
+
|
|
24
|
+
// Extract _sub (subsystem tag) from data, pass the rest as metadata
|
|
25
|
+
let subsystem: string | undefined;
|
|
26
|
+
let metadata: Record<string, unknown> | undefined;
|
|
27
|
+
if (hasData && data) {
|
|
28
|
+
const { _sub, ...rest } = data as Record<string, unknown>;
|
|
29
|
+
subsystem = _sub ? String(_sub) : undefined;
|
|
30
|
+
if (Object.keys(rest).length > 0) metadata = rest;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Call console for browser devtools
|
|
34
|
+
_engineLogActive = true;
|
|
35
|
+
if (metadata) {
|
|
36
|
+
// biome-ignore lint/suspicious/noConsole: intentional — this IS the logger
|
|
37
|
+
console[method](...messages, metadata);
|
|
38
|
+
} else {
|
|
39
|
+
// biome-ignore lint/suspicious/noConsole: intentional — this IS the logger
|
|
40
|
+
console[method](...messages);
|
|
41
|
+
}
|
|
42
|
+
_engineLogActive = false;
|
|
43
|
+
|
|
44
|
+
// Post structured message for editor console
|
|
45
|
+
if (typeof window !== 'undefined') {
|
|
46
|
+
window.postMessage(
|
|
47
|
+
{
|
|
48
|
+
type: 'engine-log',
|
|
49
|
+
level: logLevel,
|
|
50
|
+
message: messages.join(' '),
|
|
51
|
+
subsystem,
|
|
52
|
+
metadata,
|
|
53
|
+
timestamp: Date.now(),
|
|
54
|
+
},
|
|
55
|
+
'*',
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return messages;
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
prefix: '[engine]',
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Default to 'info' — debug/trace are off unless explicitly enabled
|
|
66
|
+
engineLog.setLevel(LogLevel.info);
|
|
67
|
+
|
|
68
|
+
export interface LogMeta {
|
|
69
|
+
entityId?: string | number | undefined;
|
|
70
|
+
[key: string]: unknown;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface SubsystemLogger {
|
|
74
|
+
debug(msg: string, meta?: LogMeta): void;
|
|
75
|
+
info(msg: string, meta?: LogMeta): void;
|
|
76
|
+
warn(msg: string, meta?: LogMeta): void;
|
|
77
|
+
error(msg: string, meta?: LogMeta): void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function createSubsystemLogger(subsystem: string): SubsystemLogger {
|
|
81
|
+
return {
|
|
82
|
+
debug: (msg, meta) =>
|
|
83
|
+
engineLog.withMetadata({ ...meta, _sub: subsystem }).debug(`[${subsystem}] ${msg}`),
|
|
84
|
+
info: (msg, meta) =>
|
|
85
|
+
engineLog.withMetadata({ ...meta, _sub: subsystem }).info(`[${subsystem}] ${msg}`),
|
|
86
|
+
warn: (msg, meta) =>
|
|
87
|
+
engineLog.withMetadata({ ...meta, _sub: subsystem }).warn(`[${subsystem}] ${msg}`),
|
|
88
|
+
error: (msg, meta) =>
|
|
89
|
+
engineLog.withMetadata({ ...meta, _sub: subsystem }).error(`[${subsystem}] ${msg}`),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Pre-built subsystem loggers — all share the same LogLayer instance
|
|
94
|
+
// so setLevel() on engineLog affects all of them.
|
|
95
|
+
export const log = {
|
|
96
|
+
scene: createSubsystemLogger('scene'),
|
|
97
|
+
physics: createSubsystemLogger('physics'),
|
|
98
|
+
animation: createSubsystemLogger('animation'),
|
|
99
|
+
network: createSubsystemLogger('network'),
|
|
100
|
+
audio: createSubsystemLogger('audio'),
|
|
101
|
+
ai: createSubsystemLogger('ai'),
|
|
102
|
+
input: createSubsystemLogger('input'),
|
|
103
|
+
core: createSubsystemLogger('core'),
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { engineLog };
|
|
107
|
+
|
|
108
|
+
// Expose to browser devtools: type setEngineLogLevel('debug') in console
|
|
109
|
+
if (typeof window !== 'undefined') {
|
|
110
|
+
(window as unknown as Record<string, unknown>)['setEngineLogLevel'] = (level: string) => {
|
|
111
|
+
engineLog.setLevel(level as LogLevel);
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// URL param override: ?engineLogLevel=debug
|
|
116
|
+
if (typeof window !== 'undefined') {
|
|
117
|
+
const level = new URLSearchParams(window.location.search).get('engineLogLevel');
|
|
118
|
+
if (level) engineLog.setLevel(level as LogLevel);
|
|
119
|
+
}
|