@utsp/runtime-client 0.11.0 → 0.12.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/dist/index.cjs +1 -1
- package/dist/index.d.ts +897 -237
- package/dist/index.mjs +1 -1
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,704 @@
|
|
|
1
|
+
import { Core, User, AnyPostProcessOrder } from '@utsp/core';
|
|
2
|
+
import { IApplication, IRenderer } from '@utsp/types';
|
|
3
|
+
export { IApplication } from '@utsp/types';
|
|
1
4
|
import { AutoplayOverlayOptions, PostProcessOverlay } from '@utsp/render';
|
|
2
5
|
export { ScalingMode } from '@utsp/render';
|
|
3
6
|
import { AudioManager } from '@utsp/audio';
|
|
4
7
|
export { AudioManager, AudioManagerOptions, ToneOptions } from '@utsp/audio';
|
|
5
|
-
import
|
|
6
|
-
|
|
8
|
+
import * as _utsp_input from '@utsp/input';
|
|
9
|
+
import { UnifiedInputRouter, MobileVibration } from '@utsp/input';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base Runtime Types
|
|
13
|
+
*
|
|
14
|
+
* Types shared by all client runtime variants (Micro, Mini, Standard)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Renderer type to use
|
|
19
|
+
*/
|
|
20
|
+
declare enum RendererType {
|
|
21
|
+
/** WebGL2 renderer - Optimized WebGL 1.0 with GPU palette, instanced rendering (default, recommended) */
|
|
22
|
+
TerminalGL = "webgl",
|
|
23
|
+
/** Canvas 2D renderer - CPU fallback with ImageData optimization for benchmarks */
|
|
24
|
+
Terminal2D = "terminal2d"
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Render mode for runtimes
|
|
28
|
+
*/
|
|
29
|
+
type RenderMode =
|
|
30
|
+
/** Continuous rendering at max FPS (default) - requestAnimationFrame loop */
|
|
31
|
+
'continuous'
|
|
32
|
+
/** On-demand rendering - only renders when explicitly requested via requestRender() */
|
|
33
|
+
| 'on-demand';
|
|
34
|
+
/**
|
|
35
|
+
* Base options shared by all client runtime variants
|
|
36
|
+
*/
|
|
37
|
+
interface BaseRuntimeOptions {
|
|
38
|
+
/** Application instance */
|
|
39
|
+
application: IApplication;
|
|
40
|
+
/** Container HTML element for rendering */
|
|
41
|
+
container: HTMLElement;
|
|
42
|
+
/** Enable debug logging */
|
|
43
|
+
debug?: boolean;
|
|
44
|
+
/** Initial display width in columns (default: 80). Can be overridden by IApplication via Display */
|
|
45
|
+
width?: number;
|
|
46
|
+
/** Initial display height in rows (default: 25). Can be overridden by IApplication via Display */
|
|
47
|
+
height?: number;
|
|
48
|
+
/** Renderer type (default: TerminalGL) */
|
|
49
|
+
renderer?: RendererType;
|
|
50
|
+
/** Enable ImageData rendering for Canvas 2D (default: true). */
|
|
51
|
+
useImageDataRendering?: boolean;
|
|
52
|
+
/** Render mode: 'continuous' (default) or 'on-demand' */
|
|
53
|
+
renderMode?: RenderMode;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Performance timing for a single frame
|
|
57
|
+
*/
|
|
58
|
+
interface FrameTiming$1 {
|
|
59
|
+
/** Time spent in Core tick (ms) */
|
|
60
|
+
coreTime: number;
|
|
61
|
+
/** Time spent in Renderer (ms) */
|
|
62
|
+
renderTime: number;
|
|
63
|
+
/** Total frame time (ms) */
|
|
64
|
+
totalTime: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Base runtime statistics
|
|
68
|
+
*/
|
|
69
|
+
interface BaseRuntimeStats {
|
|
70
|
+
/** Is runtime currently running */
|
|
71
|
+
running: boolean;
|
|
72
|
+
/** Number of users */
|
|
73
|
+
userCount: number;
|
|
74
|
+
/** Current FPS */
|
|
75
|
+
fps: number;
|
|
76
|
+
/** Uptime in milliseconds */
|
|
77
|
+
uptime: number;
|
|
78
|
+
/** Total frames processed */
|
|
79
|
+
totalFrames: number;
|
|
80
|
+
/** Last frame timing breakdown */
|
|
81
|
+
lastFrameTiming?: FrameTiming$1;
|
|
82
|
+
/** Average frame timing over last 60 frames */
|
|
83
|
+
avgFrameTiming?: FrameTiming$1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Performance Monitor
|
|
88
|
+
*
|
|
89
|
+
* Tracks and monitors runtime performance metrics including FPS,
|
|
90
|
+
* frame timing, and rolling averages.
|
|
91
|
+
*
|
|
92
|
+
* This class is responsible for:
|
|
93
|
+
* - FPS calculation and tracking
|
|
94
|
+
* - Frame timing measurements (core, render, total)
|
|
95
|
+
* - Rolling averages over configurable sample size
|
|
96
|
+
* - Performance statistics reporting
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const monitor = new PerformanceMonitor(60); // 60 sample rolling average
|
|
101
|
+
*
|
|
102
|
+
* // In initialization
|
|
103
|
+
* monitor.startTracking(performance.now());
|
|
104
|
+
*
|
|
105
|
+
* // Every frame
|
|
106
|
+
* monitor.updateFPS(timestamp);
|
|
107
|
+
*
|
|
108
|
+
* // After frame work
|
|
109
|
+
* monitor.recordFrameTiming(coreTime, renderTime);
|
|
110
|
+
*
|
|
111
|
+
* // Get metrics
|
|
112
|
+
* const stats = monitor.getStats();
|
|
113
|
+
* console.log(`FPS: ${stats.fps}, Avg Frame Time: ${stats.avgTotalTime}ms`);
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
/**
|
|
117
|
+
* Frame timing data for a single frame
|
|
118
|
+
*/
|
|
119
|
+
interface FrameTiming {
|
|
120
|
+
/** Time spent in core logic (ms) */
|
|
121
|
+
coreTime: number;
|
|
122
|
+
/** Time spent in rendering (ms) */
|
|
123
|
+
renderTime: number;
|
|
124
|
+
/** Total frame time (ms) */
|
|
125
|
+
totalTime: number;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Performance statistics summary
|
|
129
|
+
*/
|
|
130
|
+
interface PerformanceStats {
|
|
131
|
+
/** Current frames per second */
|
|
132
|
+
fps: number;
|
|
133
|
+
/** Last recorded frame timing */
|
|
134
|
+
lastFrame?: FrameTiming;
|
|
135
|
+
/** Average frame timing over sample window */
|
|
136
|
+
avgFrame?: FrameTiming;
|
|
137
|
+
/** Number of samples in rolling average */
|
|
138
|
+
sampleCount: number;
|
|
139
|
+
/** Maximum sample size */
|
|
140
|
+
maxSamples: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Monitors and tracks runtime performance metrics
|
|
144
|
+
*
|
|
145
|
+
* Provides FPS tracking, frame timing measurements, and rolling averages
|
|
146
|
+
* for performance analysis and optimization.
|
|
147
|
+
*/
|
|
148
|
+
declare class PerformanceMonitor {
|
|
149
|
+
private frameCount;
|
|
150
|
+
private fps;
|
|
151
|
+
private fpsUpdateTime;
|
|
152
|
+
private lastCoreTime;
|
|
153
|
+
private lastRenderTime;
|
|
154
|
+
private lastTotalTime;
|
|
155
|
+
private coreTimeSamples;
|
|
156
|
+
private renderTimeSamples;
|
|
157
|
+
private totalTimeSamples;
|
|
158
|
+
private readonly maxSamples;
|
|
159
|
+
/**
|
|
160
|
+
* Creates a new PerformanceMonitor
|
|
161
|
+
*
|
|
162
|
+
* @param maxSamples - Maximum number of samples to keep for rolling averages (default: 60)
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* const monitor = new PerformanceMonitor(60); // Track last 60 frames
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
constructor(maxSamples?: number);
|
|
170
|
+
/**
|
|
171
|
+
* Start FPS tracking
|
|
172
|
+
*
|
|
173
|
+
* Call this once when starting performance monitoring.
|
|
174
|
+
* Initializes the FPS calculation baseline.
|
|
175
|
+
*
|
|
176
|
+
* @param timestamp - Initial timestamp from performance.now()
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* monitor.startTracking(performance.now());
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
startTracking(timestamp: number): void;
|
|
184
|
+
/**
|
|
185
|
+
* Update frame counter and calculate FPS
|
|
186
|
+
*
|
|
187
|
+
* Call this every frame in your main loop. Automatically calculates
|
|
188
|
+
* FPS every second based on frame count.
|
|
189
|
+
*
|
|
190
|
+
* @param timestamp - Current timestamp from performance.now()
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* function mainLoop(timestamp: number) {
|
|
195
|
+
* monitor.updateFPS(timestamp);
|
|
196
|
+
* // ... rest of frame logic
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
updateFPS(timestamp: number): void;
|
|
201
|
+
/**
|
|
202
|
+
* Record frame timing for the current frame
|
|
203
|
+
*
|
|
204
|
+
* Call this after each frame completes to record timing data.
|
|
205
|
+
* Maintains a rolling window of samples for average calculation.
|
|
206
|
+
*
|
|
207
|
+
* @param coreTime - Time spent in core logic (ms)
|
|
208
|
+
* @param renderTime - Time spent in rendering (ms)
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```typescript
|
|
212
|
+
* const coreStart = performance.now();
|
|
213
|
+
* // ... core logic
|
|
214
|
+
* const coreTime = performance.now() - coreStart;
|
|
215
|
+
*
|
|
216
|
+
* const renderStart = performance.now();
|
|
217
|
+
* // ... rendering
|
|
218
|
+
* const renderTime = performance.now() - renderStart;
|
|
219
|
+
*
|
|
220
|
+
* monitor.recordFrameTiming(coreTime, renderTime);
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
recordFrameTiming(coreTime: number, renderTime: number): void;
|
|
224
|
+
/**
|
|
225
|
+
* Get current FPS
|
|
226
|
+
*
|
|
227
|
+
* @returns Current frames per second
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* console.log(`FPS: ${monitor.getFPS()}`);
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
getFPS(): number;
|
|
235
|
+
/**
|
|
236
|
+
* Get last recorded frame timing
|
|
237
|
+
*
|
|
238
|
+
* Returns undefined if no frames have been recorded yet.
|
|
239
|
+
*
|
|
240
|
+
* @returns Last frame timing or undefined
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* const last = monitor.getLastFrameTiming();
|
|
245
|
+
* if (last) {
|
|
246
|
+
* console.log(`Last frame: ${last.totalTime.toFixed(2)}ms`);
|
|
247
|
+
* }
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
getLastFrameTiming(): FrameTiming | undefined;
|
|
251
|
+
/**
|
|
252
|
+
* Get average frame timing over sample window
|
|
253
|
+
*
|
|
254
|
+
* Returns undefined if no samples have been recorded yet.
|
|
255
|
+
*
|
|
256
|
+
* @returns Average frame timing or undefined
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* const avg = monitor.getAverageFrameTiming();
|
|
261
|
+
* if (avg) {
|
|
262
|
+
* console.log(`Avg frame: ${avg.totalTime.toFixed(2)}ms`);
|
|
263
|
+
* console.log(`Avg core: ${avg.coreTime.toFixed(2)}ms`);
|
|
264
|
+
* console.log(`Avg render: ${avg.renderTime.toFixed(2)}ms`);
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
getAverageFrameTiming(): FrameTiming | undefined;
|
|
269
|
+
/**
|
|
270
|
+
* Get comprehensive performance statistics
|
|
271
|
+
*
|
|
272
|
+
* Returns all available performance metrics including FPS,
|
|
273
|
+
* last frame timing, average timing, and sample counts.
|
|
274
|
+
*
|
|
275
|
+
* @returns Performance statistics
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```typescript
|
|
279
|
+
* const stats = monitor.getStats();
|
|
280
|
+
* console.log(`FPS: ${stats.fps}`);
|
|
281
|
+
* console.log(`Samples: ${stats.sampleCount}/${stats.maxSamples}`);
|
|
282
|
+
* if (stats.avgFrame) {
|
|
283
|
+
* console.log(`Avg Frame Time: ${stats.avgFrame.totalTime.toFixed(2)}ms`);
|
|
284
|
+
* }
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
getStats(): PerformanceStats;
|
|
288
|
+
/**
|
|
289
|
+
* Reset all performance data
|
|
290
|
+
*
|
|
291
|
+
* Clears all tracked metrics and samples. Useful for restarting
|
|
292
|
+
* performance monitoring without creating a new instance.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```typescript
|
|
296
|
+
* monitor.reset();
|
|
297
|
+
* monitor.startTracking(performance.now());
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
reset(): void;
|
|
301
|
+
/**
|
|
302
|
+
* Calculate average of an array of numbers
|
|
303
|
+
*
|
|
304
|
+
* @param arr - Array of numbers
|
|
305
|
+
* @returns Average value
|
|
306
|
+
* @private
|
|
307
|
+
*/
|
|
308
|
+
private average;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Renderer Manager
|
|
313
|
+
*
|
|
314
|
+
* Manages renderer lifecycle including initialization, font loading,
|
|
315
|
+
* readiness checks, and rendering operations.
|
|
316
|
+
*
|
|
317
|
+
* This class is responsible for:
|
|
318
|
+
* - Renderer readiness waiting (async initialization)
|
|
319
|
+
* - Default font loading and registration
|
|
320
|
+
* - Rendering operation delegation
|
|
321
|
+
* - Renderer cleanup and destruction
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* const manager = new RendererManager(renderer, {
|
|
326
|
+
* debug: true,
|
|
327
|
+
* useImageDataRendering: false
|
|
328
|
+
* });
|
|
329
|
+
*
|
|
330
|
+
* // Initialize
|
|
331
|
+
* await manager.initialize(core);
|
|
332
|
+
*
|
|
333
|
+
* // Render
|
|
334
|
+
* manager.render(userId);
|
|
335
|
+
*
|
|
336
|
+
* // Cleanup
|
|
337
|
+
* manager.destroy();
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Configuration options for RendererManager
|
|
343
|
+
*/
|
|
344
|
+
interface RendererManagerOptions {
|
|
345
|
+
/** Enable debug logging */
|
|
346
|
+
debug?: boolean;
|
|
347
|
+
/** Enable ImageData rendering optimization (Terminal2D only) */
|
|
348
|
+
useImageDataRendering?: boolean;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Browser-specific renderer interface
|
|
352
|
+
* Refines IRenderer's getCanvas() return type from unknown to HTMLCanvasElement
|
|
353
|
+
* and adds optional Terminal2D-specific methods
|
|
354
|
+
*/
|
|
355
|
+
type ConcreteRenderer = IRenderer & {
|
|
356
|
+
/**
|
|
357
|
+
* Get canvas element (browser-specific)
|
|
358
|
+
* Refines the return type from unknown to HTMLCanvasElement | null
|
|
359
|
+
*/
|
|
360
|
+
getCanvas(): HTMLCanvasElement | null;
|
|
361
|
+
/**
|
|
362
|
+
* Enable ImageData rendering optimization (Terminal2D specific, optional)
|
|
363
|
+
*/
|
|
364
|
+
setImageDataRendering?: (enabled: boolean) => void;
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* Manages renderer lifecycle and operations
|
|
368
|
+
*
|
|
369
|
+
* Provides abstraction layer for renderer initialization, font loading,
|
|
370
|
+
* and rendering operations. Handles differences between renderer types
|
|
371
|
+
* (e.g., async WebGL initialization vs instant Canvas2D).
|
|
372
|
+
*/
|
|
373
|
+
declare class RendererManager {
|
|
374
|
+
private renderer;
|
|
375
|
+
private options;
|
|
376
|
+
/**
|
|
377
|
+
* Creates a new RendererManager
|
|
378
|
+
*
|
|
379
|
+
* @param renderer - Renderer instance to manage
|
|
380
|
+
* @param options - Configuration options
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* ```typescript
|
|
384
|
+
* const renderer = new TerminalGL(container, width, height);
|
|
385
|
+
* const manager = new RendererManager(renderer, { debug: true });
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
constructor(renderer: ConcreteRenderer, options?: RendererManagerOptions);
|
|
389
|
+
/**
|
|
390
|
+
* Initialize renderer (wait for ready + load default font)
|
|
391
|
+
*
|
|
392
|
+
* Call this before using the renderer. Handles async initialization
|
|
393
|
+
* for WebGL renderers and loads the default ASCII 8x8 font atlas.
|
|
394
|
+
*
|
|
395
|
+
* @param core - Core instance for font registry access
|
|
396
|
+
* @throws Error if renderer fails to be ready after timeout
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```typescript
|
|
400
|
+
* await manager.initialize(core);
|
|
401
|
+
* // Renderer is now ready and font is loaded
|
|
402
|
+
* ```
|
|
403
|
+
*/
|
|
404
|
+
initialize(_core: Core): Promise<void>;
|
|
405
|
+
/**
|
|
406
|
+
* Wait for renderer to be ready
|
|
407
|
+
*
|
|
408
|
+
* Some renderers (WebGL) require async initialization. This method
|
|
409
|
+
* polls isReady() until the renderer is ready or timeout occurs.
|
|
410
|
+
*
|
|
411
|
+
* @param maxAttempts - Maximum polling attempts (default: 100)
|
|
412
|
+
* @param intervalMs - Polling interval in milliseconds (default: 50ms)
|
|
413
|
+
* @throws Error if renderer fails to be ready after maxAttempts
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```typescript
|
|
417
|
+
* await manager.waitForReady();
|
|
418
|
+
* console.log('Renderer is ready!');
|
|
419
|
+
* ```
|
|
420
|
+
*/
|
|
421
|
+
waitForReady(maxAttempts?: number, intervalMs?: number): Promise<void>;
|
|
422
|
+
/**
|
|
423
|
+
* @deprecated Default 8x8 font is no longer used. Use ImageFont instead.
|
|
424
|
+
* This method is kept for backwards compatibility but does nothing.
|
|
425
|
+
*/
|
|
426
|
+
loadDefaultFont(_core: Core): Promise<void>;
|
|
427
|
+
/**
|
|
428
|
+
* Render display data for a specific user
|
|
429
|
+
*
|
|
430
|
+
* Retrieves render state from core and renders the first display.
|
|
431
|
+
* Checks renderer readiness before rendering.
|
|
432
|
+
*
|
|
433
|
+
* @param core - Core instance for render state access
|
|
434
|
+
* @param userId - User ID to render for
|
|
435
|
+
* @returns true if rendering succeeded, false otherwise
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```typescript
|
|
439
|
+
* const rendered = manager.render(core, userId);
|
|
440
|
+
* if (!rendered) {
|
|
441
|
+
* console.warn('Rendering failed or skipped');
|
|
442
|
+
* }
|
|
443
|
+
* ```
|
|
444
|
+
*/
|
|
445
|
+
render(core: Core, userId: string): boolean;
|
|
446
|
+
/**
|
|
447
|
+
* Get the underlying renderer instance
|
|
448
|
+
*
|
|
449
|
+
* @returns Renderer instance
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```typescript
|
|
453
|
+
* const renderer = manager.getRenderer();
|
|
454
|
+
* const canvas = renderer.getCanvas();
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
getRenderer(): ConcreteRenderer;
|
|
458
|
+
/**
|
|
459
|
+
* Get renderer canvas element
|
|
460
|
+
*
|
|
461
|
+
* Convenience method to access the renderer's canvas.
|
|
462
|
+
*
|
|
463
|
+
* @returns Canvas element or null if not available
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```typescript
|
|
467
|
+
* const canvas = manager.getCanvas();
|
|
468
|
+
* if (canvas) {
|
|
469
|
+
* canvas.addEventListener('click', handleClick);
|
|
470
|
+
* }
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
473
|
+
getCanvas(): HTMLCanvasElement | null;
|
|
474
|
+
/**
|
|
475
|
+
* Check if renderer is ready
|
|
476
|
+
*
|
|
477
|
+
* @returns true if renderer is ready to render
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```typescript
|
|
481
|
+
* if (manager.isReady()) {
|
|
482
|
+
* manager.render(core, userId);
|
|
483
|
+
* }
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
isReady(): boolean;
|
|
487
|
+
/**
|
|
488
|
+
* Destroy renderer and cleanup resources
|
|
489
|
+
*
|
|
490
|
+
* Delegates to the underlying renderer's destroy method.
|
|
491
|
+
* Should be called when the renderer is no longer needed.
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```typescript
|
|
495
|
+
* manager.destroy();
|
|
496
|
+
* console.log('Renderer destroyed');
|
|
497
|
+
* ```
|
|
498
|
+
*/
|
|
499
|
+
destroy(): void;
|
|
500
|
+
/**
|
|
501
|
+
* Log debug message if debug mode is enabled
|
|
502
|
+
*
|
|
503
|
+
* @param message - Message to log
|
|
504
|
+
* @private
|
|
505
|
+
*/
|
|
506
|
+
private log;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Base Client Runtime
|
|
511
|
+
*
|
|
512
|
+
* Abstract base class for all client runtime variants.
|
|
513
|
+
* Provides core functionality: rendering, core management, and lifecycle.
|
|
514
|
+
*
|
|
515
|
+
* Features NOT included (handled by subclasses):
|
|
516
|
+
* - Input handling
|
|
517
|
+
* - Audio
|
|
518
|
+
* - Network
|
|
519
|
+
* - Post-processing effects
|
|
520
|
+
* - Autoplay overlay
|
|
521
|
+
*/
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Abstract base class for all client runtimes
|
|
525
|
+
*/
|
|
526
|
+
declare abstract class BaseClientRuntime {
|
|
527
|
+
/** Core instance managing application state */
|
|
528
|
+
protected core: Core;
|
|
529
|
+
/** Renderer manager wrapping the actual renderer */
|
|
530
|
+
protected rendererManager: RendererManager;
|
|
531
|
+
/** Current renderer type */
|
|
532
|
+
protected rendererType: RendererType;
|
|
533
|
+
/** Normalized options with defaults applied */
|
|
534
|
+
protected options: Required<BaseRuntimeOptions>;
|
|
535
|
+
/** Is the runtime currently running */
|
|
536
|
+
protected running: boolean;
|
|
537
|
+
/** Timestamp when runtime started */
|
|
538
|
+
protected startTime: number;
|
|
539
|
+
/** Last frame timestamp */
|
|
540
|
+
protected lastTimestamp: number;
|
|
541
|
+
/** Current user ID */
|
|
542
|
+
protected userId: string;
|
|
543
|
+
/** Visibility change handler for tab switching */
|
|
544
|
+
protected visibilityChangeHandler?: () => void;
|
|
545
|
+
/** Tick rate in TPS (0 = no updates) */
|
|
546
|
+
protected tickRate: number;
|
|
547
|
+
/** Accumulated time for fixed timestep */
|
|
548
|
+
protected accumulatedTime: number;
|
|
549
|
+
/** Minimum frame time (1000/maxFPS) */
|
|
550
|
+
protected readonly FRAME_TIME_MIN: number;
|
|
551
|
+
/** Last render timestamp for frame limiting */
|
|
552
|
+
protected lastRenderTimestamp: number;
|
|
553
|
+
/** requestAnimationFrame ID */
|
|
554
|
+
protected rafId: number;
|
|
555
|
+
/** Flag to prevent catch-up ticks on first frame */
|
|
556
|
+
protected firstTickDone: boolean;
|
|
557
|
+
/** Performance monitoring */
|
|
558
|
+
protected performanceMonitor: PerformanceMonitor;
|
|
559
|
+
/** Render mode: continuous or on-demand */
|
|
560
|
+
protected renderMode: 'continuous' | 'on-demand';
|
|
561
|
+
/** Flag for on-demand render requests */
|
|
562
|
+
protected renderRequested: boolean;
|
|
563
|
+
constructor(options: BaseRuntimeOptions);
|
|
564
|
+
/**
|
|
565
|
+
* Create the appropriate renderer based on options
|
|
566
|
+
*/
|
|
567
|
+
protected createRenderer(): ConcreteRenderer;
|
|
568
|
+
/**
|
|
569
|
+
* Get the renderer type
|
|
570
|
+
*/
|
|
571
|
+
getRendererType(): RendererType;
|
|
572
|
+
/**
|
|
573
|
+
* Check if runtime is running
|
|
574
|
+
*/
|
|
575
|
+
isRunning(): boolean;
|
|
576
|
+
/**
|
|
577
|
+
* Set the tick rate (TPS)
|
|
578
|
+
*/
|
|
579
|
+
setTickRate(tickRate: number): void;
|
|
580
|
+
/**
|
|
581
|
+
* Set render mode
|
|
582
|
+
*/
|
|
583
|
+
setRenderMode(mode: 'continuous' | 'on-demand'): void;
|
|
584
|
+
/**
|
|
585
|
+
* Set maximum FPS
|
|
586
|
+
*/
|
|
587
|
+
setMaxFPS(fps: number): void;
|
|
588
|
+
/**
|
|
589
|
+
* Get current tick rate
|
|
590
|
+
*/
|
|
591
|
+
getTickRate(): number;
|
|
592
|
+
/**
|
|
593
|
+
* Request a render in on-demand mode
|
|
594
|
+
*/
|
|
595
|
+
requestRender(): void;
|
|
596
|
+
/**
|
|
597
|
+
* Start the runtime
|
|
598
|
+
*/
|
|
599
|
+
start(): Promise<void>;
|
|
600
|
+
/**
|
|
601
|
+
* Hook called before start() initializes renderer
|
|
602
|
+
* Override in subclasses to handle autoplay, audio initialization, etc.
|
|
603
|
+
*/
|
|
604
|
+
protected onBeforeStart(): Promise<void>;
|
|
605
|
+
/**
|
|
606
|
+
* Hook called after application.init() but before createLocalUser()
|
|
607
|
+
* Override in subclasses to configure input targets, etc.
|
|
608
|
+
*/
|
|
609
|
+
protected onAfterInit(): Promise<void>;
|
|
610
|
+
/**
|
|
611
|
+
* Stop the runtime
|
|
612
|
+
*/
|
|
613
|
+
stop(): Promise<void>;
|
|
614
|
+
/**
|
|
615
|
+
* Hook called during stop() for subclass cleanup
|
|
616
|
+
*/
|
|
617
|
+
protected onStop(): Promise<void>;
|
|
618
|
+
/**
|
|
619
|
+
* Get runtime statistics
|
|
620
|
+
*/
|
|
621
|
+
getStats(): BaseRuntimeStats;
|
|
622
|
+
/**
|
|
623
|
+
* Destroy the runtime and clean up all resources
|
|
624
|
+
*/
|
|
625
|
+
destroy(): Promise<void>;
|
|
626
|
+
/**
|
|
627
|
+
* Hook called during destroy() for subclass cleanup
|
|
628
|
+
*/
|
|
629
|
+
protected onDestroy(): Promise<void>;
|
|
630
|
+
/**
|
|
631
|
+
* Create a local user
|
|
632
|
+
*/
|
|
633
|
+
protected createLocalUser(): Promise<void>;
|
|
634
|
+
/**
|
|
635
|
+
* Hook called when user is created, before initUser()
|
|
636
|
+
* Override to inject audio processor, vibration, etc.
|
|
637
|
+
*/
|
|
638
|
+
protected onUserCreated(_user: User): void;
|
|
639
|
+
/**
|
|
640
|
+
* Process initial orders after initUser()
|
|
641
|
+
* Override to handle macro orders, post-process, etc.
|
|
642
|
+
*/
|
|
643
|
+
protected processInitialOrders(user: User): void;
|
|
644
|
+
/**
|
|
645
|
+
* Main game loop
|
|
646
|
+
*/
|
|
647
|
+
protected mainLoop(timestamp: number): void;
|
|
648
|
+
/**
|
|
649
|
+
* Collect and apply input from devices
|
|
650
|
+
* Override in subclasses with input support
|
|
651
|
+
*/
|
|
652
|
+
protected collectAndApplyInput(_user: User): void;
|
|
653
|
+
/**
|
|
654
|
+
* Process orders generated during tick (sounds, vibration, etc.)
|
|
655
|
+
* Override in subclasses with audio/postprocess support
|
|
656
|
+
*/
|
|
657
|
+
protected processTickOrders(user: User): void;
|
|
658
|
+
/**
|
|
659
|
+
* Render the current state
|
|
660
|
+
*/
|
|
661
|
+
protected render(): void;
|
|
662
|
+
/**
|
|
663
|
+
* Handle palette change from Core
|
|
664
|
+
*/
|
|
665
|
+
protected onCorePaletteChanged(palette: Map<number, {
|
|
666
|
+
r: number;
|
|
667
|
+
g: number;
|
|
668
|
+
b: number;
|
|
669
|
+
a: number;
|
|
670
|
+
e: number;
|
|
671
|
+
}>): void;
|
|
672
|
+
/**
|
|
673
|
+
* Handle bitmap font change from Core
|
|
674
|
+
*/
|
|
675
|
+
protected onCoreBitmapFontChanged(fontId: number): void;
|
|
676
|
+
/**
|
|
677
|
+
* Handle image font change from Core
|
|
678
|
+
*/
|
|
679
|
+
protected onCoreImageFontChanged(fontId: number): void;
|
|
680
|
+
/**
|
|
681
|
+
* Hook called after font change for post-process sync
|
|
682
|
+
* Override in subclasses with post-process support
|
|
683
|
+
*/
|
|
684
|
+
protected onFontChanged(_renderer: ConcreteRenderer): void;
|
|
685
|
+
/**
|
|
686
|
+
* Debug logging
|
|
687
|
+
*/
|
|
688
|
+
protected log(message: string): void;
|
|
689
|
+
/**
|
|
690
|
+
* Get the Core instance
|
|
691
|
+
*/
|
|
692
|
+
getCore(): Core;
|
|
693
|
+
/**
|
|
694
|
+
* Get the renderer manager
|
|
695
|
+
*/
|
|
696
|
+
getRendererManager(): RendererManager;
|
|
697
|
+
/**
|
|
698
|
+
* Get current user ID
|
|
699
|
+
*/
|
|
700
|
+
getUserId(): string;
|
|
701
|
+
}
|
|
7
702
|
|
|
8
703
|
/**
|
|
9
704
|
* Runtime Client Types and Options
|
|
@@ -13,23 +708,6 @@ export { IApplication } from '@utsp/types';
|
|
|
13
708
|
* Client runtime mode
|
|
14
709
|
*/
|
|
15
710
|
type ClientRuntimeMode = 'local' | 'connected';
|
|
16
|
-
/**
|
|
17
|
-
* Renderer type to use
|
|
18
|
-
*/
|
|
19
|
-
declare enum RendererType {
|
|
20
|
-
/** WebGL2 renderer - Optimized WebGL 1.0 with GPU palette, instanced rendering (default, recommended) */
|
|
21
|
-
TerminalGL = "webgl",
|
|
22
|
-
/** Canvas 2D renderer - CPU fallback with ImageData optimization for benchmarks */
|
|
23
|
-
Terminal2D = "terminal2d"
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Render mode for ClientRuntime
|
|
27
|
-
*/
|
|
28
|
-
type RenderMode =
|
|
29
|
-
/** Continuous rendering at max FPS (default) - requestAnimationFrame loop */
|
|
30
|
-
'continuous'
|
|
31
|
-
/** On-demand rendering - only renders when explicitly requested via requestRender() */
|
|
32
|
-
| 'on-demand';
|
|
33
711
|
/**
|
|
34
712
|
* Base client runtime options
|
|
35
713
|
*/
|
|
@@ -57,23 +735,8 @@ interface BaseClientRuntimeOptions {
|
|
|
57
735
|
};
|
|
58
736
|
/** Enable ImageData rendering for Canvas 2D (default: true). Provides pixel-perfect rendering with no gaps between cells. 10-20× faster than fillRect. Only for Terminal2D renderer with bitmap fonts. */
|
|
59
737
|
useImageDataRendering?: boolean;
|
|
60
|
-
/** Render mode: 'continuous' (default) renders at max FPS, 'on-demand' only renders when explicitly requested.
|
|
738
|
+
/** Render mode: 'continuous' (default) renders at max FPS, 'on-demand' only renders when explicitly requested. */
|
|
61
739
|
renderMode?: RenderMode;
|
|
62
|
-
/** Tick rate in ticks per second (default: 30). Set to 0 to disable update loop (only init/initUser, no update/updateUser). When set to 0, automatically enables 'on-demand' render mode. */
|
|
63
|
-
tickRate?: number;
|
|
64
|
-
/**
|
|
65
|
-
* Scaling mode for pixel-perfect rendering (default: ScalingMode.None)
|
|
66
|
-
*
|
|
67
|
-
* Controls how the canvas is scaled to fit the container:
|
|
68
|
-
* - ScalingMode.None: Fills available space, may have sub-pixel artifacts (default)
|
|
69
|
-
* - ScalingMode.Eighth: Snaps to 0.125 increments (1.0, 1.125, 1.25...)
|
|
70
|
-
* - ScalingMode.Quarter: Snaps to 0.25 increments (1.0, 1.25, 1.5...)
|
|
71
|
-
* - ScalingMode.Half: Snaps to 0.5 increments (1.0, 1.5, 2.0...)
|
|
72
|
-
* - ScalingMode.Integer: Integer scaling only (1x, 2x, 3x...), crispest pixels
|
|
73
|
-
*
|
|
74
|
-
* Use ScalingMode.Integer for pixel-art style games that need crisp, artifact-free rendering.
|
|
75
|
-
*/
|
|
76
|
-
scalingMode?: ScalingMode;
|
|
77
740
|
/** Capture input events to prevent default browser behavior (Tab, arrows, etc.). Default: false. When true, preventDefault() and stopPropagation() are called on keyboard and mouse events to keep focus in the terminal. All F keys (F1-F12) and Ctrl/Cmd shortcuts are automatically excluded. */
|
|
78
741
|
captureInput?: boolean;
|
|
79
742
|
/** Enable input handling (keyboard, mouse, touch, gamepad). Default: true. When false, no input listeners are created - useful for display-only clients in documentation pages where you want to scroll freely without the client intercepting events. */
|
|
@@ -140,17 +803,6 @@ interface ConnectedModeOptions extends BaseClientRuntimeOptions {
|
|
|
140
803
|
* Union type of client runtime options
|
|
141
804
|
*/
|
|
142
805
|
type ClientRuntimeOptions = LocalModeOptions | ConnectedModeOptions;
|
|
143
|
-
/**
|
|
144
|
-
* Performance timing for a single frame
|
|
145
|
-
*/
|
|
146
|
-
interface FrameTiming {
|
|
147
|
-
/** Time spent in Core tick (ms) */
|
|
148
|
-
coreTime: number;
|
|
149
|
-
/** Time spent in Renderer (ms) */
|
|
150
|
-
renderTime: number;
|
|
151
|
-
/** Total frame time (ms) */
|
|
152
|
-
totalTime: number;
|
|
153
|
-
}
|
|
154
806
|
/**
|
|
155
807
|
* Client runtime statistics
|
|
156
808
|
*/
|
|
@@ -170,39 +822,29 @@ interface ClientRuntimeStats {
|
|
|
170
822
|
/** Network latency in ms (connected mode only) */
|
|
171
823
|
latency?: number;
|
|
172
824
|
/** Last frame timing breakdown */
|
|
173
|
-
lastFrameTiming?: FrameTiming;
|
|
825
|
+
lastFrameTiming?: FrameTiming$1;
|
|
174
826
|
/** Average frame timing over last 60 frames */
|
|
175
|
-
avgFrameTiming?: FrameTiming;
|
|
827
|
+
avgFrameTiming?: FrameTiming$1;
|
|
176
828
|
}
|
|
177
829
|
|
|
178
830
|
/**
|
|
179
|
-
* Client Runtime
|
|
831
|
+
* Client Runtime (Standard)
|
|
180
832
|
*
|
|
181
|
-
*
|
|
833
|
+
* Full-featured client runtime supporting both local and connected modes.
|
|
834
|
+
* Extends BaseClientRuntime with:
|
|
835
|
+
* - Input handling (keyboard, mouse, touch, gamepad)
|
|
836
|
+
* - Audio support
|
|
837
|
+
* - Network synchronization
|
|
838
|
+
* - Post-processing effects
|
|
839
|
+
* - Autoplay overlay
|
|
840
|
+
* - Bridge messaging
|
|
182
841
|
*/
|
|
183
842
|
|
|
184
|
-
declare class ClientRuntime {
|
|
185
|
-
private core;
|
|
186
|
-
private rendererManager;
|
|
187
|
-
private rendererType;
|
|
843
|
+
declare class ClientRuntime extends BaseClientRuntime {
|
|
188
844
|
private input;
|
|
189
845
|
private networkSync;
|
|
190
|
-
private options;
|
|
191
|
-
private running;
|
|
192
|
-
private startTime;
|
|
193
|
-
private lastTimestamp;
|
|
194
|
-
private userId;
|
|
195
846
|
private mode;
|
|
196
|
-
private
|
|
197
|
-
private tickRate;
|
|
198
|
-
private accumulatedTime;
|
|
199
|
-
private readonly FRAME_TIME_MIN;
|
|
200
|
-
private lastRenderTimestamp;
|
|
201
|
-
private rafId;
|
|
202
|
-
private firstTickDone;
|
|
203
|
-
private performanceMonitor;
|
|
204
|
-
private renderMode;
|
|
205
|
-
private renderRequested;
|
|
847
|
+
private localOptions;
|
|
206
848
|
private autoplayOverlay;
|
|
207
849
|
private autoplay;
|
|
208
850
|
private audioManager;
|
|
@@ -213,221 +855,239 @@ declare class ClientRuntime {
|
|
|
213
855
|
private localBridgeWildcardHandlers;
|
|
214
856
|
constructor(options: ClientRuntimeOptions);
|
|
215
857
|
getMode(): ClientRuntimeMode;
|
|
216
|
-
getRendererType(): RendererType;
|
|
217
|
-
isRunning(): boolean;
|
|
218
|
-
private createRenderer;
|
|
219
858
|
setTickRate(tickRate: number): void;
|
|
220
|
-
setRenderMode(mode: 'continuous' | 'on-demand'): void;
|
|
221
|
-
setMaxFPS(fps: number): void;
|
|
222
|
-
getTickRate(): number;
|
|
223
859
|
/**
|
|
224
|
-
*
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
*
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
*
|
|
233
|
-
* tickRate: 0, // Disable update loop
|
|
234
|
-
* application: myApp,
|
|
235
|
-
* container: document.getElementById('app')
|
|
236
|
-
* });
|
|
237
|
-
*
|
|
238
|
-
* await runtime.start();
|
|
239
|
-
*
|
|
240
|
-
* // Manually request render after changing something
|
|
241
|
-
* core.getUser('local').setCell(0, 0, '@', 1, 0);
|
|
242
|
-
* runtime.requestRender(); // Trigger render
|
|
243
|
-
* ```
|
|
860
|
+
* Override onBeforeStart to handle autoplay and audio initialization
|
|
861
|
+
*/
|
|
862
|
+
protected onBeforeStart(): Promise<void>;
|
|
863
|
+
/**
|
|
864
|
+
* Override onAfterInit to configure input and post-process
|
|
865
|
+
*/
|
|
866
|
+
protected onAfterInit(): Promise<void>;
|
|
867
|
+
/**
|
|
868
|
+
* Override start() for connected mode
|
|
244
869
|
*/
|
|
245
|
-
requestRender(): void;
|
|
246
870
|
start(): Promise<void>;
|
|
247
|
-
|
|
871
|
+
/**
|
|
872
|
+
* Override onStop for cleanup
|
|
873
|
+
*/
|
|
874
|
+
protected onStop(): Promise<void>;
|
|
248
875
|
getStats(): ClientRuntimeStats;
|
|
249
|
-
|
|
250
|
-
|
|
876
|
+
/**
|
|
877
|
+
* Override onDestroy for full cleanup
|
|
878
|
+
*/
|
|
879
|
+
protected onDestroy(): Promise<void>;
|
|
880
|
+
/**
|
|
881
|
+
* Override createLocalUser for full feature support
|
|
882
|
+
*/
|
|
883
|
+
protected createLocalUser(): Promise<void>;
|
|
251
884
|
/**
|
|
252
885
|
* Load sounds from Core's SoundRegistry into AudioManager's SoundBank
|
|
253
|
-
* Used in standalone mode to transfer sounds registered via core.loadSound()
|
|
254
|
-
* @private
|
|
255
886
|
*/
|
|
256
887
|
private loadSoundsFromRegistry;
|
|
257
|
-
private mainLoop;
|
|
258
|
-
private collectAndApplyInput;
|
|
259
|
-
private collectAndSendInput;
|
|
260
|
-
private render;
|
|
261
888
|
/**
|
|
262
|
-
*
|
|
263
|
-
* Converts Core palette Map to RGBColor array and updates renderer
|
|
889
|
+
* Override mainLoop for connected mode support
|
|
264
890
|
*/
|
|
265
|
-
|
|
891
|
+
protected mainLoop(timestamp: number): void;
|
|
266
892
|
/**
|
|
267
|
-
*
|
|
268
|
-
* Loads the font from registry and updates renderer
|
|
893
|
+
* Override collectAndApplyInput for full input support
|
|
269
894
|
*/
|
|
270
|
-
|
|
895
|
+
protected collectAndApplyInput(user: User): void;
|
|
896
|
+
private collectAndSendInput;
|
|
271
897
|
/**
|
|
272
|
-
*
|
|
273
|
-
* Loads the PNG font atlas from registry and updates renderer
|
|
898
|
+
* Override onFontChanged to sync PostProcessOverlay
|
|
274
899
|
*/
|
|
275
|
-
|
|
900
|
+
protected onFontChanged(renderer: ConcreteRenderer): void;
|
|
276
901
|
/**
|
|
277
902
|
* Get the AudioManager instance
|
|
278
|
-
* Returns null before start() is called
|
|
279
903
|
*/
|
|
280
904
|
getAudioManager(): InstanceType<typeof AudioManager> | null;
|
|
281
905
|
/**
|
|
282
|
-
* Get the AudioContext instance
|
|
283
|
-
* Returns null if AudioManager not initialized
|
|
906
|
+
* Get the AudioContext instance
|
|
284
907
|
*/
|
|
285
908
|
getAudioContext(): AudioContext | null;
|
|
286
909
|
/**
|
|
287
|
-
*
|
|
910
|
+
* Get the PostProcessOverlay instance
|
|
911
|
+
*/
|
|
912
|
+
getPostProcessOverlay(): PostProcessOverlay | null;
|
|
913
|
+
/**
|
|
914
|
+
* Apply ambient effect configuration
|
|
288
915
|
*/
|
|
289
916
|
private applyAmbientEffectConfig;
|
|
290
917
|
/**
|
|
291
|
-
* Apply post-process orders
|
|
292
|
-
* These are binary orders decoded from UpdatePacket
|
|
918
|
+
* Apply post-process orders
|
|
293
919
|
*/
|
|
294
920
|
private applyPostProcessOrders;
|
|
921
|
+
private applyScalingMode;
|
|
922
|
+
private applyGridConfig;
|
|
923
|
+
private patternFromType;
|
|
924
|
+
private dispatchLocalBridgeMessages;
|
|
925
|
+
sendBridge(channel: string, data: unknown): void;
|
|
926
|
+
onBridge<T = unknown>(channel: string, handler: (data: T) => void): void;
|
|
927
|
+
offBridge<T = unknown>(channel: string, handler: (data: T) => void): void;
|
|
928
|
+
removeAllBridgeHandlers(channel?: string): void;
|
|
295
929
|
/**
|
|
296
|
-
*
|
|
930
|
+
* Override log for mode-specific prefix
|
|
297
931
|
*/
|
|
298
|
-
|
|
932
|
+
protected log(message: string): void;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
interface InputFeatureOptions {
|
|
936
|
+
debug?: boolean;
|
|
937
|
+
captureInput?: boolean;
|
|
938
|
+
mobileInputConfig?: {
|
|
939
|
+
preventDefault?: boolean;
|
|
940
|
+
passive?: boolean;
|
|
941
|
+
maxTouches?: number;
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
declare class InputFeature {
|
|
945
|
+
private input;
|
|
946
|
+
private mobileVibration;
|
|
947
|
+
constructor(options?: InputFeatureOptions);
|
|
299
948
|
/**
|
|
300
|
-
*
|
|
949
|
+
* Set mobile input target (usually the canvas)
|
|
301
950
|
*/
|
|
302
|
-
|
|
951
|
+
setMobileTarget(element: HTMLElement): void;
|
|
303
952
|
/**
|
|
304
|
-
*
|
|
953
|
+
* Start listening for input
|
|
305
954
|
*/
|
|
306
|
-
|
|
955
|
+
start(): void;
|
|
307
956
|
/**
|
|
308
|
-
*
|
|
309
|
-
* Returns null before start() is called
|
|
957
|
+
* Stop listening for input
|
|
310
958
|
*/
|
|
311
|
-
|
|
959
|
+
stop(): void;
|
|
312
960
|
/**
|
|
313
|
-
*
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
* with the server application. Use this for external UI communication
|
|
317
|
-
* (chat, settings, custom commands, etc.).
|
|
318
|
-
*
|
|
319
|
-
* **Note:** Only available in 'connected' mode. In 'local' mode, this is a no-op.
|
|
320
|
-
*
|
|
321
|
-
* @param channel - Channel name (e.g., 'chat', 'settings', 'ready')
|
|
322
|
-
* @param data - Any JSON-serializable data
|
|
323
|
-
*
|
|
324
|
-
* @example
|
|
325
|
-
* ```typescript
|
|
326
|
-
* // Send a chat message
|
|
327
|
-
* runtime.sendBridge('chat', { message: 'Hello everyone!' });
|
|
328
|
-
*
|
|
961
|
+
* Destroy and cleanup
|
|
962
|
+
*/
|
|
963
|
+
destroy(): void;
|
|
329
964
|
/**
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
* In local mode, this simulates the server→client path by calling
|
|
333
|
-
* registered handlers directly. Same timing as connected mode.
|
|
334
|
-
*
|
|
335
|
-
* @param messages - Array of bridge messages from user.getBridgeMessages()
|
|
336
|
-
* @private
|
|
965
|
+
* Get the input router (for network sync)
|
|
337
966
|
*/
|
|
338
|
-
|
|
967
|
+
getRouter(): UnifiedInputRouter;
|
|
339
968
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
* Bridge messages are sent immediately (not queued), bypassing the UTSP
|
|
343
|
-
* protocol for real-time external app communication.
|
|
344
|
-
*
|
|
345
|
-
* **Note:** In 'connected' mode, sends to server. In 'local' mode, routes
|
|
346
|
-
* directly to application.onBridgeMessage for isomorphic behavior.
|
|
347
|
-
*
|
|
348
|
-
* @param channel - Channel name (e.g., 'chat', 'ready', 'settings')
|
|
349
|
-
* @param data - Data to send (will be JSON serialized)
|
|
350
|
-
*
|
|
351
|
-
* @example
|
|
352
|
-
* ```typescript
|
|
353
|
-
* // Send a chat message
|
|
354
|
-
* runtime.sendBridge('chat', { message: 'Hello everyone!' });
|
|
355
|
-
*
|
|
356
|
-
* // Mark player as ready
|
|
357
|
-
* runtime.sendBridge('ready', { ready: true });
|
|
358
|
-
*
|
|
359
|
-
* // Send custom settings
|
|
360
|
-
* runtime.sendBridge('settings', { volume: 0.8, theme: 'dark' });
|
|
361
|
-
* ```
|
|
969
|
+
* Get gamepad for vibration processor injection
|
|
362
970
|
*/
|
|
363
|
-
|
|
971
|
+
getGamepad(): _utsp_input.GamepadInputs | null;
|
|
364
972
|
/**
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* Bridge messages from the application (via user.sendBridge) are synchronized
|
|
368
|
-
* with tick updates, arriving at the same time as render updates for consistency.
|
|
369
|
-
*
|
|
370
|
-
* **Isomorphic:** Works in both 'connected' and 'local' modes.
|
|
371
|
-
* - Connected: Messages come from server via network
|
|
372
|
-
* - Local: Messages are dispatched directly from application
|
|
373
|
-
*
|
|
374
|
-
* @param channel - Channel name to listen for (use '*' for all channels)
|
|
375
|
-
* @param handler - Callback function receiving the parsed data
|
|
376
|
-
*
|
|
377
|
-
* @example
|
|
378
|
-
* ```typescript
|
|
379
|
-
* // Listen for score updates
|
|
380
|
-
* runtime.onBridge('score', (data) => {
|
|
381
|
-
* updateScoreboard(data.value, data.combo);
|
|
382
|
-
* });
|
|
383
|
-
*
|
|
384
|
-
* // Listen for notifications
|
|
385
|
-
* runtime.onBridge('notification', (data) => {
|
|
386
|
-
* showToast(data.title, data.message);
|
|
387
|
-
* });
|
|
388
|
-
*
|
|
389
|
-
* // Wildcard handler for all channels
|
|
390
|
-
* runtime.onBridge('*', (channel, data) => {
|
|
391
|
-
* console.log(`Received ${channel}:`, data);
|
|
392
|
-
* });
|
|
393
|
-
* ```
|
|
973
|
+
* Get mobile vibration processor
|
|
394
974
|
*/
|
|
395
|
-
|
|
975
|
+
getMobileVibration(): MobileVibration;
|
|
396
976
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
* @param channel - Channel name
|
|
400
|
-
* @param handler - The exact handler function to remove
|
|
401
|
-
*
|
|
402
|
-
* @example
|
|
403
|
-
* ```typescript
|
|
404
|
-
* const handler = (data) => console.log(data);
|
|
405
|
-
* runtime.onBridge('score', handler);
|
|
406
|
-
*
|
|
407
|
-
* // Later, remove the handler
|
|
408
|
-
* runtime.offBridge('score', handler);
|
|
409
|
-
* ```
|
|
977
|
+
* Collect and apply input to user
|
|
410
978
|
*/
|
|
411
|
-
|
|
979
|
+
collectAndApply(user: User, canvas: HTMLCanvasElement | null, displayWidth: number, displayHeight: number, rendererOffsets: {
|
|
980
|
+
offsetX: number;
|
|
981
|
+
offsetY: number;
|
|
982
|
+
}): void;
|
|
412
983
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* Useful for cleanup in React useEffect or component unmount.
|
|
416
|
-
*
|
|
417
|
-
* @param channel - Optional channel name. If omitted, removes all handlers.
|
|
418
|
-
*
|
|
419
|
-
* @example
|
|
420
|
-
* ```typescript
|
|
421
|
-
* // Remove all handlers for 'score' channel
|
|
422
|
-
* runtime.removeAllBridgeHandlers('score');
|
|
423
|
-
*
|
|
424
|
-
* // Remove ALL bridge handlers
|
|
425
|
-
* runtime.removeAllBridgeHandlers();
|
|
426
|
-
* ```
|
|
984
|
+
* Process vibration commands from user
|
|
427
985
|
*/
|
|
428
|
-
|
|
986
|
+
processVibrationCommands(user: User): void;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* Audio Feature
|
|
991
|
+
*
|
|
992
|
+
* Handles sound playback and spatial audio.
|
|
993
|
+
* Can be omitted for silent clients (spectators, embeds without sound).
|
|
994
|
+
*/
|
|
995
|
+
|
|
996
|
+
interface AudioFeatureOptions {
|
|
997
|
+
debug?: boolean;
|
|
998
|
+
}
|
|
999
|
+
declare class AudioFeature {
|
|
1000
|
+
private audioManager;
|
|
1001
|
+
private debug;
|
|
1002
|
+
constructor(options?: AudioFeatureOptions);
|
|
1003
|
+
/**
|
|
1004
|
+
* Initialize audio context (should be called after user interaction)
|
|
1005
|
+
*/
|
|
1006
|
+
initialize(): void;
|
|
1007
|
+
/**
|
|
1008
|
+
* Play the start sound (used with autoplay overlay)
|
|
1009
|
+
*/
|
|
1010
|
+
playStartSound(): void;
|
|
1011
|
+
/**
|
|
1012
|
+
* Stop all sounds
|
|
1013
|
+
*/
|
|
1014
|
+
stopAll(): void;
|
|
1015
|
+
/**
|
|
1016
|
+
* Destroy and cleanup
|
|
1017
|
+
*/
|
|
1018
|
+
destroy(): void;
|
|
1019
|
+
/**
|
|
1020
|
+
* Get the AudioManager instance
|
|
1021
|
+
*/
|
|
1022
|
+
getManager(): AudioManager;
|
|
1023
|
+
/**
|
|
1024
|
+
* Get the AudioContext
|
|
1025
|
+
*/
|
|
1026
|
+
getContext(): AudioContext | null;
|
|
1027
|
+
/**
|
|
1028
|
+
* Inject audio processor into user
|
|
1029
|
+
*/
|
|
1030
|
+
injectIntoUser(user: User): void;
|
|
1031
|
+
/**
|
|
1032
|
+
* Process audio commands from user
|
|
1033
|
+
*/
|
|
1034
|
+
processAudioCommands(user: User): void;
|
|
1035
|
+
/**
|
|
1036
|
+
* Load sounds from Core's SoundRegistry into AudioManager's SoundBank
|
|
1037
|
+
*/
|
|
1038
|
+
loadSoundsFromRegistry(core: Core): Promise<void>;
|
|
1039
|
+
private log;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* PostProcess Feature
|
|
1044
|
+
*
|
|
1045
|
+
* Handles scanlines, ambient effects, grid overlay, and scaling modes.
|
|
1046
|
+
* Can be omitted for minimal clients without visual effects.
|
|
1047
|
+
*/
|
|
1048
|
+
|
|
1049
|
+
interface PostProcessFeatureOptions {
|
|
1050
|
+
debug?: boolean;
|
|
1051
|
+
}
|
|
1052
|
+
declare class PostProcessFeature {
|
|
1053
|
+
private overlay;
|
|
1054
|
+
private orderCollector;
|
|
1055
|
+
private debug;
|
|
1056
|
+
constructor(container: HTMLElement, options?: PostProcessFeatureOptions);
|
|
1057
|
+
/**
|
|
1058
|
+
* Destroy and cleanup
|
|
1059
|
+
*/
|
|
1060
|
+
destroy(): void;
|
|
1061
|
+
/**
|
|
1062
|
+
* Get the PostProcessOverlay instance
|
|
1063
|
+
*/
|
|
1064
|
+
getOverlay(): PostProcessOverlay;
|
|
1065
|
+
/**
|
|
1066
|
+
* Sync overlay with renderer dimensions after font change
|
|
1067
|
+
*/
|
|
1068
|
+
syncWithRenderer(renderer: {
|
|
1069
|
+
getCellWidth(): number;
|
|
1070
|
+
getCellHeight(): number;
|
|
1071
|
+
getCurrentScale(): number;
|
|
1072
|
+
getGridSize(): {
|
|
1073
|
+
cols: number;
|
|
1074
|
+
rows: number;
|
|
1075
|
+
};
|
|
1076
|
+
}): void;
|
|
1077
|
+
/**
|
|
1078
|
+
* Process post-process commands from user (converts to orders and applies)
|
|
1079
|
+
*/
|
|
1080
|
+
processCommands(user: User, renderer: any): void;
|
|
1081
|
+
/**
|
|
1082
|
+
* Apply post-process orders (used by both local and network modes)
|
|
1083
|
+
*/
|
|
1084
|
+
applyOrders(orders: AnyPostProcessOrder[], renderer: any): void;
|
|
1085
|
+
private applyAmbientEffect;
|
|
1086
|
+
private applyScalingMode;
|
|
1087
|
+
private applyGridConfig;
|
|
1088
|
+
private patternFromType;
|
|
429
1089
|
private log;
|
|
430
1090
|
}
|
|
431
1091
|
|
|
432
|
-
export { ClientRuntime, RendererType };
|
|
433
|
-
export type { BaseClientRuntimeOptions, ClientRuntimeMode, ClientRuntimeOptions, ClientRuntimeStats, ConnectedModeOptions, FrameTiming, LocalModeOptions, RenderMode };
|
|
1092
|
+
export { AudioFeature, BaseClientRuntime, ClientRuntime, InputFeature, PostProcessFeature, RendererType };
|
|
1093
|
+
export type { AudioFeatureOptions, BaseClientRuntimeOptions, BaseRuntimeOptions, BaseRuntimeStats, ClientRuntimeMode, ClientRuntimeOptions, ClientRuntimeStats, ConnectedModeOptions, FrameTiming$1 as FrameTiming, InputFeatureOptions, LocalModeOptions, PostProcessFeatureOptions, RenderMode };
|