@3dsource/angular-unreal-module 0.0.157 → 0.0.158

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/README.md CHANGED
@@ -1,422 +1,212 @@
1
- # @3dsource/angular-unreal-module
2
-
3
- A set of standalone Angular components, services, and providers for integrating Unreal Engine (WebRTC) scenes into Angular applications. It facilitates communication between Angular and Unreal Engine and enables interactive 3D experiences.
4
-
5
- ## Overview
6
-
7
- This package provides:
8
-
9
- - Standalone Unreal scene component to embed UE stream
10
- - Communication bridge (commands, UI interactions, input data)
11
- - Callback listener for Unreal events and command responses
12
- - NgRx state and effects for 3D stream lifecycle
13
- - Config and utilities for telemetry, errors, and regions ping
14
- - Auto-reconnection support for WebRTC/DataChannel failures
15
- - File receiving from Unreal Engine
16
- - Analytics, FPS monitoring, and stream status telemetry
17
- - Playwright testing mode with mock services
18
-
19
- ## Installation
20
-
21
- ### Prerequisites
22
-
23
- - Angular `>=19.0.0 <23.0.0`
24
- - NgRx store and effects `>=19.0.0 <23.0.0`
25
- - Angular CDK `>=19.0.0 <23.0.0` — used for dialog overlays
26
- - RxJS `>=7.8.0 <8.0.0`
27
- - `provideHttpClient()` — required by internal services (telemetry, signalling, regions ping, error reporting)
28
-
29
- ### Peer Dependencies
30
-
31
- This library requires the following peer dependencies:
32
-
33
- ```json
34
- {
35
- "@3dsource/source-ui-native": ">=1.0.9",
36
- "@3dsource/types-unreal": ">=0.0.7",
37
- "@3dsource/utils": ">=1.0.21",
38
- "@angular/cdk": ">=19.0.0 <23.0.0",
39
- "@angular/common": ">=19.0.0 <23.0.0",
40
- "@angular/core": ">=19.0.0 <23.0.0",
41
- "@angular/forms": ">=19.0.0 <23.0.0",
42
- "@angular/platform-browser": ">=19.0.0 <23.0.0",
43
- "@ngrx/effects": ">=19.0.0 <23.0.0",
44
- "@ngrx/store": ">=19.0.0 <23.0.0",
45
- "rxjs": ">=7.8.0 <8.0.0"
46
- }
47
- ```
48
-
49
- ### Library Installation
50
-
51
- ```shell
52
- npm i @3dsource/angular-unreal-module
53
- ```
54
-
55
- ## Usage
56
-
57
- The API is fully standalone (no NgModule). Use providers and components as shown below.
58
-
59
- ### 1) Provide the state and config at the application root
60
-
61
- Add providers in your application bootstrap (e.g., `app.config.ts`):
62
-
63
- > **⚠️ Important:** `UNREAL_CONFIG` is **required** — multiple internal services inject it without `{ optional: true }`. Omitting it will cause a `NullInjectorError` at runtime. You can provide it with an empty object `{}` as a minimum.
64
-
65
- ```ts
66
- import { ApplicationConfig } from '@angular/core';
67
- import { provideRouter } from '@angular/router';
68
- import { provideHttpClient } from '@angular/common/http';
69
- import { provideStore } from '@ngrx/store';
70
- import { provideUnrealState, UNREAL_CONFIG } from '@3dsource/angular-unreal-module';
71
-
72
- export const appConfig: ApplicationConfig = {
73
- providers: [
74
- provideRouter([]),
75
- provideHttpClient(),
76
-
77
- // Root NgRx (if not already added in your app)
78
- provideStore(),
79
- provideUnrealState(),
80
-
81
- // Required: Unreal initial configuration
82
- {
83
- provide: UNREAL_CONFIG,
84
- useValue: {
85
- customErrorsEndpoint: '', // Endpoint for custom error reporting
86
- commandTelemetryReceiver: '', // Endpoint for command telemetry
87
- regionsPingUrl: '', // URL prefix for regions latency ping
88
- screenLockerContainerId: '', // DOM container id for screen locker overlay
89
- dataChannelConnectionTimeout: 8000, // Timeout in ms for data channel connection (default: 8000)
90
- streamTelemetryV2Url: '', // Endpoint for stream-status telemetry
91
- fpsMonitor: false, // Enable FPS monitoring
92
- autoHighResolution: false, // Raise resolution after the scene becomes idle
93
- playwright: false, // Mirrors the provider flag for services/effects
94
- },
95
- },
96
- ],
97
- };
98
- ```
99
-
100
- #### Minimal configuration
101
-
102
- If you don't need custom endpoints, provide `UNREAL_CONFIG` with an empty object:
103
-
104
- ```ts
105
- { provide: UNREAL_CONFIG, useValue: {} },
106
- provideUnrealState(),
107
- ```
108
-
109
- Every `UnrealInitialConfig` field is optional, but the `UNREAL_CONFIG` provider
110
- itself is required. Available fields are `playwright`,
111
- `customErrorsEndpoint`, `commandTelemetryReceiver`, `regionsPingUrl`,
112
- `screenLockerContainerId`, `dataChannelConnectionTimeout`,
113
- `streamTelemetryV2Url`, `fpsMonitor` and `autoHighResolution`.
114
-
115
- ### 2) Boot the engine in each lazy 3D route
116
-
117
- `provideUnrealModule()` registers the effects and initializes the streaming
118
- services. Put it on every lazy route that renders a 3D scene:
119
-
120
- ```ts
121
- import { Routes } from '@angular/router';
122
- import { provideUnrealModule } from '@3dsource/angular-unreal-module';
123
-
124
- export const STREAM_ROUTES: Routes = [
125
- {
126
- path: ':id',
127
- loadComponent: () => import('./stream.component').then((module) => module.StreamComponent),
128
- providers: [provideUnrealModule()],
129
- },
130
- ];
131
- ```
132
-
133
- Keep `provideUnrealState()` and `UNREAL_CONFIG` at the root. Keeping
134
- `provideUnrealModule()` in lazy routes also keeps the streaming engine out of
135
- the initial application bundle.
136
-
137
- ### 3) Use the Unreal scene component
138
-
139
- Import the component into a standalone component and use it in the template.
140
-
141
- ```ts
142
- import { Component } from '@angular/core';
143
- import { UnrealSceneComponent } from '@3dsource/angular-unreal-module';
144
-
145
- @Component({
146
- selector: 'app-root',
147
- standalone: true,
148
- imports: [UnrealSceneComponent],
149
- template: ` <app-unreal-scene [isStudio]="false" [useContainerAsSizeProvider]="true" [resolutionSize]="{ width: 1920, height: 1080 }" (changeMouseOverScene)="onHover($event)" /> `,
150
- })
151
- export class AppComponent {
152
- onHover(isOver: boolean) {
153
- // handle mouse over scene
154
- }
155
- }
156
- ```
157
-
158
- Component selector: `<app-unreal-scene>`
159
-
160
- Inputs:
161
-
162
- | Input | Type | Default |
163
- | ---------------------------- | ----------------------------------- | ------------------------------- |
164
- | `isStudio` | `boolean` | `false` |
165
- | `useContainerAsSizeProvider` | `boolean` | `true` |
166
- | `resolutionSize` | `{ width: number; height: number }` | `{ width: 1920, height: 1080 }` |
167
-
168
- Outputs:
169
-
170
- | Output | Type |
171
- | ---------------------- | --------------------------- |
172
- | `changeMouseOverScene` | `OutputEmitterRef<boolean>` |
173
-
174
- ### 4) Send commands / interactions to Unreal
175
-
176
- Inject `UnrealCommunicatorService` to send commands or UI interactions. Types for command packets are provided by `@3dsource/types-unreal`.
177
-
178
- There are three sending methods — choose based on your needs:
179
-
180
- | Method | Description |
181
- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
182
- | `sendCommandToUnreal` | Full pipeline: adds `correlationId`, records telemetry, dispatches NgRx `commandStarted` action. **Recommended for application commands.** |
183
- | `emitUIInteraction` | Sends the packet as a raw `UIInteraction` message. No telemetry or store dispatch. |
184
- | `emitCommand` | Sends the packet as a raw `Command` message (for console commands, resolution changes, etc.). |
185
-
186
- ```ts
187
- import { Component, inject } from '@angular/core';
188
- import { UnrealCommunicatorService } from '@3dsource/angular-unreal-module';
189
- import { MetaBoxCommand } from '@3dsource/types-unreal';
190
- import type { MetaBoxCommandPacket } from '@3dsource/types-unreal';
191
-
192
- @Component({ standalone: true, template: '' })
193
- export class MyComponent {
194
- private unreal = inject(UnrealCommunicatorService);
195
-
196
- sendSomeCommand() {
197
- // Recommended: use sendCommandToUnreal for full telemetry + store tracking
198
- this.unreal.sendCommandToUnreal({
199
- command: MetaBoxCommand.FChangeResolutionCommand,
200
- payload: { resolution: { x: 1920, y: 1080 } },
201
- });
202
- }
203
-
204
- sendRawUIInteraction() {
205
- // Low-level: sends UIInteraction message without telemetry tracking
206
- const packet = {
207
- command: 'CustomCommand',
208
- payload: { key: 'value' },
209
- } as MetaBoxCommandPacket;
210
- this.unreal.emitUIInteraction(packet);
211
- }
212
- }
213
- ```
214
-
215
- ### 5) Store integration (actions & selectors)
216
-
217
- `provideUnrealState()` registers the NgRx feature state `unrealFeature`. You
218
- can dispatch actions and select state in your components:
219
-
220
- ```ts
221
- import { inject } from '@angular/core';
222
- import { Store } from '@ngrx/store';
223
- import { disconnectStream, selectShowLoader, selectTotalProgress, setConfig, setOrchestrationContext, startStream, unrealFeature } from '@3dsource/angular-unreal-module';
224
-
225
- // Dispatch actions
226
- const store = inject(Store);
227
- store.dispatch(startStream({ config: { autoStart: true, warnTimeout: 120 } }));
228
-
229
- // Select state
230
- const progress = store.selectSignal(selectTotalProgress);
231
- const isVideoPlaying = store.selectSignal(unrealFeature.selectIsVideoPlaying);
232
- const dataChannelConnected = store.selectSignal(unrealFeature.selectDataChannelConnected);
233
- ```
234
-
235
- **Key selectors:**
236
-
237
- - `selectTotalProgress` — Scene load progress (0–1 float)
238
- - `selectShowLoader` — Whether loader screen should be visible
239
- - `selectShowReconnectPopup` — Whether reconnect popup should be shown
240
- - `selectIsVideoPlayingAndDataChannelConnected` — Combined readiness check
241
- - `selectStreamConfig` — Current stream configuration
242
- - `unrealFeature.selectCirrusConnected` — Signalling server connection status
243
- - `unrealFeature.selectDataChannelConnected` — Data channel status
244
- - `unrealFeature.selectViewportReady` — Viewport readiness
245
-
246
- **Key actions:**
247
-
248
- - `startStream` — Start streaming with config
249
- - `setConfig` — Update stream configuration
250
- - `setOrchestrationContext` — Set orchestration URLs and environment
251
- - `disconnectStream` — Disconnect with reason
252
- - `destroyUnrealScene` — Full teardown
253
- - `reconnectPeer` — Trigger peer reconnection
254
-
255
- ### 6) Listen for Unreal callbacks
256
-
257
- Inject `UnrealCallbackService` to listen for callback events from Unreal Engine and to observe command responses.
258
-
259
- There are two methods:
260
-
261
- | Method | Description |
262
- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
263
- | `fromUnrealCallback` | Listens for callbacks matching a command or event key. Supports MetaBox commands and custom Unreal callback events. Returns `Observable<UnrealCallbackDescriptor[K]>`. |
264
- | `observeCommandResponse` | Sends a command and waits for its matching response by `correlationId`. Returns `Observable<MetaBoxCommandList[K]>`. Includes timeout and error handling. |
265
-
266
- **Custom Unreal callback events** (defined in `UnrealCallbackEventMap`):
267
-
268
- | Event | Payload Type |
269
- | -------------------------- | --------------------------------------------------- |
270
- | `onSceneState` | `FSceneState` |
271
- | `onFocusObject` | `FProductPayload` |
272
- | `cameraChanged` | `FCameraChangedPayload` |
273
- | `onObjectTransformChanged` | `{ objectName: string; transform: FTransformJson }` |
274
- | `onChangeSequence` | `unknown` |
275
- | `onFinishedSequence` | `unknown` |
276
-
277
- ```ts
278
- import { Component, inject } from '@angular/core';
279
- import { UnrealCallbackService } from '@3dsource/angular-unreal-module';
280
- import { UnrealCommunicatorService } from '@3dsource/angular-unreal-module';
281
- import { MetaBoxCommand } from '@3dsource/types-unreal';
282
-
283
- @Component({ standalone: true, template: '' })
284
- export class MyComponent {
285
- private callbackService = inject(UnrealCallbackService);
286
- private communicator = inject(UnrealCommunicatorService);
287
-
288
- listenForCallbacks() {
289
- // Listen for a MetaBox command callback
290
- this.callbackService.fromUnrealCallback(MetaBoxCommand.FLoadProductCommand).subscribe((data) => console.log('Product loaded:', data));
291
-
292
- // Listen for a custom Unreal event
293
- this.callbackService.fromUnrealCallback('cameraChanged').subscribe((data) => console.log('Camera changed:', data));
294
- }
295
-
296
- sendAndObserve() {
297
- // Send a command and observe its response (with correlationId matching)
298
- this.callbackService
299
- .observeCommandResponse(
300
- { command: MetaBoxCommand.FLoopBackCommand },
301
- (data) => this.communicator.sendCommandToUnreal(data),
302
- 60000, // timeout in ms (default: 60000)
303
- true, // emit on timeout (default: true)
304
- )
305
- .subscribe((response) => console.log('Response:', response));
306
- }
307
- }
308
- ```
309
-
310
- ## Exported API
311
-
312
- ### Components
313
-
314
- | Component | Selector | Description |
315
- | ------------------------------- | ------------------ | -------------------------------------- |
316
- | `UnrealSceneComponent` | `app-unreal-scene` | Main scene container with video stream |
317
- | `AfkTimeoutModalComponent` | — | AFK timeout warning modal |
318
- | `FreezeFrameComponent` | — | Freeze frame overlay |
319
- | `LowBandwidthModalComponent` | — | Low bandwidth warning modal |
320
- | `LowBandwidthDetectorComponent` | — | Low bandwidth detector |
321
- | `ImageLoadingSrcComponent` | — | Loading image overlay |
322
- | `IntroSrcComponent` | — | Intro image/video overlay |
323
- | `VideoStatsComponent` | — | Video statistics display |
324
- | `StatGraphComponent` | — | Statistics graph |
325
- | `WebrtcErrorModalComponent` | — | WebRTC error modal |
326
-
327
- ### Services
328
-
329
- | Service | Description |
330
- | ------------------------------ | --------------------------------------------------------------- |
331
- | `UnrealCommunicatorService` | Send commands and UI interactions to Unreal |
332
- | `UnrealCallbackService` | Listen for Unreal callback events and observe command responses |
333
- | `AggregatorService` | Aggregates data channel messages from Unreal |
334
- | `SignallingService` | Manages WebSocket signalling connection |
335
- | `VideoService` | Manages video element and stats |
336
- | `WebRtcPlayerService` | Manages WebRTC peer connection |
337
- | `FreezeFrameService` | Handles freeze frame images |
338
- | `AFKService` | AFK (away from keyboard) detection and timeout |
339
- | `DevModeService` | Toggle dev mode for debugging |
340
- | `FileReceiverService` | Receives files from Unreal via data channel |
341
- | `FileHandlerService` | Processes received files |
342
- | `RegionsPingService` | Pings regions to determine latency |
343
- | `CommandTelemetryService` | Records command telemetry |
344
- | `StreamStatusTelemetryService` | Reports stream status telemetry |
345
- | `AnalyticsService` | Analytics event tracking |
346
- | `FpsMonitorService` | FPS monitoring |
347
-
348
- ### Pipes
349
-
350
- | Pipe | Description |
351
- | ---------- | ------------------------------------------------------------ |
352
- | `SafePipe` | Sanitizes a value for the requested Angular security context |
353
-
354
- ### Interfaces
355
-
356
- | Interface | Description |
357
- | -------------------------- | ---------------------------------------------------------------------------- |
358
- | `UnrealInitialConfig` | Shape for `UNREAL_CONFIG` injection token |
359
- | `StreamConfig` | Stream configuration (autoStart, warnTimeout) |
360
- | `StreamResolutionProps` | Stream resolution width/height |
361
- | `UnrealCallbackEventMap` | Custom Unreal callback events pushed from Unreal via data channel |
362
- | `UnrealCallbackDescriptor` | Combined map of MetaBoxCommandList and UnrealCallbackEventMap callback types |
363
-
364
- ## Features
365
-
366
- - Standalone Unreal Scene Component
367
- - Command and UI Interaction API via `UnrealCommunicatorService`
368
- - Callback listener and command response observer via `UnrealCallbackService`
369
- - Event-driven status UI (freeze frame, video stats, play overlay, AFK, low bandwidth)
370
- - NgRx-powered state management and effects
371
- - **Required** initial configuration via `UNREAL_CONFIG` injection token
372
- - Auto-reconnection on WebRTC/DataChannel failures (configurable)
373
- - File receiving from Unreal Engine via data channel
374
- - Analytics and FPS monitoring
375
- - Playwright testing mode with mock service substitution
376
-
377
- ## Examples
378
-
379
- Check the demo application for complete usage examples:
380
-
381
- ```shell
382
- pnpm demo:start
383
- ```
384
-
385
- See also: `projects/demo/src/app/demo-layout/info-pages/unreal-scene-demo/constants/unreal.routes.ts` for a real-world provider configuration example.
386
-
387
- ## Repository development
388
-
389
- Run package commands from the repository root:
390
-
391
- ```shell
392
- pnpm unreal:build
393
- pnpm unreal:build:watch
394
- pnpm unreal:lint
395
- pnpm unreal:test
396
- pnpm unreal:test:watch
397
- pnpm unreal:test:signalling
398
- pnpm unreal:test:signalling:leaks
399
- ```
400
-
401
- `unreal:build` builds `source-ui-native`, `types-unreal` and `utils` before this
402
- package. `unreal:build:watch` performs that initial build automatically and then
403
- watches `angular-unreal-module`.
404
-
405
- To version and publish:
406
-
407
- ```shell
408
- pnpm unreal:release:patch
409
- pnpm unreal:release:dev
410
- ```
411
-
412
- The release command publishes to npm. After verifying the npm release, purge
413
- the matching jsDelivr tag explicitly:
414
-
415
- ```shell
416
- pnpm unreal:purge-cdn -- latest
417
- ```
418
-
419
- ## Engine requirements
420
-
421
- - Node.js: >=24.16.0
422
- - pnpm: 11.17.0 (activated from the root `packageManager` field via Corepack)
1
+ # @3dsource/angular-unreal-module
2
+
3
+ Standalone Angular integration for Unreal Engine Pixel Streaming. The package
4
+ provides the scene component, WebRTC and signalling lifecycle, NgRx state,
5
+ command/callback APIs, reconnection, file transfer and telemetry.
6
+
7
+ ## Requirements
8
+
9
+ - Angular, Angular CDK and Angular Forms `>=19.0.0 <23.0.0`
10
+ - NgRx Store and Effects `>=19.0.0 <23.0.0`
11
+ - RxJS `>=7.8.0 <8.0.0`
12
+ - `@3dsource/source-ui-native >=1.0.9`
13
+ - `@3dsource/types-unreal >=0.0.7`
14
+ - `@3dsource/utils >=1.0.21`
15
+ - `provideHttpClient()` in the host application
16
+
17
+ ## Installation
18
+
19
+ ```shell
20
+ pnpm add @3dsource/angular-unreal-module @3dsource/source-ui-native @3dsource/types-unreal @3dsource/utils
21
+ ```
22
+
23
+ The package is standalone and does not expose an NgModule.
24
+
25
+ ## Setup
26
+
27
+ ### 1. Register state and configuration once
28
+
29
+ Add the Unreal feature state, HTTP client and configuration at the application
30
+ root. `UNREAL_CONFIG` is required, although all its fields are optional.
31
+
32
+ <!-- prettier-ignore -->
33
+ ```typescript
34
+ import { provideHttpClient } from '@angular/common/http';
35
+ import type { ApplicationConfig } from '@angular/core';
36
+ import { provideStore } from '@ngrx/store';
37
+ import {
38
+ provideUnrealState,
39
+ UNREAL_CONFIG,
40
+ type UnrealInitialConfig,
41
+ } from '@3dsource/angular-unreal-module';
42
+
43
+ const unrealConfig = {
44
+ regionsPingUrl: 'https://datacenter.3dsource.com/regions/',
45
+ dataChannelConnectionTimeout: 8000,
46
+ fpsMonitor: false,
47
+ autoHighResolution: false,
48
+ } satisfies UnrealInitialConfig;
49
+
50
+ export const appConfig: ApplicationConfig = {
51
+ providers: [
52
+ provideHttpClient(),
53
+ provideStore(),
54
+ provideUnrealState(),
55
+ { provide: UNREAL_CONFIG, useValue: unrealConfig },
56
+ ],
57
+ };
58
+ ```
59
+
60
+ Omit `provideStore()` when the root NgRx store is already configured.
61
+
62
+ Available configuration fields:
63
+
64
+ | Field | Purpose |
65
+ | ------------------------------ | ---------------------------------------------- |
66
+ | `regionsPingUrl` | Region latency endpoint |
67
+ | `dataChannelConnectionTimeout` | DataChannel connection timeout in ms |
68
+ | `customErrorsEndpoint` | Custom error reporting endpoint |
69
+ | `commandTelemetryReceiver` | Command telemetry endpoint |
70
+ | `streamTelemetryV2Url` | Stream lifecycle telemetry endpoint |
71
+ | `screenLockerContainerId` | Container used by the screen-locker overlay |
72
+ | `fpsMonitor` | Enables FPS monitoring |
73
+ | `autoHighResolution` | Raises resolution after the scene becomes idle |
74
+ | `playwright` | Enables the test-specific service behaviour |
75
+
76
+ Use `{ provide: UNREAL_CONFIG, useValue: {} }` for the minimal configuration.
77
+
78
+ ### 2. Boot the engine on a lazy route
79
+
80
+ Lazy-load the route file from the application router:
81
+
82
+ <!-- prettier-ignore -->
83
+ ```typescript
84
+ import type { Routes } from '@angular/router';
85
+
86
+ export const APP_ROUTES: Routes = [
87
+ {
88
+ path: 'stream',
89
+ loadChildren: () =>
90
+ import('./stream/stream.routes').then((module) => module.STREAM_ROUTES),
91
+ },
92
+ ];
93
+ ```
94
+
95
+ Register `provideUnrealModule()` inside that lazy route file:
96
+
97
+ <!-- prettier-ignore -->
98
+ ```typescript
99
+ import type { Routes } from '@angular/router';
100
+ import { provideUnrealModule } from '@3dsource/angular-unreal-module';
101
+ import { StreamComponent } from './stream.component';
102
+
103
+ export const STREAM_ROUTES: Routes = [
104
+ {
105
+ path: '',
106
+ component: StreamComponent,
107
+ providers: [provideUnrealModule()],
108
+ },
109
+ ];
110
+ ```
111
+
112
+ Keep `provideUnrealState()` and `UNREAL_CONFIG` at the application root.
113
+ The `loadChildren()` boundary keeps the streaming engine out of the initial
114
+ bundle. Route-scoping `provideUnrealModule()` tears down its effects when the
115
+ route is left.
116
+
117
+ ### 3. Render the scene
118
+
119
+ ```typescript
120
+ import { ChangeDetectionStrategy, Component } from '@angular/core';
121
+ import { UnrealSceneComponent } from '@3dsource/angular-unreal-module';
122
+
123
+ @Component({
124
+ selector: 'app-stream',
125
+ imports: [UnrealSceneComponent],
126
+ template: `<app-unreal-scene />`,
127
+ changeDetection: ChangeDetectionStrategy.OnPush,
128
+ })
129
+ export class StreamComponent {}
130
+ ```
131
+
132
+ `UnrealSceneComponent` also accepts `isStudio`,
133
+ `useContainerAsSizeProvider` and `resolutionSize` inputs, and emits
134
+ `changeMouseOverScene`.
135
+
136
+ ## Main API
137
+
138
+ - `provideUnrealState()` — registers the `unrealFeature` NgRx state.
139
+ - `provideUnrealModule()` — registers effects and boots streaming services.
140
+ - `UnrealSceneComponent` — renders and manages the Pixel Streaming scene.
141
+ - `UnrealCommunicatorService` — sends commands and UI interactions.
142
+ - `UnrealCallbackService` — observes Unreal callbacks and command responses.
143
+ - `unrealFeature`, exported selectors and actions — expose connection and scene
144
+ lifecycle state.
145
+ - `FileReceiverService` and `FileHandlerService` — receive files over the
146
+ DataChannel.
147
+
148
+ Command packet types are provided by `@3dsource/types-unreal`.
149
+
150
+ Run `pnpm demo:start` from the repository root to see the scene component in
151
+ the demo application.
152
+
153
+ ## Optional prefetch scripts
154
+
155
+ The package publishes two dependency-free scripts for use in the document
156
+ `<head>` before Angular starts:
157
+
158
+ - `region-ping-prefetch.js` measures regions early and caches the closest one.
159
+ - `stream-prefetch.js` opens and parks an eligible WebRTC connection so Angular
160
+ can adopt it after bootstrap.
161
+
162
+ <!-- prettier-ignore -->
163
+ ```html
164
+ <script
165
+ src="https://cdn.jsdelivr.net/npm/@3dsource/angular-unreal-module/js/region-ping-prefetch.js"
166
+ async
167
+ ></script>
168
+ <script
169
+ src="https://cdn.jsdelivr.net/npm/@3dsource/angular-unreal-module/js/stream-prefetch.js"
170
+ async
171
+ ></script>
172
+ ```
173
+
174
+ `stream-prefetch.js` runs by default only on
175
+ `metabox-configurator/{modular|basic}/...` routes. It reads the same-origin
176
+ `assets/config.json`; override that path with `data-config-url` when needed.
177
+ Pin an exact package version in production when deterministic CDN assets are
178
+ required.
179
+
180
+ ## Repository development
181
+
182
+ Run commands from the repository root:
183
+
184
+ ```shell
185
+ pnpm unreal:build
186
+ pnpm unreal:build:watch
187
+ pnpm unreal:lint
188
+ pnpm unreal:test
189
+ pnpm unreal:test:watch
190
+ pnpm unreal:test:signalling
191
+ pnpm unreal:test:signalling:leaks
192
+ ```
193
+
194
+ `unreal:build` builds the local `source-ui-native`, `types-unreal` and `utils`
195
+ dependencies before this package.
196
+
197
+ Release commands publish only this package:
198
+
199
+ ```shell
200
+ pnpm unreal:release:patch
201
+ pnpm unreal:release:dev
202
+ ```
203
+
204
+ After a successful publish, the release automatically purges the matching
205
+ jsDelivr tag. Retry a failed purge without rerunning the release:
206
+
207
+ ```shell
208
+ pnpm unreal:purge-cdn -- latest
209
+ pnpm unreal:purge-cdn -- dev
210
+ ```
211
+
212
+ Repository tooling requires Node.js 24.16.0 or newer and pnpm 11.17.0.