@primitiv/core 0.19.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.
@@ -0,0 +1,2421 @@
1
+ import { Vector2, Order, PostProcessConfig, ScalingMode, RenderPassConfig, AmbientEffectConfig, GridConfig, ScanlinesConfig, AxisSource, ButtonSource, InputBindingLoadPacket, AxisBinding, ButtonBinding, TouchZoneBinding, MacroTemplate, MacroDefine, MacroOrder, MacroCreateOrder, MacroFeedback, BridgeMessage, CompressedInputPacket, AudioAck, SoundInstanceId, SoundFormat, SoundLoadType, SoundLoadPacket, SoundExternalLoadPacket, IResourceLoader, RenderPassState, CharOrder, TextOrder, TextMultilineOrder, SubFrameOrder, SubFrameMultiOrder, FullFrameOrder, FullFrameMultiOrder, SpriteOrder, SpriteMultiOrder, ColorMapCell, ShapeOrder, PolylineOrder, DotCloudOrder, DotCloudMultiOrder, SpriteCloudOrder, SpriteCloudMultiOrder, SpriteCloudVariedOrder, SpriteCloudVariedMultiOrder, BitmaskOrder, Bitmask4Order, Bitmask16Order, FillOrder, FillCharOrder, FillSpriteOrder, FillSpriteMultiOrder, AudioOrder, VibrationOrder } from '@primitiv/types';
2
+
3
+ /**
4
+ * Primitiv Core - Grid Primitive
5
+ */
6
+ /**
7
+ * Optimized 2D buffer using a single Uint32Array for performance.
8
+ *
9
+ * Storage Format (32-bit Packed Integer):
10
+ * - Bits 0-15 (16 bits): CharCode (0-65535)
11
+ * - Bits 16-23 (8 bits): Foreground Color (0-255)
12
+ * - Bits 24-31 (8 bits): Background Color (0-255)
13
+ *
14
+ * Example:
15
+ * [ BG (8) | FG (8) | CHAR (16) ]
16
+ *
17
+ * This allows:
18
+ * - Atomic reads/writes (1 ops vs 3)
19
+ * - Fast comparison (dirty checks)
20
+ * - Zero-allocation updates
21
+ */
22
+ declare class Grid {
23
+ readonly width: number;
24
+ readonly height: number;
25
+ readonly size: number;
26
+ readonly data: Uint32Array;
27
+ constructor(width: number, height: number);
28
+ /**
29
+ * Clear the grid with empty cells (BG: COLOR_SKIP, FG: COLOR_SKIP, Char: 0)
30
+ */
31
+ clear(): void;
32
+ /**
33
+ * Fill the entire grid with a specific char/color
34
+ */
35
+ fill(charCode: number, fg: number, bg: number): void;
36
+ /**
37
+ * Set a cell with bounds checking (Safe version for rasterization)
38
+ */
39
+ setSafe(x: number, y: number, charCode: number, fg: number, bg: number): void;
40
+ /**
41
+ * Set a single cell (Atomic)
42
+ * @param index Array index (y * width + x)
43
+ * @param charCode 16-bit char code
44
+ * @param fg 8-bit foreground color
45
+ * @param bg 8-bit background color
46
+ */
47
+ set(index: number, charCode: number, fg: number, bg: number): void;
48
+ /**
49
+ * Set a single cell using packed value
50
+ */
51
+ setPacked(index: number, value: number): void;
52
+ /**
53
+ * Get packed cell value
54
+ */
55
+ get(index: number): number;
56
+ /**
57
+ * Unpack a cell at index into components
58
+ * Useful for rendering or debugging
59
+ */
60
+ unpack(index: number): {
61
+ char: number;
62
+ fg: number;
63
+ bg: number;
64
+ };
65
+ /**
66
+ * Create a clone of this grid
67
+ */
68
+ clone(): Grid;
69
+ }
70
+
71
+ /**
72
+ * Static helpers for cell bitwise operations without object overhead.
73
+ */
74
+ declare class CellStruct {
75
+ /**
76
+ * Pack components into a 32-bit integer
77
+ */
78
+ static pack(char: number, fg: number, bg: number): number;
79
+ /**
80
+ * Extract CharCode (Bits 0-15)
81
+ */
82
+ static getChar(cell: number): number;
83
+ /**
84
+ * Extract Foreground Color (Bits 16-23)
85
+ */
86
+ static getFg(cell: number): number;
87
+ /**
88
+ * Extract Background Color (Bits 24-31)
89
+ */
90
+ static getBg(cell: number): number;
91
+ }
92
+
93
+ /**
94
+ * Structure of Sprite objects in Primitives
95
+ */
96
+ /**
97
+ * Unicolor sprite - Stores only charcodes.
98
+ * Colors (fg/bg) are defined at render time via SpriteOrder.
99
+ */
100
+ interface UnicolorSprite {
101
+ id: number;
102
+ width: number;
103
+ height: number;
104
+ data: Uint16Array;
105
+ }
106
+ /**
107
+ * Multicolor sprite - Stores charcodes + fg/bg colors.
108
+ * Each cell contains its own complete set of attributes.
109
+ * The data buffer format must match the Grid (packed 32-bit: BG|FG|Char).
110
+ */
111
+ interface MulticolorSprite {
112
+ id: number;
113
+ width: number;
114
+ height: number;
115
+ data: Uint32Array;
116
+ }
117
+ /**
118
+ * Definition for creating a Unicolor Sprite (friendly format)
119
+ */
120
+ interface UnicolorSpriteDefinition {
121
+ spriteId: number;
122
+ width: number;
123
+ height: number;
124
+ data: string | string[] | number[];
125
+ }
126
+ /**
127
+ * Definition for creating a Multicolor Sprite (friendly format)
128
+ * Not implementing fully yet as we need to define the Cell input format
129
+ */
130
+ interface MulticolorSpriteDefinition {
131
+ spriteId: number;
132
+ width: number;
133
+ height: number;
134
+ data: any[];
135
+ }
136
+
137
+ /**
138
+ * SpriteRegistry
139
+ * Central registry to manage unicolor and multicolor sprites.
140
+ * Adapted for Primitiv Core V6 (Uint32Array / Uint16Array based).
141
+ */
142
+ declare class SpriteRegistry {
143
+ private unicolorSprites;
144
+ private multicolorSprites;
145
+ /**
146
+ * Loads unicolor sprites from public definitions
147
+ * Supports strings, string arrays, and numbers
148
+ */
149
+ loadUnicolorSprites(definitions: UnicolorSpriteDefinition[]): void;
150
+ /**
151
+ * Loads multicolor sprites from public definitions
152
+ */
153
+ loadMulticolorSprites(definitions: MulticolorSpriteDefinition[]): void;
154
+ getUnicolorSprite(id: number): UnicolorSprite | undefined;
155
+ getMulticolorSprite(id: number): MulticolorSprite | undefined;
156
+ hasUnicolorSprite(id: number): boolean;
157
+ hasMulticolorSprite(id: number): boolean;
158
+ clearAll(): void;
159
+ }
160
+
161
+ type CharCodeMode = '8bit' | '16bit';
162
+ /**
163
+ * Layer configuration options.
164
+ */
165
+ interface LayerOptions {
166
+ /** Optional layer name for tooling/debug. */
167
+ name?: string;
168
+ /**
169
+ * CharCode mode for this layer (immutable after creation)
170
+ * - '8bit': 256 char codes (CP437 default)
171
+ * - '16bit': 65536 char codes (256 atlas blocks × 256 chars)
172
+ * @default '8bit'
173
+ */
174
+ charCodeMode?: CharCodeMode;
175
+ /**
176
+ * If true, the layer is sent on the reliable channel.
177
+ * @default false
178
+ */
179
+ mustBeReliable?: boolean;
180
+ /**
181
+ * If true, the layer is considered a macro layer (ephemeral, local effects).
182
+ * @default false
183
+ */
184
+ isMacroLayer?: boolean;
185
+ }
186
+ /**
187
+ * Layer State
188
+ * Represents a renderable surface in the world.
189
+ * Wraps a Grid with positioning and composition properties.
190
+ */
191
+ declare class Layer {
192
+ id: number;
193
+ grid: Grid;
194
+ x: number;
195
+ y: number;
196
+ private origin;
197
+ zIndex: number;
198
+ visible: boolean;
199
+ private name?;
200
+ private isMacroLayer;
201
+ private width;
202
+ private height;
203
+ private mustBeReliable;
204
+ private spriteRegistry?;
205
+ readonly charCodeMode: CharCodeMode;
206
+ /** Pre-computed flag: true when charCodeMode is '16bit' (avoids string comparison per tick) */
207
+ readonly is16bit: boolean;
208
+ private pendingOrders;
209
+ private ordersUpdatedThisTick;
210
+ private enabled;
211
+ private needsCommit;
212
+ private static rasterizer;
213
+ /**
214
+ * Creates a new layer.
215
+ *
216
+ * @param origin - Layer origin in world space.
217
+ * @param zOrder - Z-order for stacking (higher = on top).
218
+ * @param width - Layer width in cells (1-256).
219
+ * @param height - Layer height in cells (1-256).
220
+ * @param options - Layer options.
221
+ */
222
+ constructor(origin: Vector2, zOrder: number, width: number, height: number, options?: LayerOptions | boolean);
223
+ /**
224
+ * Explicitly set the layer ID.
225
+ * Needed because the constructor no longer takes an ID.
226
+ */
227
+ setId(id: number): void;
228
+ /**
229
+ * Injects the SpriteRegistry into the layer.
230
+ * Required for sprite-dependent orders (Sprite, SpriteCloud, FillSprite, etc.)
231
+ * @internal
232
+ */
233
+ setSpriteRegistry(registry: SpriteRegistry): void;
234
+ /**
235
+ * Resize the layer (clears content)
236
+ */
237
+ resize(width: number, height: number): void;
238
+ getMustBeReliable(): boolean;
239
+ getName(): string | undefined;
240
+ getIsMacroLayer(): boolean;
241
+ getWidth(): number;
242
+ getHeight(): number;
243
+ getOrigin(): Vector2;
244
+ /**
245
+ * Sets the layer origin in world space.
246
+ * Marks the layer as needing commit so the new position is transmitted.
247
+ */
248
+ setOrigin(origin: Vector2): void;
249
+ /**
250
+ * Sets the layer name (debug/metadata).
251
+ * Trims whitespace; empty string clears the name.
252
+ */
253
+ setName(name: string | undefined): void;
254
+ /**
255
+ * Enables or disables the layer.
256
+ * The enabled state is transmitted over the network so the client
257
+ * hides/shows the layer accordingly.
258
+ */
259
+ setEnabled(enabled: boolean): void;
260
+ /**
261
+ * Sets the z-index (stacking order).
262
+ * Marks the layer as needing commit so the new z-index is transmitted.
263
+ */
264
+ setZIndex(zIndex: number): void;
265
+ /**
266
+ * Marks this layer as reliable or volatile for network transport.
267
+ */
268
+ setMustBeReliable(reliable: boolean): void;
269
+ /**
270
+ * Returns the cell at the given coordinates (unpacked).
271
+ *
272
+ * @param x - X coordinate (0..width-1).
273
+ * @param y - Y coordinate (0..height-1).
274
+ * @returns The unpacked cell `{ char, fg, bg }` or `null` if out of bounds.
275
+ */
276
+ getCellAt(x: number, y: number): {
277
+ char: number;
278
+ fg: number;
279
+ bg: number;
280
+ } | null;
281
+ /**
282
+ * UTSP Parity: Set orders for this layer.
283
+ * Stores orders for serialization AND rasterizes into the grid.
284
+ */
285
+ setOrders(orders: Order[]): void;
286
+ /**
287
+ * Get pending orders (for serialization by TickPacketEncoder).
288
+ */
289
+ getPendingOrders(): Order[];
290
+ /**
291
+ * Clear pending orders after serialization.
292
+ * Called by Engine.endTick() after encoding.
293
+ */
294
+ clearPendingOrders(): void;
295
+ /**
296
+ * Returns true if setOrders() was called this tick (even with empty array).
297
+ * Used by TickPacketEncoder to determine FLAG_HAS_ORDERS.
298
+ */
299
+ getOrdersUpdatedThisTick(): boolean;
300
+ /**
301
+ * Marks the layer as needing to be sent to clients.
302
+ *
303
+ * **Note:** You typically do NOT need to call this method.
304
+ * All setters (`setOrders()`, `setOrigin()`, `setEnabled()`, `setZIndex()`)
305
+ * already mark the layer for commit automatically.
306
+ *
307
+ * This method is only useful for:
308
+ * - Force resync: sending a layer's current state even if unchanged this tick
309
+ * - Internal use after direct grid manipulation (not recommended)
310
+ */
311
+ commit(): void;
312
+ getNeedsCommit(): boolean;
313
+ /**
314
+ * Clear the commit flag after endTick processing.
315
+ */
316
+ clearCommit(): void;
317
+ isEnabled(): boolean;
318
+ /**
319
+ * Returns a debug-friendly snapshot of this layer (metadata only).
320
+ */
321
+ getDebugInfo(): {
322
+ id: number;
323
+ name?: string;
324
+ zIndex: number;
325
+ origin: {
326
+ x: number;
327
+ y: number;
328
+ };
329
+ width: number;
330
+ height: number;
331
+ visible: boolean;
332
+ enabled: boolean;
333
+ mustBeReliable: boolean;
334
+ isMacroLayer: boolean;
335
+ charCodeMode: CharCodeMode;
336
+ needsCommit: boolean;
337
+ ordersCount: number;
338
+ };
339
+ }
340
+
341
+ /**
342
+ * Display State
343
+ * Represents a Viewport (Camera) into the world.
344
+ * Does NOT contain logic, only state.
345
+ */
346
+ declare class Display {
347
+ readonly id: number;
348
+ x: number;
349
+ y: number;
350
+ width: number;
351
+ height: number;
352
+ cellWidth: number;
353
+ cellHeight: number;
354
+ pixelWidth: number;
355
+ pixelHeight: number;
356
+ postProcess: PostProcessConfig;
357
+ scalingMode: ScalingMode;
358
+ activePaletteSlot: number;
359
+ renderPasses: RenderPassConfig[] | undefined;
360
+ constructor(id: number, width: number, height: number);
361
+ /**
362
+ * Move the camera to a specific position
363
+ */
364
+ teleport(x: number, y: number): void;
365
+ /**
366
+ * Resize the viewport (cell dimensions).
367
+ */
368
+ resize(width: number, height: number): void;
369
+ /**
370
+ * Resize the viewport using a Vector2 (cell dimensions).
371
+ * Alias for `resize(size.x, size.y)`.
372
+ */
373
+ setSize(size: Vector2): void;
374
+ /**
375
+ * Store the client's pixel viewport dimensions.
376
+ * Called by the runtime when the client reports its screen size.
377
+ * @internal
378
+ */
379
+ setPixelViewport(pixelWidth: number, pixelHeight: number): void;
380
+ /**
381
+ * Calculate the maximum number of cells that fit in the client's pixel viewport
382
+ * for the given cell size. Uses the stored pixelWidth/pixelHeight.
383
+ *
384
+ * @param cellW - Cell width in pixels (defaults to this.cellWidth).
385
+ * @param cellH - Cell height in pixels (defaults to this.cellHeight).
386
+ * @returns `{ cols, rows }` clamped to [1, 256], or `null` if no pixel viewport is known.
387
+ */
388
+ calculateMaxCells(cellW?: number, cellH?: number): {
389
+ cols: number;
390
+ rows: number;
391
+ } | null;
392
+ /**
393
+ * Set cell pixel dimensions.
394
+ * Clamped to [1, 255]. Affects canvas resolution and Responsive grid calculation.
395
+ */
396
+ setCellSize(width: number, height: number): void;
397
+ /**
398
+ * Get cell pixel dimensions.
399
+ */
400
+ getCellSize(): {
401
+ cellWidth: number;
402
+ cellHeight: number;
403
+ };
404
+ /**
405
+ * Set scaling mode.
406
+ */
407
+ setScalingMode(mode: ScalingMode): void;
408
+ /**
409
+ * Set ambient (CRT/Blur) effects.
410
+ */
411
+ setAmbientEffect(config: boolean | Partial<AmbientEffectConfig>): void;
412
+ /**
413
+ * Set grid overlay (debug cell delimitation).
414
+ */
415
+ setGrid(config: boolean | Partial<GridConfig>): void;
416
+ /**
417
+ * Move the camera by a delta (relative movement).
418
+ *
419
+ * @param deltaX - Delta X in world cells.
420
+ * @param deltaY - Delta Y in world cells.
421
+ */
422
+ moveOrigin(deltaX: number, deltaY: number): void;
423
+ /**
424
+ * Set scanlines configuration.
425
+ * Pass `true` to enable with defaults, `false` to disable,
426
+ * or a partial config to merge.
427
+ */
428
+ setScanlines(config: boolean | Partial<ScanlinesConfig>): void;
429
+ /**
430
+ * Enable or disable scanlines.
431
+ */
432
+ setScanlinesEnabled(enabled: boolean): void;
433
+ /**
434
+ * Set scanlines opacity (0..1).
435
+ */
436
+ setScanlinesOpacity(opacity: number): void;
437
+ /**
438
+ * Enable or disable the grid overlay.
439
+ */
440
+ setGridEnabled(enabled: boolean): void;
441
+ /**
442
+ * Enable or disable the ambient effect.
443
+ */
444
+ setAmbientEffectEnabled(enabled: boolean): void;
445
+ /**
446
+ * Set post-processing effects.
447
+ */
448
+ setPostProcess(config: PostProcessConfig | null): void;
449
+ /**
450
+ * Set origin (top-left of viewport).
451
+ */
452
+ setOrigin(origin: Vector2): void;
453
+ /**
454
+ * Get origin (top-left of viewport).
455
+ * Backward-compatible helper.
456
+ */
457
+ getOrigin(): Vector2;
458
+ /**
459
+ * Get viewport size.
460
+ * Backward-compatible helper.
461
+ */
462
+ getSize(): {
463
+ x: number;
464
+ y: number;
465
+ width: number;
466
+ height: number;
467
+ };
468
+ /**
469
+ * Switch palette slot.
470
+ */
471
+ switchPalette(slotId: number): void;
472
+ /**
473
+ * Set render passes for multi-pass compositing (max 4).
474
+ * Each pass filters layers by Z-range.
475
+ * Pass `undefined` or empty array to reset to the default single pass.
476
+ */
477
+ setRenderPasses(passes: RenderPassConfig[] | undefined): void;
478
+ /**
479
+ * Get the current render pass configuration.
480
+ */
481
+ getRenderPasses(): RenderPassConfig[] | undefined;
482
+ private normalizePass;
483
+ /**
484
+ * Returns a debug-friendly snapshot of this display (metadata only).
485
+ */
486
+ getDebugInfo(): {
487
+ id: number;
488
+ origin: {
489
+ x: number;
490
+ y: number;
491
+ };
492
+ size: {
493
+ width: number;
494
+ height: number;
495
+ };
496
+ pixelViewport: {
497
+ pixelWidth: number;
498
+ pixelHeight: number;
499
+ };
500
+ cellSize: {
501
+ cellWidth: number;
502
+ cellHeight: number;
503
+ };
504
+ scalingMode: ScalingMode;
505
+ activePaletteSlot: number;
506
+ postProcess: PostProcessConfig;
507
+ renderPasses?: RenderPassConfig[];
508
+ };
509
+ }
510
+
511
+ /**
512
+ * InputBindingRegistry - Registry for logical axes and buttons.
513
+ *
514
+ * This registry is shared between client and server to ensure consistent input decoding.
515
+ * The server defines the bindings and sends them to the client via a JSON LoadPacket.
516
+ * Both sides use this registry to evaluate raw source values into logical actions.
517
+ */
518
+ declare class InputBindingRegistry {
519
+ private axes;
520
+ private buttons;
521
+ private touchZones;
522
+ private axisNameToId;
523
+ private buttonNameToId;
524
+ private touchZoneNameToId;
525
+ private version;
526
+ private _axesSortedCache;
527
+ private _buttonsSortedCache;
528
+ private _touchZonesSortedCache;
529
+ defineAxis(bindingId: number, name: string, sources?: AxisSource[], min?: number, max?: number, defaultValue?: number): void;
530
+ defineButton(bindingId: number, name: string, sources?: ButtonSource[], defaultValue?: boolean): void;
531
+ defineTouchZone(zoneId: number, name: string, x: number, y: number, width: number, height: number): void;
532
+ /**
533
+ * Evaluates an axis by summing all its sources.
534
+ *
535
+ * @param bindingId - Axis binding ID
536
+ * @param sourceValues - Map of raw source values (sourceId -> value)
537
+ * @returns Final axis value (clamped)
538
+ */
539
+ evaluateAxis(bindingId: number, sourceValues: Map<number, number>): number;
540
+ /**
541
+ * Evaluates a button with OR logic (pressed if any source is pressed).
542
+ */
543
+ evaluateButton(bindingId: number, sourceValues: Map<number, boolean>): boolean;
544
+ toLoadPacket(): InputBindingLoadPacket;
545
+ /**
546
+ * Rebuild this registry from a previously serialised `InputBindingLoadPacket`.
547
+ *
548
+ * Clears any existing bindings first, then re-registers every axis,
549
+ * button, and touch zone contained in the packet.
550
+ */
551
+ loadFromPacket(packet: InputBindingLoadPacket): void;
552
+ getAllAxes(): AxisBinding[];
553
+ getAllButtons(): ButtonBinding[];
554
+ getAllTouchZones(): TouchZoneBinding[];
555
+ getAxisCount(): number;
556
+ getButtonCount(): number;
557
+ getAxisId(name: string): number | null;
558
+ getButtonId(name: string): number | null;
559
+ clear(): void;
560
+ }
561
+
562
+ interface MacroInstanceState {
563
+ instanceId: number;
564
+ templateId: number;
565
+ layerId: number;
566
+ x: number;
567
+ y: number;
568
+ zIndex: number;
569
+ params: Record<string, unknown>;
570
+ state: 'running' | 'paused';
571
+ }
572
+ interface CreateInstanceConfig {
573
+ /** Template name (resolved to templateId internally) */
574
+ macro: string;
575
+ /** Target layer ID */
576
+ layer: number;
577
+ /** Position in cell coordinates on the layer */
578
+ x: number;
579
+ y: number;
580
+ /** Z-index within the macro layer (for multi-instance ordering) */
581
+ zIndex?: number;
582
+ /** Instance name (for later reference by name) */
583
+ name?: string;
584
+ /** Runtime parameters (merged with template defaults) */
585
+ params?: Record<string, unknown>;
586
+ }
587
+ declare class MacroRegistry {
588
+ private templates;
589
+ private templateNameToId;
590
+ private nextTemplateId;
591
+ private instances;
592
+ private instanceNameToId;
593
+ private nextInstanceId;
594
+ private pendingDefines;
595
+ private pendingOrders;
596
+ private feedbackHandlers;
597
+ registerTemplate(name: string, template: MacroTemplate): number;
598
+ getTemplate(idOrName: number | string): MacroTemplate | undefined;
599
+ getTemplateId(name: string): number | undefined;
600
+ createInstance(config: CreateInstanceConfig): number;
601
+ updateInstance(nameOrId: number | string, params: Record<string, unknown>): void;
602
+ removeInstance(nameOrId: number | string): void;
603
+ pauseInstance(nameOrId: number | string): void;
604
+ resumeInstance(nameOrId: number | string): void;
605
+ getPendingDefines(): MacroDefine[];
606
+ getPendingOrders(): MacroOrder[];
607
+ clearPendingDefines(): void;
608
+ clearPendingOrders(): void;
609
+ getAllDefines(): MacroDefine[];
610
+ getActiveInstanceOrders(): MacroCreateOrder[];
611
+ onEvent(nameOrId: number | string, event: string, handler: (data?: unknown) => void): void;
612
+ handleFeedback(feedback: MacroFeedback): void;
613
+ private resolveInstanceId;
614
+ }
615
+
616
+ /**
617
+ * User
618
+ * Represents a user connected to the Primitiv Engine.
619
+ * Owns a set of Layers and Displays (Viewports).
620
+ * Holds the current input state (axes, buttons, mouse).
621
+ * Collects imperative commands (Audio, Vibration) for the current tick.
622
+ *
623
+ * @typeParam TData - Custom per-user data state.
624
+ */
625
+ declare class User<TData = any> {
626
+ readonly id: string;
627
+ readonly name: string;
628
+ /** Custom persistent state for this user */
629
+ data: TData;
630
+ /**
631
+ * Incoming bridge messages from the remote peer (client or server).
632
+ *
633
+ * Populated between ticks by the runtime. Read during `updateUser()` to
634
+ * process messages synchronised with the game tick. The runtime clears the
635
+ * inbox automatically after `updateUser()` completes.
636
+ */
637
+ bridgeInbox: BridgeMessage[];
638
+ private _loadedSounds;
639
+ private _soundLoadErrors;
640
+ private _playingSounds;
641
+ /**
642
+ * Whether this user's browser tab is hidden.
643
+ * Set by the runtime when a visibility-change message is received.
644
+ * Used by RuntimeServer to skip sending updates to inactive clients.
645
+ */
646
+ isTabHidden: boolean;
647
+ private layers;
648
+ private displays;
649
+ private nextLayerId;
650
+ private _layersCache;
651
+ private _displaysCache;
652
+ private spriteRegistry?;
653
+ private macroRegistry;
654
+ private commandQueue;
655
+ private _commandQueueSwap;
656
+ private nextSoundInstanceId;
657
+ private axes;
658
+ private buttons;
659
+ private justPressed;
660
+ private justReleased;
661
+ mouseX: number;
662
+ mouseY: number;
663
+ activeDisplay: number;
664
+ mouseOver: boolean;
665
+ constructor(id: string, name: string);
666
+ /**
667
+ * Inject the sprite registry into this user.
668
+ * Called by the runtime after creation so layers can rasterize sprites.
669
+ * @internal
670
+ */
671
+ setSpriteRegistry(registry: SpriteRegistry): void;
672
+ /**
673
+ * Alias for createLayer for better readability in application code.
674
+ * Auto-assigns a unique numeric ID to the layer (like UTSP).
675
+ */
676
+ addLayer(layer: Layer, _id?: string): void;
677
+ /**
678
+ * Alias for createDisplay for better readability.
679
+ */
680
+ addDisplay(display: Display): void;
681
+ /**
682
+ * Returns a summary of mouse position info relative to the local display.
683
+ */
684
+ getMouseDisplayInfo(): {
685
+ localX: number;
686
+ localY: number;
687
+ displayId: number;
688
+ } | null;
689
+ /**
690
+ * Backward-compatible alias for touch display info.
691
+ * Uses unified pointer state (mouse/touch) tracked on the active display.
692
+ */
693
+ getTouchDisplayInfo(displayId?: number): {
694
+ localX: number;
695
+ localY: number;
696
+ displayId: number;
697
+ } | null;
698
+ /**
699
+ * Get viewport info for a display, including pixel dimensions
700
+ * reported by the client.
701
+ */
702
+ getDisplayViewport(displayId: number): {
703
+ id: number;
704
+ x: number;
705
+ y: number;
706
+ width: number;
707
+ height: number;
708
+ pixelWidth: number;
709
+ pixelHeight: number;
710
+ origin: {
711
+ x: number;
712
+ y: number;
713
+ };
714
+ size: {
715
+ x: number;
716
+ y: number;
717
+ width: number;
718
+ height: number;
719
+ };
720
+ } | null;
721
+ /**
722
+ * Calculate the maximum number of cells that fit in the client's pixel viewport
723
+ * for the given cell size. Delegates to Display.calculateMaxCells().
724
+ *
725
+ * @param displayId - Display ID.
726
+ * @param cellW - Cell width in pixels.
727
+ * @param cellH - Cell height in pixels.
728
+ */
729
+ calculateMaxCells(displayId: number, cellW: number, cellH: number): {
730
+ cols: number;
731
+ rows: number;
732
+ } | null;
733
+ private inputRegistry;
734
+ /**
735
+ * Get binding registry for application specific input definitions.
736
+ */
737
+ getInputBindingRegistry(): InputBindingRegistry;
738
+ /**
739
+ * Updates the user state from a binary input packet.
740
+ * This is called on the server when receiving a packet,
741
+ * or on the client after hardware sampling.
742
+ */
743
+ applyInput(packet: CompressedInputPacket, registry: InputBindingRegistry): void;
744
+ /**
745
+ * Clears one-frame transitions and command queues.
746
+ * Should be called at the end of the engine update.
747
+ */
748
+ poll(): void;
749
+ /**
750
+ * Play a sound for this user.
751
+ * Queues an AudioOrder for the next network update.
752
+ */
753
+ playSound(sound: string | number, options?: {
754
+ volume?: number;
755
+ pitch?: number;
756
+ loop?: boolean;
757
+ fadeIn?: number;
758
+ x?: number;
759
+ y?: number;
760
+ lowpass?: number;
761
+ highpass?: number;
762
+ reverb?: number;
763
+ }): number;
764
+ /**
765
+ * Stop a sound immediately by instance ID or name.
766
+ */
767
+ stopSound(target: number | string): void;
768
+ /**
769
+ * Stop all sounds immediately.
770
+ */
771
+ stopAllSounds(): void;
772
+ /**
773
+ * Fade out a sound over a duration (seconds).
774
+ */
775
+ fadeOutSound(target: number | string, duration: number): void;
776
+ /**
777
+ * Fade out all sounds over a duration (seconds).
778
+ */
779
+ fadeOutAllSounds(duration: number): void;
780
+ /**
781
+ * Pause a specific sound instance.
782
+ */
783
+ pauseSound(target: number | string): void;
784
+ /**
785
+ * Pause all sounds.
786
+ */
787
+ pauseAllSounds(): void;
788
+ /**
789
+ * Resume a specific sound instance.
790
+ */
791
+ resumeSound(target: number | string): void;
792
+ /**
793
+ * Resume all sounds.
794
+ */
795
+ resumeAllSounds(): void;
796
+ /**
797
+ * Set audio effects (lowpass, highpass, reverb) on a playing sound instance.
798
+ */
799
+ setSoundEffects(instanceId: number, options: {
800
+ lowpass?: number;
801
+ highpass?: number;
802
+ reverb?: number;
803
+ pitch?: number;
804
+ volume?: number;
805
+ }): void;
806
+ /**
807
+ * Set the listener position for 2D spatial audio.
808
+ */
809
+ setListenerPosition(x: number, y: number): void;
810
+ /**
811
+ * Configure spatial audio parameters.
812
+ */
813
+ configureSpatialAudio(config: {
814
+ maxDistance?: number;
815
+ referenceDistance?: number;
816
+ rolloffFactor?: number;
817
+ panSpread?: number;
818
+ }): void;
819
+ /**
820
+ * Signal that all registered sounds should be sent to this user's client.
821
+ * In standalone mode, this triggers loading sounds into the AudioEngine's SoundBank.
822
+ */
823
+ sendSounds(): void;
824
+ /** @internal */
825
+ _pendingSendSounds: boolean;
826
+ /**
827
+ * Trigger a vibration on the user's device (mobile).
828
+ */
829
+ vibrate(pattern: number | number[]): void;
830
+ /**
831
+ * Trigger a dual-rumble vibration on the user's gamepad.
832
+ *
833
+ * @param options Vibration parameters (duration, motors, gamepad index).
834
+ *
835
+ * @example
836
+ * ```ts
837
+ * // Heavy hit on first gamepad
838
+ * user.vibrateGamepad({ duration: 200, strongMagnitude: 1.0, weakMagnitude: 0.3 });
839
+ *
840
+ * // Light buzz on second gamepad
841
+ * user.vibrateGamepad({ duration: 100, strongMagnitude: 0, weakMagnitude: 0.8, gamepadIndex: 1 });
842
+ * ```
843
+ */
844
+ vibrateGamepad(options: {
845
+ duration: number;
846
+ strongMagnitude?: number;
847
+ weakMagnitude?: number;
848
+ startDelay?: number;
849
+ gamepadIndex?: number;
850
+ }): void;
851
+ /**
852
+ * Update post-processing effects for a specific display.
853
+ */
854
+ setPostProcess(displayId: number, config: PostProcessConfig | null): void;
855
+ setAmbientEffect(displayId: number, config: boolean | Partial<AmbientEffectConfig>): void;
856
+ setGrid(displayId: number, config: boolean | Partial<GridConfig>): void;
857
+ setScalingMode(displayId: number, mode: ScalingMode): void;
858
+ switchPalette(displayId: number, slotId: number): void;
859
+ setOrigin(displayId: number, origin: Vector2): void;
860
+ /**
861
+ * Returns and clears the current command queue.
862
+ * Internal use for synchronization.
863
+ */
864
+ flushCommands(): Order[];
865
+ getAxis(name: string): number;
866
+ getButton(name: string): boolean;
867
+ isJustPressed(name: string): boolean;
868
+ isJustReleased(name: string): boolean;
869
+ createLayer(id: number, width: number, height: number): Layer;
870
+ getLayer(id: number): Layer | undefined;
871
+ removeLayer(id: number): boolean;
872
+ getLayers(): Layer[];
873
+ createDisplay(id: number, width: number, height: number): Display;
874
+ getDisplay(id: number): Display | undefined;
875
+ removeDisplay(id: number): boolean;
876
+ getDisplays(): Display[];
877
+ defineButton(bindingId: number, name: string, sources: ButtonSource[], defaultValue?: boolean): void;
878
+ defineAxis(bindingId: number, name: string, sources: AxisSource[], min?: number, max?: number, defaultValue?: number): void;
879
+ /**
880
+ * Process an audio acknowledgment from this user's client.
881
+ *
882
+ * Called automatically by the runtime when the client reports audio events.
883
+ * Updates internal tracking maps so the application can query state at any
884
+ * time via `isSoundLoaded()`, `isSoundPlaying()`, etc.
885
+ *
886
+ * @internal
887
+ */
888
+ handleAudioAck(ack: AudioAck): void;
889
+ /** Check whether a sound (by soundId) is loaded on this user's client. */
890
+ isSoundLoaded(soundId: number): boolean;
891
+ /** Get all loaded sounds for this user. */
892
+ getLoadedSounds(): ReadonlyMap<number, {
893
+ name: string;
894
+ loadedAt: number;
895
+ }>;
896
+ /** Get the load error for a specific sound, if any. */
897
+ getSoundLoadError(soundId: number): string | undefined;
898
+ /** Get all sound load errors for this user. */
899
+ getSoundLoadErrors(): ReadonlyMap<number, {
900
+ name: string;
901
+ error: string;
902
+ at: number;
903
+ }>;
904
+ /** Check whether a sound instance is currently playing on this user's client. */
905
+ isSoundPlaying(instanceId: SoundInstanceId): boolean;
906
+ /** Get all currently playing sound instances for this user. */
907
+ getPlayingSounds(): ReadonlyMap<SoundInstanceId, {
908
+ soundId: number;
909
+ startedAt: number;
910
+ }>;
911
+ /** Get the number of sound instances currently playing on this user's client. */
912
+ getPlayingSoundCount(): number;
913
+ /** Injected by Engine.createUser() */
914
+ setMacroRegistry(registry: MacroRegistry): void;
915
+ /** Get the macro registry (used by encoder to gather pending orders/defines). */
916
+ getMacroRegistry(): MacroRegistry | null;
917
+ /**
918
+ * Load a macro template. Call during initUser().
919
+ * Returns the templateId for reference.
920
+ */
921
+ loadMacro(name: string, template: MacroTemplate): number;
922
+ /** Create a macro instance on a macro layer. */
923
+ createMacroInstance(config: {
924
+ macro: string;
925
+ layer: number;
926
+ x: number;
927
+ y: number;
928
+ zIndex?: number;
929
+ name?: string;
930
+ params?: Record<string, unknown>;
931
+ }): number;
932
+ updateMacroInstance(nameOrId: number | string, params: Record<string, unknown>): void;
933
+ removeMacroInstance(nameOrId: number | string): void;
934
+ pauseMacroInstance(nameOrId: number | string): void;
935
+ resumeMacroInstance(nameOrId: number | string): void;
936
+ /** Register a handler for macro feedback from the client. */
937
+ onMacroEvent(nameOrId: number | string, event: string, handler: (data?: unknown) => void): void;
938
+ /** Handle macro feedback received from ClientCallback. */
939
+ handleMacroFeedback(feedback: MacroFeedback): void;
940
+ }
941
+
942
+ /**
943
+ * UserUpdateBuilder
944
+ *
945
+ * Serializes UserSession state and commands into a binary update packet.
946
+ * Currently focuses on imperative commands (Audio, Vibration).
947
+ */
948
+ declare class UserUpdateBuilder {
949
+ private buffer;
950
+ private view;
951
+ private offset;
952
+ private textEncoder;
953
+ constructor(initialSize?: number);
954
+ /**
955
+ * Serializes the session's pending commands into a binary payload.
956
+ * Note: This does not yet serialize the Grid/Layer state, only the command queue.
957
+ */
958
+ serialize(session: User): Uint8Array;
959
+ private writeOrder;
960
+ private writeAudioOrder;
961
+ private writeVibrationOrder;
962
+ private writePostProcessOrder;
963
+ private ensureCapacity;
964
+ private writeUint8;
965
+ private writeUint16;
966
+ private writeInt16;
967
+ private writeString;
968
+ }
969
+
970
+ /**
971
+ * UserUpdateParser
972
+ *
973
+ * Deserializes binary update packets into User state and commands.
974
+ * Currently focuses on imperative commands (Audio, Vibration).
975
+ */
976
+ declare class UserUpdateParser {
977
+ private textDecoder;
978
+ /**
979
+ * Parses a binary update payload into a list of Orders.
980
+ */
981
+ parse(payload: Uint8Array): Order[];
982
+ private parseOrder;
983
+ private parseAudioOrder;
984
+ private parseVibrationOrder;
985
+ private parsePostProcessOrder;
986
+ }
987
+
988
+ /**
989
+ * Encodes a CompressedInputPacket into a self-describing binary buffer.
990
+ *
991
+ * Binary layout:
992
+ * [axisCount(1), buttonCount(1),
993
+ * axes(N × (bindingId:uint16 + value:int8) = 3 bytes each),
994
+ * buttonBindingIds(M × uint16), buttonValues(ceil(M/8) bytes bitpacked),
995
+ * displayId(1), mouseX(1), mouseY(1), flags(1),
996
+ * textInputs(variable), viewports(variable), touches(variable)]
997
+ *
998
+ * The 2-byte header (axisCount, buttonCount) makes the format self-describing
999
+ * so the decoder does not need an external registry to know the field counts.
1000
+ * BindingIds are preserved to ensure correct input mapping after decode.
1001
+ */
1002
+ declare function encodeCompressedInput(packet: CompressedInputPacket): Uint8Array;
1003
+ /**
1004
+ * Decodes a self-describing binary buffer into a CompressedInputPacket.
1005
+ *
1006
+ * Axis and button counts are read from the 2-byte header, so no external
1007
+ * registry is needed to parse the packet. BindingIds are preserved from
1008
+ * the encoded data to ensure correct input mapping.
1009
+ */
1010
+ declare function decodeCompressedInput(buffer: Uint8Array, _registry?: InputBindingRegistry): CompressedInputPacket;
1011
+
1012
+ /**
1013
+ * Font system for Primitiv Core
1014
+ * Supports BitmapFont (pixel-based) and ImageFont (PNG atlas-based)
1015
+ */
1016
+ /**
1017
+ * Font type enumeration
1018
+ */
1019
+ declare enum FontType {
1020
+ Bitmap = "bitmap",
1021
+ Image = "image"
1022
+ }
1023
+ /**
1024
+ * Number of 256-char blocks in an atlas
1025
+ * Must be a power of two from 1 to 256.
1026
+ * - 1 block = 256 chars (128×128 @ 8px)
1027
+ * - 2 blocks = 512 chars (256×128 @ 8px)
1028
+ * - 4 blocks = 1024 chars (256×256 @ 8px)
1029
+ * - 256 blocks = 65536 chars (2048×2048 @ 8px)
1030
+ */
1031
+ type AtlasBlocks = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256;
1032
+ /**
1033
+ * Glyph size in pixels (uniform within an atlas)
1034
+ */
1035
+ type GlyphSize = 8 | 16 | 32;
1036
+ /**
1037
+ * Atlas grid layout computed from block count.
1038
+ * The atlas may be rectangular (cols ≠ rows).
1039
+ */
1040
+ interface AtlasLayout {
1041
+ /** Number of character columns (blocksPerRow × 16) */
1042
+ cols: number;
1043
+ /** Number of character rows (blocksPerCol × 16) */
1044
+ rows: number;
1045
+ /** Number of blocks per row */
1046
+ blocksPerRow: number;
1047
+ /** Number of block rows */
1048
+ blocksPerCol: number;
1049
+ }
1050
+ /**
1051
+ * Return the smallest power of two ≥ n (n must be > 0).
1052
+ */
1053
+ declare function nextPow2(n: number): number;
1054
+ /**
1055
+ * Compute the atlas grid layout for a given block count.
1056
+ * Both blocksPerRow and blocksPerCol are powers of two.
1057
+ */
1058
+ declare function getAtlasLayout(blocks: number): AtlasLayout;
1059
+ /**
1060
+ * Get the number of columns in an atlas grid
1061
+ * @param blocks Number of atlas blocks (1, 4, or 16)
1062
+ * @returns Number of columns (16, 32, or 64)
1063
+ */
1064
+ declare function getAtlasColumns(blocks: AtlasBlocks): number;
1065
+ /**
1066
+ * Get the number of rows in an atlas grid
1067
+ * @param blocks Number of atlas blocks
1068
+ * @returns Number of rows
1069
+ */
1070
+ declare function getAtlasRows(blocks: AtlasBlocks): number;
1071
+ /**
1072
+ * Get the maximum character code for an atlas configuration
1073
+ * @param blocks Number of atlas blocks
1074
+ * @returns Maximum charCode (blocks * 256 - 1)
1075
+ */
1076
+ declare function getMaxCharCode(blocks: AtlasBlocks): number;
1077
+ /**
1078
+ * Get atlas texture dimensions in pixels.
1079
+ * Each block occupies 16 × nextPow2(glyphWidth) by 16 × nextPow2(glyphHeight),
1080
+ * so the overall atlas is always PoT.
1081
+ *
1082
+ * @param blocks Number of atlas blocks
1083
+ * @param glyphWidth Width of each glyph in pixels
1084
+ * @param glyphHeight Height of each glyph in pixels (defaults to glyphWidth)
1085
+ * @returns Atlas dimensions { width, height }
1086
+ */
1087
+ declare function getAtlasDimensions(blocks: AtlasBlocks, glyphWidth: number, glyphHeight?: number): {
1088
+ width: number;
1089
+ height: number;
1090
+ };
1091
+ /**
1092
+ * Options for loading an ImageFont
1093
+ */
1094
+ interface ImageFontOptions {
1095
+ /** Width of each glyph in pixels (8, 16, or 32) */
1096
+ glyphWidth: number;
1097
+ /** Height of each glyph in pixels (8, 16, or 32) */
1098
+ glyphHeight: number;
1099
+ /** Target cell width for rendering (default: glyphWidth) */
1100
+ cellWidth?: number;
1101
+ /** Target cell height for rendering (default: glyphHeight) */
1102
+ cellHeight?: number;
1103
+ /** Number of 256-char blocks (power of two, 1-256) */
1104
+ atlasBlocks?: AtlasBlocks;
1105
+ }
1106
+ /**
1107
+ * ImageFont configuration
1108
+ * For PNG atlas-based fonts with pre-rendered glyphs
1109
+ */
1110
+ interface ImageFontConfig {
1111
+ glyphWidth: number;
1112
+ glyphHeight: number;
1113
+ cellWidth?: number;
1114
+ cellHeight?: number;
1115
+ atlasBlocks: AtlasBlocks;
1116
+ }
1117
+ /**
1118
+ * ImageFont class
1119
+ * Represents a PNG atlas-based font for extended character sets
1120
+ */
1121
+ declare class ImageFont {
1122
+ private fontId;
1123
+ private config;
1124
+ private readonly atlasColumns;
1125
+ private readonly atlasRows;
1126
+ private readonly maxCharCode;
1127
+ private blocks;
1128
+ constructor(fontId: number, config: ImageFontConfig);
1129
+ /**
1130
+ * Add image data for a specific block
1131
+ */
1132
+ addBlock(blockIndex: number, data: Uint8Array): void;
1133
+ /**
1134
+ * Get image data for a specific block
1135
+ */
1136
+ getBlock(blockIndex: number): Uint8Array | undefined;
1137
+ /**
1138
+ * Get the unique font ID
1139
+ */
1140
+ getFontId(): number;
1141
+ /**
1142
+ * Get the full configuration
1143
+ */
1144
+ getConfig(): ImageFontConfig;
1145
+ /**
1146
+ * Get the glyph width in pixels
1147
+ */
1148
+ getGlyphWidth(): number;
1149
+ /**
1150
+ * Get the glyph height in pixels
1151
+ */
1152
+ getGlyphHeight(): number;
1153
+ /**
1154
+ * Get the target cell width in pixels (rendering size)
1155
+ */
1156
+ getCellWidth(): number;
1157
+ /**
1158
+ * Get the target cell height in pixels (rendering size)
1159
+ */
1160
+ getCellHeight(): number;
1161
+ /**
1162
+ * Get the number of atlas blocks
1163
+ */
1164
+ getAtlasBlocks(): AtlasBlocks;
1165
+ /**
1166
+ * Get the number of columns in the atlas grid
1167
+ */
1168
+ getAtlasColumns(): number;
1169
+ /**
1170
+ * Get the maximum supported charCode
1171
+ */
1172
+ getMaxCharCode(): number;
1173
+ /**
1174
+ * Get the number of rows in the atlas grid
1175
+ */
1176
+ getAtlasRows(): number;
1177
+ /**
1178
+ * Get the atlas dimensions in pixels.
1179
+ * Uses effective (next-PoT) glyph size for PoT texture dimensions.
1180
+ */
1181
+ getAtlasDimensions(): {
1182
+ width: number;
1183
+ height: number;
1184
+ };
1185
+ /**
1186
+ * Get UV coordinates for a character code.
1187
+ *
1188
+ * Glyphs are tightly packed within each block (no per-glyph padding).
1189
+ * Blocks are positioned at PoT boundaries in the atlas.
1190
+ * UV coordinates sample only the real glyph area.
1191
+ *
1192
+ * @param charCode Character code (0 to maxCharCode)
1193
+ * @returns UV coordinates { u1, v1, u2, v2 } or null if out of range
1194
+ */
1195
+ getCharUV(charCode: number): {
1196
+ u1: number;
1197
+ v1: number;
1198
+ u2: number;
1199
+ v2: number;
1200
+ } | null;
1201
+ /**
1202
+ * Check if a charCode is valid for this atlas
1203
+ */
1204
+ isValidCharCode(charCode: number): boolean;
1205
+ }
1206
+
1207
+ /**
1208
+ * Registry for managing ImageFont instances
1209
+ * Each font is identified by a unique fontId (0-255) and a human-readable name
1210
+ */
1211
+ declare class ImageFontRegistry {
1212
+ private fonts;
1213
+ private nameToId;
1214
+ private nextId;
1215
+ private allocateId;
1216
+ /**
1217
+ * Register a new ImageFont structure (no data)
1218
+ */
1219
+ registerFont(name: string, options: ImageFontOptions): number;
1220
+ /**
1221
+ * Unregister a font by name
1222
+ */
1223
+ unregisterFont(name: string): void;
1224
+ /**
1225
+ * Check if a font exists by name
1226
+ */
1227
+ hasFont(name: string): boolean;
1228
+ /**
1229
+ * Add a data block to an existing font
1230
+ */
1231
+ addBlock(fontId: number, blockIndex: number, data: Uint8Array): void;
1232
+ getFont(fontId: number): ImageFont | undefined;
1233
+ getFontByName(name: string): ImageFont | undefined;
1234
+ getFontId(name: string): number | undefined;
1235
+ /**
1236
+ * Get all registered fonts
1237
+ */
1238
+ getAllFonts(): ImageFont[];
1239
+ /**
1240
+ * Get the human-readable name of a font by its ID
1241
+ */
1242
+ getFontName(fontId: number): string | undefined;
1243
+ }
1244
+
1245
+ /**
1246
+ * Internal representation of a registered sound
1247
+ */
1248
+ interface SoundEntry {
1249
+ soundId: number;
1250
+ name: string;
1251
+ loadType: SoundLoadType;
1252
+ format: SoundFormat;
1253
+ data?: Uint8Array;
1254
+ url?: string;
1255
+ size?: number;
1256
+ checksum?: string;
1257
+ }
1258
+ /**
1259
+ * SoundRegistry - Manages sound definitions on the server
1260
+ */
1261
+ declare class SoundRegistry {
1262
+ private sounds;
1263
+ private nameToId;
1264
+ private nextId;
1265
+ /**
1266
+ * Register a sound with embedded data (File mode)
1267
+ */
1268
+ registerFile(name: string, format: SoundFormat, data: Uint8Array): number;
1269
+ /**
1270
+ * Register an external sound (FileExternal mode)
1271
+ */
1272
+ registerExternal(name: string, format: SoundFormat, url: string, size?: number, checksum?: string): number;
1273
+ get(idOrName: number | string): SoundEntry | undefined;
1274
+ has(idOrName: number | string): boolean;
1275
+ /**
1276
+ * Generate load packets for all registered sounds
1277
+ */
1278
+ toLoadPackets(): Array<SoundLoadPacket | SoundExternalLoadPacket>;
1279
+ private allocateId;
1280
+ private addEntry;
1281
+ }
1282
+
1283
+ interface TickPackets {
1284
+ reliable: Uint8Array;
1285
+ volatile: Uint8Array;
1286
+ }
1287
+ declare class TickPacketEncoder {
1288
+ /**
1289
+ * Encode a user's tick state into reliable + volatile packets.
1290
+ */
1291
+ static encode(user: User): TickPackets;
1292
+ /**
1293
+ * Encode the complete user state into a single packet (for LoadBundle).
1294
+ *
1295
+ * Unlike encode(), this includes ALL layers regardless of mustBeReliable
1296
+ * and ignores the needsCommit flag - every layer is encoded.
1297
+ * This is used to send the full initial state during the handshake.
1298
+ */
1299
+ static encodeFull(user: User, palettes?: Map<number, any[]>): Uint8Array;
1300
+ private static encodePacket;
1301
+ private static encodeAudioOrder;
1302
+ private static encodeSoundTarget;
1303
+ private static encodeVibrationOrder;
1304
+ private static encodeMacroDefine;
1305
+ private static encodeMacroOrder;
1306
+ /**
1307
+ * Encode PostProcessConfig into the binary stream.
1308
+ *
1309
+ * Format:
1310
+ * flags: u8 (bit0=ambientEffect, bit1=scanlines, bit2=grid)
1311
+ * If bit0: enabled(1) blur(1) scale×10(1) opacity×100(1)
1312
+ * If bit1: enabled(1) opacity×100(1) pattern(1) spacing(1) thickness(1) colorR(1) colorG(1) colorB(1)
1313
+ * If bit2: enabled(1) lineWidth×10(1) colorLen(1) color(utf8)
1314
+ */
1315
+ private static encodePostProcess;
1316
+ }
1317
+
1318
+ /**
1319
+ * EngineStats - Lightweight tick-level metrics for the Primitiv Engine.
1320
+ *
1321
+ * Tracks per-tick encoding cost (time, bytes, layer/cell/order counts)
1322
+ * using a fixed-size ring buffer. Provides rolling averages and
1323
+ * instantaneous snapshots with zero allocation in the hot path.
1324
+ */
1325
+ /** Snapshot of engine metrics at query time. */
1326
+ interface EngineStatsSnapshot {
1327
+ /** Total ticks encoded since engine start. */
1328
+ totalTicks: number;
1329
+ /** Duration of the last endTick() call (ms). */
1330
+ lastTickDurationMs: number;
1331
+ /** Rolling average of endTick() duration over the window (ms). */
1332
+ avgTickDurationMs: number;
1333
+ /** Peak endTick() duration within the window (ms). */
1334
+ peakTickDurationMs: number;
1335
+ /** Bytes produced by the last endTick() (reliable + volatile). */
1336
+ lastTickBytes: number;
1337
+ /** Rolling average bytes per tick. */
1338
+ avgTickBytes: number;
1339
+ /** Number of layers encoded in the last tick. */
1340
+ lastLayerCount: number;
1341
+ /** Number of draw orders encoded in the last tick. */
1342
+ lastOrderCount: number;
1343
+ /** Number of display cells composited in the last tick. */
1344
+ lastCellCount: number;
1345
+ /** Number of displays encoded in the last tick. */
1346
+ lastDisplayCount: number;
1347
+ }
1348
+ /**
1349
+ * Collects per-tick metrics in a fixed-size ring buffer.
1350
+ *
1351
+ * Usage (called by Engine.endTick internals):
1352
+ * stats.beginTick();
1353
+ * // … encode …
1354
+ * stats.endTick({ bytes, layers, orders, cells, displays });
1355
+ */
1356
+ declare class EngineStats {
1357
+ private readonly samples;
1358
+ private head;
1359
+ private count;
1360
+ private readonly windowSize;
1361
+ /** Monotonically increasing tick counter. */
1362
+ totalTicks: number;
1363
+ private _t0;
1364
+ constructor(windowSize?: number);
1365
+ /** Call immediately before encoding begins. */
1366
+ beginTick(): void;
1367
+ /** Call immediately after encoding finishes with the tick's counters. */
1368
+ endTick(counters: {
1369
+ bytes: number;
1370
+ layers: number;
1371
+ orders: number;
1372
+ cells: number;
1373
+ displays: number;
1374
+ }): void;
1375
+ /** Return a snapshot of current metrics. Zero-alloc for the ring scan. */
1376
+ getSnapshot(): EngineStatsSnapshot;
1377
+ /** Reset all samples and counters. */
1378
+ reset(): void;
1379
+ }
1380
+
1381
+ type EngineMode = 'server' | 'client' | 'standalone';
1382
+ interface EngineOptions {
1383
+ mode: EngineMode;
1384
+ }
1385
+ /**
1386
+ * Engine
1387
+ * The central game engine that orchestrates the world.
1388
+ * Unified Architecture: Operates as Server or Client based on mode.
1389
+ */
1390
+ declare class Engine {
1391
+ static readonly VGA_COLORS: {
1392
+ colorId: number;
1393
+ r: number;
1394
+ g: number;
1395
+ b: number;
1396
+ a: number;
1397
+ }[];
1398
+ static readonly SYSTEM_COLORS: {
1399
+ colorId: number;
1400
+ r: number;
1401
+ g: number;
1402
+ b: number;
1403
+ a: number;
1404
+ }[];
1405
+ readonly mode: EngineMode;
1406
+ readonly sessions: Map<string, User>;
1407
+ readonly spriteRegistry: SpriteRegistry;
1408
+ readonly fontRegistry: ImageFontRegistry;
1409
+ readonly soundRegistry: SoundRegistry;
1410
+ readonly inputBindings: InputBindingRegistry;
1411
+ readonly macroRegistry: MacroRegistry;
1412
+ /** Per-tick performance metrics. */
1413
+ readonly stats: EngineStats;
1414
+ /**
1415
+ * Get the sprite registry instance.
1416
+ */
1417
+ getSpriteRegistry(): SpriteRegistry;
1418
+ private resourceLoader;
1419
+ private onFontAllocatedCallback;
1420
+ private onFontBlockAddedCallback;
1421
+ constructor(options: EngineOptions);
1422
+ /**
1423
+ * Set the resource loader implementation.
1424
+ * Must be called by the runtime before any loadSound() / loadSounds() call.
1425
+ *
1426
+ * - ClientRuntime injects FetchResourceLoader (browser)
1427
+ * - RuntimeServer injects NodeResourceLoader (Node.js)
1428
+ */
1429
+ setResourceLoader(loader: IResourceLoader): void;
1430
+ /**
1431
+ * Create and register a new User session.
1432
+ *
1433
+ * @param clientId - Numeric client ID (will be converted to string internally)
1434
+ * @param name - Optional display name (defaults to "Player {clientId}")
1435
+ * @returns The newly created User
1436
+ */
1437
+ createUser(clientId: number, name?: string): User;
1438
+ /**
1439
+ * Remove a User session by numeric client ID.
1440
+ *
1441
+ * @param clientId - Numeric client ID
1442
+ * @returns true if the user was found and removed
1443
+ */
1444
+ removeUser(clientId: number): boolean;
1445
+ /**
1446
+ * Get a User session by numeric client ID.
1447
+ *
1448
+ * @param clientId - Numeric client ID
1449
+ * @returns The User if found, undefined otherwise
1450
+ */
1451
+ getUser(clientId: number): User | undefined;
1452
+ /**
1453
+ * Encode a user's current tick state into binary packets.
1454
+ *
1455
+ * Produces two packets:
1456
+ * - `reliable`: layers with mustBeReliable=true + audio/vibration commands
1457
+ * - `volatile`: layers with mustBeReliable=false (no commands)
1458
+ *
1459
+ * After encoding, clears pending orders and commit flags on dirty layers.
1460
+ * The caller is responsible for transporting these packets (loopback or network).
1461
+ */
1462
+ endTick(user: User): TickPackets;
1463
+ /**
1464
+ * Get a snapshot of engine performance metrics.
1465
+ *
1466
+ * Returns rolling averages over the last ~120 ticks:
1467
+ * tick duration, bytes produced, layer/order/cell counts.
1468
+ */
1469
+ getEngineStats(): EngineStatsSnapshot;
1470
+ /**
1471
+ * Encode the complete initial state of a user into a single packet (for LoadBundle).
1472
+ *
1473
+ * Unlike endTick(), this includes ALL layers regardless of mustBeReliable flag
1474
+ * and does NOT require layers to be committed. Used during the handshake to send
1475
+ * the full initial state (displays, layers, commands) to the client before simulation.
1476
+ *
1477
+ * Does NOT clear pending orders or commit flags - the caller (RuntimeServer)
1478
+ * manages post-encoding cleanup separately.
1479
+ */
1480
+ encodeInitialState(user: User): Uint8Array;
1481
+ /**
1482
+ * Register a callback fired when font structure is (re)allocated.
1483
+ * The runtime uses this to call renderer.setImageFontStructure().
1484
+ */
1485
+ onFontAllocated(cb: () => void): void;
1486
+ /**
1487
+ * Register a callback fired when a font block is added.
1488
+ * The runtime uses this to call renderer.setImageFontBlock().
1489
+ */
1490
+ onFontBlockAdded(cb: (blockIndex: number) => void): void;
1491
+ /**
1492
+ * Configure the font / atlas structure.
1493
+ *
1494
+ * @param glyphWidth Width of each glyph in the atlas PNG (px)
1495
+ * @param glyphHeight Height of each glyph in the atlas PNG (px)
1496
+ * @param atlasBlocks Number of 256-char blocks (power of two, 1-256)
1497
+ * @param cellWidth Rendering cell width (px) - may be larger than glyph for padding
1498
+ * @param cellHeight Rendering cell height (px)
1499
+ */
1500
+ loadFont(glyphWidth: number, glyphHeight: number, atlasBlocks: AtlasBlocks, cellWidth: number, cellHeight: number): void;
1501
+ /**
1502
+ * Load a font block from a resource path (PNG image).
1503
+ * Can also accept raw Uint8Array data directly.
1504
+ *
1505
+ * @param blockIndex Block index (0-based). Block 0 is the base ASCII set.
1506
+ * @param pathOrData Path to a PNG file, or raw PNG bytes
1507
+ */
1508
+ loadFontBlock(blockIndex: number, pathOrData: string | Uint8Array): Promise<void>;
1509
+ /**
1510
+ * Load multiple font blocks in parallel.
1511
+ * @param blocks Record of blockIndex -> path/URL
1512
+ */
1513
+ loadFontBlocks(blocks: Record<number, string>): Promise<void>;
1514
+ /**
1515
+ * Get the current font configuration (fontId 0).
1516
+ * Returns undefined if no font is allocated.
1517
+ */
1518
+ getFontConfig(): ImageFontConfig | undefined;
1519
+ /**
1520
+ * Get block data for a specific block index.
1521
+ */
1522
+ getFontBlock(blockIndex: number): Uint8Array | undefined;
1523
+ private palettes;
1524
+ /**
1525
+ * Detect sound format from file path extension.
1526
+ */
1527
+ private detectSoundFormat;
1528
+ /**
1529
+ * Load a sound from a file path and register it.
1530
+ * Returns the assigned sound ID (0-255).
1531
+ *
1532
+ * Works isomorphically:
1533
+ * - Browser: fetches via HTTP
1534
+ * - Node.js: reads from filesystem
1535
+ */
1536
+ loadSound(name: string, path: string): Promise<number>;
1537
+ /**
1538
+ * Load multiple sounds in parallel.
1539
+ * @param sounds Record of name -> path pairs
1540
+ * @returns Record of name -> soundId
1541
+ */
1542
+ loadSounds(sounds: Record<string, string>): Promise<Record<string, number>>;
1543
+ /**
1544
+ * Initialize the default palette (slot 0).
1545
+ *
1546
+ * Matches UTSP Core.initializeDefaultPalette():
1547
+ * - 0-15: VGA base colors
1548
+ * - 16-239: Undefined -> transparent (r:0, g:0, b:0, a:0)
1549
+ * - 240-254: System reserved colors (cannot be overridden)
1550
+ * - 255: COLOR_SKIP -> transparent (r:0, g:0, b:0, a:0)
1551
+ */
1552
+ private initializeDefaultPalette;
1553
+ /**
1554
+ * Load a palette into a specific slot.
1555
+ *
1556
+ * Matches UTSP Core.loadPaletteToSlot():
1557
+ * - Accepts user-defined colors for indices 0-239
1558
+ * - Forces system reserved colors 240-254 (cannot be overridden)
1559
+ * - Forces color 255 as transparent (COLOR_SKIP)
1560
+ * - Undefined slots default to transparent (r:0, g:0, b:0, a:0)
1561
+ */
1562
+ loadPaletteToSlot(slot: number, palette: any[]): void;
1563
+ /**
1564
+ * Get a palette from a specific slot.
1565
+ */
1566
+ getPalette(slot: number): any[] | undefined;
1567
+ }
1568
+
1569
+ /**
1570
+ * DisplayCompositor
1571
+ *
1572
+ * Merges multiple Layers into a single Display buffer.
1573
+ * Optimized for Primitiv V6 (Uint32Array).
1574
+ *
1575
+ * Supports multi-pass rendering: each pass filters layers by Z-range,
1576
+ * then passes are composited bottom-up (lowest pass first).
1577
+ *
1578
+ * Cached scratch buffers (opaqueMask, passGrids, sortScratch) are reused
1579
+ * across frames to avoid per-frame heap allocations.
1580
+ */
1581
+ declare class DisplayCompositor {
1582
+ /** Reusable opaque-mask buffer (resized as needed). */
1583
+ private _opaqueMask;
1584
+ /** Per-pass cached grids for multi-pass compositing. */
1585
+ private _passGrids;
1586
+ /** Per-pass opaque-mask buffers. */
1587
+ private _passOpaqueMasks;
1588
+ /** Scratch array for sorting layers without allocating. */
1589
+ private _sortScratch;
1590
+ /** Last composite pass output (cached for retrieval). */
1591
+ private _lastPasses;
1592
+ /** Ensure the opaque mask is large enough, then zero it. */
1593
+ private ensureMask;
1594
+ /** Ensure per-pass grid buffers are allocated and correctly sized. */
1595
+ private ensurePassGrids;
1596
+ /**
1597
+ * Composites layers onto a target Display grid.
1598
+ *
1599
+ * When the display has no render passes defined, uses a single default
1600
+ * pass that accepts Z 0-255.
1601
+ *
1602
+ * With render passes:
1603
+ * 1. Each pass composites only the layers whose zIndex falls in [zMin, zMax].
1604
+ * 2. Passes are composited bottom-up (pass 0 first), each pass's opaque pixels
1605
+ * overwrite the previous ones.
1606
+ * 3. Per-pass grid data is preserved for renderers that support multi-pass.
1607
+ *
1608
+ * @returns Per-pass render states when multi-pass is active, undefined otherwise.
1609
+ */
1610
+ composite(display: Display, layers: Layer[], target: Grid): RenderPassState[] | undefined;
1611
+ /** Retrieve the last composite passes result (for callers who can't use the return value). */
1612
+ getLastPasses(): RenderPassState[] | undefined;
1613
+ private compositeSinglePass;
1614
+ private compositeMultiPass;
1615
+ /**
1616
+ * Overlay pass data onto target.
1617
+ * Foreground passes overwrite background passes:
1618
+ * - Opaque BG: fully replaces target cell
1619
+ * - Transparent BG with char/fg: char and fg overwrite target (foreground wins)
1620
+ */
1621
+ private overlayPass;
1622
+ private compositeLayer;
1623
+ }
1624
+
1625
+ /**
1626
+ * LayerRasterizer
1627
+ *
1628
+ * Responsible for translating drawing orders into a Grid's packed data.
1629
+ * Optimized for Primitiv V6 (Uint32Array).
1630
+ */
1631
+ declare class LayerRasterizer {
1632
+ /**
1633
+ * Rasterize a set of orders onto a target grid.
1634
+ * Note: Does NOT clear the grid; assume it's pre-cleared if needed.
1635
+ */
1636
+ rasterize(grid: Grid, orders: Order[], spriteRegistry?: SpriteRegistry): void;
1637
+ private executeOrder;
1638
+ private drawChar;
1639
+ private drawText;
1640
+ private drawTextMultiline;
1641
+ private drawSubFrame;
1642
+ private drawSubFrameMulti;
1643
+ private drawFullFrame;
1644
+ private drawFullFrameMulti;
1645
+ private drawColorMap;
1646
+ private drawFill;
1647
+ private drawFillChar;
1648
+ private drawFillSprite;
1649
+ private drawFillSpriteMulti;
1650
+ private drawSprite;
1651
+ private drawSpriteMulti;
1652
+ private drawDotCloud;
1653
+ private drawDotCloudMulti;
1654
+ private drawSpriteCloud;
1655
+ private drawSpriteCloudMulti;
1656
+ private drawSpriteCloudVaried;
1657
+ private drawSpriteCloudVariedMulti;
1658
+ private drawBitmask;
1659
+ private drawBitmask4;
1660
+ private drawBitmask16;
1661
+ private drawPolyline;
1662
+ private drawLineBresenham;
1663
+ private drawShape;
1664
+ private drawRectangle;
1665
+ private drawCircle;
1666
+ private drawEllipse;
1667
+ private drawTriangle;
1668
+ }
1669
+
1670
+ /**
1671
+ * OrderBuilder - Fluent API for generating draw orders
1672
+ */
1673
+ declare class OrderBuilder {
1674
+ private orders;
1675
+ /**
1676
+ * Convert string or number to char code
1677
+ */
1678
+ static toCharCode(char: string | number): number;
1679
+ /**
1680
+ * Dedent template literals
1681
+ */
1682
+ static dedent(text: string): string;
1683
+ /**
1684
+ * Encodes a string into CP437 character codes packed into a string.
1685
+ */
1686
+ static encodeString(text: string): string;
1687
+ /**
1688
+ * Get the accumulated orders
1689
+ */
1690
+ getOrders(): Order[];
1691
+ /**
1692
+ * Clear orders
1693
+ */
1694
+ clear(): this;
1695
+ /**
1696
+ * Draw a single character
1697
+ */
1698
+ char(x: number, y: number, char: string | number, fg?: number, bg?: number): this;
1699
+ static char(x: number, y: number, char: string | number, fg?: number, bg?: number): CharOrder;
1700
+ /**
1701
+ * Draw a single line of text
1702
+ */
1703
+ text(x: number, y: number, text: string, fg?: number, bg?: number): this;
1704
+ static text(x: number, y: number, text: string, fg?: number, bg?: number): TextOrder;
1705
+ /**
1706
+ * Draw multiple lines of text
1707
+ */
1708
+ textMultiline(x: number, y: number, text: string, fg?: number, bg?: number): this;
1709
+ static textMultiline(x: number, y: number, text: string, fg?: number, bg?: number): TextMultilineOrder;
1710
+ /**
1711
+ * Draw a sub-frame (region of characters)
1712
+ */
1713
+ subFrame(x: number, y: number, width: number, height: number, frame: (string | number)[], fg?: number, bg?: number): this;
1714
+ static subFrame(x: number, y: number, width: number, height: number, frame: (string | number)[], fg?: number, bg?: number): SubFrameOrder;
1715
+ /**
1716
+ * Draw a sub-frame with individual cell colors
1717
+ */
1718
+ subFrameMulti(x: number, y: number, width: number, height: number, frame: {
1719
+ char: string | number;
1720
+ fg: number;
1721
+ bg: number;
1722
+ }[]): this;
1723
+ static subFrameMulti(x: number, y: number, width: number, height: number, frame: {
1724
+ char?: string | number;
1725
+ charCode?: string | number;
1726
+ fg?: number;
1727
+ fgColor?: number;
1728
+ fgColorCode?: number;
1729
+ bg?: number;
1730
+ bgColor?: number;
1731
+ bgColorCode?: number;
1732
+ }[]): SubFrameMultiOrder;
1733
+ /**
1734
+ * Draw a full frame (entire grid of characters)
1735
+ */
1736
+ fullFrame(frame: (string | number)[], fg?: number, bg?: number): this;
1737
+ static fullFrame(frame: (string | number)[], fg?: number, bg?: number): FullFrameOrder;
1738
+ /**
1739
+ * Draw a full frame with individual cell colors
1740
+ */
1741
+ fullFrameMulti(frame: {
1742
+ char?: string | number;
1743
+ charCode?: string | number;
1744
+ fg?: number;
1745
+ fgColor?: number;
1746
+ fgColorCode?: number;
1747
+ bg?: number;
1748
+ bgColor?: number;
1749
+ bgColorCode?: number;
1750
+ }[]): this;
1751
+ static fullFrameMulti(frame: {
1752
+ char?: string | number;
1753
+ charCode?: string | number;
1754
+ fg?: number;
1755
+ fgColor?: number;
1756
+ fgColorCode?: number;
1757
+ bg?: number;
1758
+ bgColor?: number;
1759
+ bgColorCode?: number;
1760
+ }[]): FullFrameMultiOrder;
1761
+ /**
1762
+ * Draw a unicolor sprite
1763
+ */
1764
+ sprite(x: number, y: number, spriteId: number, fg?: number, bg?: number): this;
1765
+ static sprite(x: number, y: number, spriteId: number, fg?: number, bg?: number): SpriteOrder;
1766
+ /**
1767
+ * Draw a multicolor sprite
1768
+ */
1769
+ spriteMulti(x: number, y: number, spriteId: number): this;
1770
+ static spriteMulti(x: number, y: number, spriteId: number): SpriteMultiOrder;
1771
+ /**
1772
+ * Draw a color map (region of colors)
1773
+ */
1774
+ colorMap(x: number, y: number, width: number, height: number, data: ColorMapCell[]): this;
1775
+ /**
1776
+ * Draw a rectangle
1777
+ */
1778
+ rect(x: number, y: number, width: number, height: number, char?: string | number, fg?: number, bg?: number, filled?: boolean): this;
1779
+ static rect(x: number, y: number, width: number, height: number, char?: string | number, fg?: number, bg?: number, filled?: boolean): ShapeOrder;
1780
+ /**
1781
+ * Draw a circle
1782
+ */
1783
+ circle(x: number, y: number, radius: number, char: string | number, fg?: number, bg?: number, filled?: boolean): this;
1784
+ static circle(x: number, y: number, radius: number, charOrOptions?: string | number | {
1785
+ charCode?: string | number;
1786
+ fgColor?: number;
1787
+ bgColor?: number;
1788
+ filled?: boolean;
1789
+ }, fg?: number, bg?: number, filled?: boolean): ShapeOrder;
1790
+ /**
1791
+ * Draw a line
1792
+ */
1793
+ line(x1: number, y1: number, x2: number, y2: number, charOrOptions: string | number | {
1794
+ charCode?: string | number;
1795
+ fgColor?: number;
1796
+ bgColor?: number;
1797
+ }, fg?: number, bg?: number): this;
1798
+ static line(x1: number, y1: number, x2: number, y2: number, charOrOptions: string | number | {
1799
+ charCode?: string | number;
1800
+ fgColor?: number;
1801
+ bgColor?: number;
1802
+ }, fg?: number, bg?: number): ShapeOrder;
1803
+ /**
1804
+ * Draw a triangle
1805
+ */
1806
+ triangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, char: string | number, fg?: number, bg?: number, filled?: boolean): this;
1807
+ static triangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, charOrOptions?: string | number | {
1808
+ charCode?: string | number;
1809
+ fgColor?: number;
1810
+ bgColor?: number;
1811
+ filled?: boolean;
1812
+ }, fg?: number, bg?: number, filled?: boolean): ShapeOrder;
1813
+ /**
1814
+ * Draw an ellipse
1815
+ */
1816
+ ellipse(x: number, y: number, radiusX: number, radiusY: number, char: string | number, fg?: number, bg?: number, filled?: boolean): this;
1817
+ static ellipse(x: number, y: number, radiusX: number, radiusY: number, charOrOptions?: string | number | {
1818
+ charCode?: string | number;
1819
+ fgColor?: number;
1820
+ bgColor?: number;
1821
+ filled?: boolean;
1822
+ }, fg?: number, bg?: number, filled?: boolean): ShapeOrder;
1823
+ /**
1824
+ * Draw a polyline
1825
+ */
1826
+ polyline(points: {
1827
+ x: number;
1828
+ y: number;
1829
+ }[], char: string | number, fg?: number, bg?: number): this;
1830
+ static polyline(points: {
1831
+ x: number;
1832
+ y: number;
1833
+ }[], char: string | number, fg?: number, bg?: number): PolylineOrder;
1834
+ /**
1835
+ * Draw a closed polygon (polyline that connects back to start)
1836
+ */
1837
+ polygon(points: {
1838
+ x: number;
1839
+ y: number;
1840
+ }[], char: string | number, fg?: number, bg?: number): this;
1841
+ static polygon(points: {
1842
+ x: number;
1843
+ y: number;
1844
+ }[], char: string | number, fg?: number, bg?: number): PolylineOrder;
1845
+ /**
1846
+ * Draw a cloud of dots with a single character and color
1847
+ */
1848
+ dotCloud(positions: {
1849
+ x: number;
1850
+ y: number;
1851
+ }[], char: string | number, fg?: number, bg?: number): this;
1852
+ static dotCloud(positions: {
1853
+ x?: number;
1854
+ y?: number;
1855
+ posX?: number;
1856
+ posY?: number;
1857
+ }[], char: string | number, fg?: number, bg?: number): DotCloudOrder;
1858
+ /**
1859
+ * Draw a cloud of dots with individual characters and colors
1860
+ */
1861
+ dotCloudMulti(dots: {
1862
+ x: number;
1863
+ y: number;
1864
+ char: string | number;
1865
+ fg: number;
1866
+ bg: number;
1867
+ }[]): this;
1868
+ static dotCloudMulti(dots: {
1869
+ x?: number;
1870
+ y?: number;
1871
+ posX?: number;
1872
+ posY?: number;
1873
+ char?: string | number;
1874
+ charCode?: string | number;
1875
+ fg?: number;
1876
+ fgColor?: number;
1877
+ fgColorCode?: number;
1878
+ bg?: number;
1879
+ bgColor?: number;
1880
+ bgColorCode?: number;
1881
+ }[]): DotCloudMultiOrder;
1882
+ /**
1883
+ * Draw a cloud of sprites with a single sprite ID and color
1884
+ */
1885
+ spriteCloud(positions: {
1886
+ x: number;
1887
+ y: number;
1888
+ }[], spriteId: number, fg?: number, bg?: number): this;
1889
+ static spriteCloud(spriteId: number, positions: {
1890
+ x?: number;
1891
+ y?: number;
1892
+ posX?: number;
1893
+ posY?: number;
1894
+ }[], fg?: number, bg?: number): SpriteCloudOrder;
1895
+ /**
1896
+ * Draw a cloud of sprites with a single sprite ID (multicolor)
1897
+ */
1898
+ spriteCloudMulti(positions: {
1899
+ x: number;
1900
+ y: number;
1901
+ }[], spriteId: number): this;
1902
+ static spriteCloudMulti(spriteId: number, positions: {
1903
+ x?: number;
1904
+ y?: number;
1905
+ posX?: number;
1906
+ posY?: number;
1907
+ }[]): SpriteCloudMultiOrder;
1908
+ /**
1909
+ * Draw a cloud of sprites where each position has a specific sprite ID (varied)
1910
+ */
1911
+ spriteCloudVaried(sprites: {
1912
+ x: number;
1913
+ y: number;
1914
+ spriteId: number;
1915
+ fg: number;
1916
+ bg: number;
1917
+ }[]): this;
1918
+ static spriteCloudVaried(sprites: {
1919
+ x?: number;
1920
+ y?: number;
1921
+ posX?: number;
1922
+ posY?: number;
1923
+ spriteId?: number;
1924
+ spriteIndex?: number;
1925
+ fg?: number;
1926
+ fgColor?: number;
1927
+ fgColorCode?: number;
1928
+ bg?: number;
1929
+ bgColor?: number;
1930
+ bgColorCode?: number;
1931
+ }[]): SpriteCloudVariedOrder;
1932
+ /**
1933
+ * Draw a cloud of sprites where each position has a specific sprite ID (varied multicolor)
1934
+ */
1935
+ spriteCloudVariedMulti(sprites: {
1936
+ x: number;
1937
+ y: number;
1938
+ spriteId: number;
1939
+ }[]): this;
1940
+ static spriteCloudVariedMulti(sprites: {
1941
+ x?: number;
1942
+ y?: number;
1943
+ posX?: number;
1944
+ posY?: number;
1945
+ spriteId?: number;
1946
+ spriteIndex?: number;
1947
+ }[]): SpriteCloudVariedMultiOrder;
1948
+ /**
1949
+ * Draw a 1-bit bitmask (char vs empty)
1950
+ */
1951
+ bitmask(x: number, y: number, width: number, height: number, mask: ArrayLike<number>, char: string | number, fg?: number, bg?: number, override?: boolean): this;
1952
+ static bitmask(x: number, y: number, width: number, height: number, mask: ArrayLike<number | boolean>, char: string | number, fg?: number, bg?: number, override?: boolean): BitmaskOrder;
1953
+ /**
1954
+ * Draw a 2-bit bitmask (up to 3 variants + empty)
1955
+ */
1956
+ bitmask4(x: number, y: number, width: number, height: number, mask: ArrayLike<number>, variants: {
1957
+ char: string | number;
1958
+ charCode?: string | number;
1959
+ fg?: number;
1960
+ fgColor?: number;
1961
+ bg?: number;
1962
+ bgColor?: number;
1963
+ }[], override?: boolean): this;
1964
+ static bitmask4(x: number, y: number, width: number, height: number, mask: ArrayLike<number>, variants: {
1965
+ char: string | number;
1966
+ charCode?: string | number;
1967
+ fg?: number;
1968
+ fgColor?: number;
1969
+ bg?: number;
1970
+ bgColor?: number;
1971
+ }[], override?: boolean): Bitmask4Order;
1972
+ /**
1973
+ * Draw a 4-bit bitmask (up to 15 variants + empty)
1974
+ */
1975
+ bitmask16(x: number, y: number, width: number, height: number, mask: ArrayLike<number>, variants: {
1976
+ char: string | number;
1977
+ charCode?: string | number;
1978
+ fg?: number;
1979
+ fgColor?: number;
1980
+ bg?: number;
1981
+ bgColor?: number;
1982
+ }[], override?: boolean): this;
1983
+ static bitmask16(x: number, y: number, width: number, height: number, mask: ArrayLike<number>, variants: {
1984
+ char: string | number;
1985
+ charCode?: string | number;
1986
+ fg?: number;
1987
+ fgColor?: number;
1988
+ bg?: number;
1989
+ bgColor?: number;
1990
+ }[], override?: boolean): Bitmask16Order;
1991
+ /**
1992
+ * Fill a region or the whole grid
1993
+ */
1994
+ fill(char: string | number, fg?: number, bg?: number): this;
1995
+ static fill(char: string | number, fg?: number, bg?: number): FillOrder;
1996
+ /**
1997
+ * Fill the grid with a character pattern
1998
+ */
1999
+ fillChar(patternWidth: number, patternHeight: number, pattern: (string | number)[], fg?: number, bg?: number): this;
2000
+ static fillChar(patternWidth: number, patternHeight: number, pattern: (string | number)[], fg?: number, bg?: number): FillCharOrder;
2001
+ /**
2002
+ * Fill the grid with a unicolor sprite pattern
2003
+ */
2004
+ fillSprite(spriteId: number, fg?: number, bg?: number): this;
2005
+ static fillSprite(spriteId: number, fg?: number, bg?: number): FillSpriteOrder;
2006
+ /**
2007
+ * Fill the grid with a multicolor sprite pattern
2008
+ */
2009
+ fillSpriteMulti(spriteId: number): this;
2010
+ static fillSpriteMulti(spriteId: number): FillSpriteMultiOrder;
2011
+ /**
2012
+ * Draw a box with a border (returns two ShapeOrders: filled interior + unfilled border).
2013
+ *
2014
+ * @param x - Left edge
2015
+ * @param y - Top edge
2016
+ * @param width - Total width including border
2017
+ * @param height - Total height including border
2018
+ * @param border - Border appearance { charCode?, fgColor?, bgColor? }
2019
+ * @param fill - Interior fill { charCode?, fgColor?, bgColor? }
2020
+ */
2021
+ boxWithBorder(x: number, y: number, width: number, height: number, border?: {
2022
+ charCode?: string | number;
2023
+ fgColor?: number;
2024
+ bgColor?: number;
2025
+ }, fill?: {
2026
+ charCode?: string | number;
2027
+ fgColor?: number;
2028
+ bgColor?: number;
2029
+ }): this;
2030
+ static boxWithBorder(x: number, y: number, width: number, height: number, border?: {
2031
+ charCode?: string | number;
2032
+ fgColor?: number;
2033
+ bgColor?: number;
2034
+ }, fill?: {
2035
+ charCode?: string | number;
2036
+ fgColor?: number;
2037
+ bgColor?: number;
2038
+ }): ShapeOrder[];
2039
+ /**
2040
+ * Draw a grid of dots at regular intervals.
2041
+ *
2042
+ * Places a character at every intersection of a grid with the given
2043
+ * cell dimensions and row/col count.
2044
+ *
2045
+ * @param startX - Left origin
2046
+ * @param startY - Top origin
2047
+ * @param cellWidth - Horizontal distance between grid points
2048
+ * @param cellHeight - Vertical distance between grid points
2049
+ * @param rows - Number of rows (grid lines = rows + 1)
2050
+ * @param cols - Number of columns (grid lines = cols + 1)
2051
+ * @param char - Character to place at each intersection
2052
+ * @param fg - Foreground color
2053
+ * @param bg - Background color
2054
+ */
2055
+ grid(startX: number, startY: number, cellWidth: number, cellHeight: number, rows: number, cols: number, char?: string | number, fg?: number, bg?: number): this;
2056
+ static grid(startX: number, startY: number, cellWidth: number, cellHeight: number, rows: number, cols: number, char?: string | number, fg?: number, bg?: number): DotCloudOrder;
2057
+ }
2058
+
2059
+ /**
2060
+ * BinaryReader - Position-tracked binary buffer reader.
2061
+ *
2062
+ * Shared implementation used by TickPacketDecoder and OrderDecoder.
2063
+ * Supports all primitive read operations needed by the Primitiv V6 protocol.
2064
+ */
2065
+ declare class BinaryReader {
2066
+ private _buf;
2067
+ private _view;
2068
+ offset: number;
2069
+ constructor(buffer: Uint8Array, offset?: number);
2070
+ get remaining(): number;
2071
+ /** Access the underlying buffer (for sub-slicing). */
2072
+ get rawBuffer(): Uint8Array;
2073
+ readU8(): number;
2074
+ readI8(): number;
2075
+ readU16BE(): number;
2076
+ readI16BE(): number;
2077
+ readU16LE(): number;
2078
+ readBytes(count: number): Uint8Array;
2079
+ }
2080
+
2081
+ /**
2082
+ * BinaryWriter - Growable binary buffer for encoding.
2083
+ *
2084
+ * Shared implementation used by TickPacketEncoder and OrderEncoder.
2085
+ * Supports pooling via reset() to avoid per-tick heap allocations.
2086
+ */
2087
+ declare class BinaryWriter {
2088
+ private buffer;
2089
+ private view;
2090
+ offset: number;
2091
+ constructor(initialSize?: number);
2092
+ /**
2093
+ * Reset the writer for reuse (zero-alloc).
2094
+ * Keeps the existing buffer - only resets the write cursor.
2095
+ */
2096
+ reset(): void;
2097
+ private ensure;
2098
+ /**
2099
+ * Ensure capacity and return the underlying buffer for direct writes
2100
+ * (e.g. TextEncoder.encodeInto). Caller must advance offset manually.
2101
+ */
2102
+ ensureAndGetBuffer(bytes: number): Uint8Array;
2103
+ writeU8(v: number): void;
2104
+ writeI8(v: number): void;
2105
+ writeU16BE(v: number): void;
2106
+ writeI16BE(v: number): void;
2107
+ writeU16LE(v: number): void;
2108
+ writeBytes(data: Uint8Array): void;
2109
+ /**
2110
+ * Return a trimmed copy of the written data.
2111
+ * Safe to use when the writer will be reused/reset afterwards.
2112
+ */
2113
+ toUint8Array(): Uint8Array;
2114
+ /**
2115
+ * Return a view (subarray) of the written data - zero-copy.
2116
+ * WARNING: The view shares the underlying buffer. Only valid until the next
2117
+ * write or reset. Use when a short-lived read is sufficient (e.g. immediate
2118
+ * copy into a packet).
2119
+ */
2120
+ getView(): Uint8Array;
2121
+ }
2122
+
2123
+ /**
2124
+ * OrderEncoder - Encodes render orders to compact binary format.
2125
+ *
2126
+ * Each order starts with a 1-byte type tag followed by type-specific payload.
2127
+ * Convention: Big-endian for sizes/positions, charCodes as-is (1 byte 8bit, 2 bytes LE 16bit).
2128
+ */
2129
+
2130
+ declare class OrderEncoder {
2131
+ private static readonly _sharedWriter;
2132
+ /**
2133
+ * Encode a list of render orders into binary.
2134
+ * @param orders The orders to encode.
2135
+ * @param is16bit Whether charCodes are 16-bit (true) or 8-bit (false).
2136
+ * @returns Encoded binary data.
2137
+ */
2138
+ static encode(orders: Order[], is16bit?: boolean): Uint8Array;
2139
+ /**
2140
+ * Encode a list of render orders directly into a provided BinaryWriter.
2141
+ * Zero-alloc variant - avoids creating an intermediate Uint8Array.
2142
+ * Used by TickPacketEncoder to write orders inline.
2143
+ */
2144
+ static encodeInto(w: BinaryWriter, orders: Order[], is16bit?: boolean): void;
2145
+ /**
2146
+ * Encode a single order into the writer.
2147
+ */
2148
+ private static encodeOne;
2149
+ private static encodeChar;
2150
+ private static encodeText;
2151
+ private static encodeTextMultiline;
2152
+ private static encodeSubFrame;
2153
+ private static encodeSubFrameMulti;
2154
+ private static encodeFullFrame;
2155
+ private static encodeFullFrameMulti;
2156
+ private static encodeSprite;
2157
+ private static encodeSpriteMulti;
2158
+ private static encodeColorMap;
2159
+ private static encodeShape;
2160
+ private static encodePolyline;
2161
+ private static encodeDotCloud;
2162
+ private static encodeDotCloudMulti;
2163
+ private static encodeSpriteCloud;
2164
+ private static encodeSpriteCloudMulti;
2165
+ private static encodeSpriteCloudVaried;
2166
+ private static encodeSpriteCloudVariedMulti;
2167
+ private static encodeBitmask;
2168
+ private static encodeBitmask4;
2169
+ private static encodeBitmask16;
2170
+ private static encodeFill;
2171
+ private static encodeFillChar;
2172
+ private static encodeFillSprite;
2173
+ private static encodeFillSpriteMulti;
2174
+ }
2175
+
2176
+ /**
2177
+ * OrderDecoder - Decodes render orders from compact binary format.
2178
+ *
2179
+ * Mirrors OrderEncoder: Big-endian for sizes/positions, charCodes 1 byte (8bit) or 2 bytes LE (16bit).
2180
+ */
2181
+
2182
+ declare class OrderDecoder {
2183
+ /**
2184
+ * Decode a binary buffer into a list of render orders.
2185
+ * @param buffer The binary data (may contain 0..N orders concatenated).
2186
+ * @param is16bit Whether charCodes are 16-bit.
2187
+ * @param layerWidth Width of the target layer (needed for FullFrame).
2188
+ * @param layerHeight Height of the target layer (needed for FullFrame).
2189
+ * @returns Decoded orders array.
2190
+ */
2191
+ static decode(buffer: Uint8Array, is16bit?: boolean, layerWidth?: number, layerHeight?: number): Order[];
2192
+ /**
2193
+ * Decode exactly `count` orders from an existing BinaryReader.
2194
+ *
2195
+ * Unlike decode(), this does not create its own reader and does not
2196
+ * read until end-of-buffer. It advances the shared reader by exactly
2197
+ * the bytes consumed by `count` orders, allowing the caller to
2198
+ * continue reading subsequent sections from the same buffer.
2199
+ */
2200
+ static decodeN(r: BinaryReader, count: number, is16bit: boolean, layerWidth: number, layerHeight: number): Order[];
2201
+ private static decodeOne;
2202
+ private static decodeChar;
2203
+ private static decodeText;
2204
+ private static decodeTextMultiline;
2205
+ private static decodeSubFrame;
2206
+ private static decodeSubFrameMulti;
2207
+ private static decodeFullFrame;
2208
+ private static decodeFullFrameMulti;
2209
+ private static decodeSprite;
2210
+ private static decodeSpriteMulti;
2211
+ private static decodeColorMap;
2212
+ private static decodeShape;
2213
+ private static decodePolyline;
2214
+ private static decodeDotCloud;
2215
+ private static decodeDotCloudMulti;
2216
+ private static decodeSpriteCloud;
2217
+ private static decodeSpriteCloudMulti;
2218
+ private static decodeSpriteCloudVaried;
2219
+ private static decodeSpriteCloudVariedMulti;
2220
+ private static decodeBitmask;
2221
+ private static decodeBitmask4;
2222
+ private static decodeBitmask16;
2223
+ private static decodeFill;
2224
+ private static decodeFillChar;
2225
+ private static decodeFillSprite;
2226
+ private static decodeFillSpriteMulti;
2227
+ }
2228
+
2229
+ /**
2230
+ * TickPacketDecoder - Decodes a full tick update packet from binary.
2231
+ *
2232
+ * Mirrors TickPacketEncoder. Produces a structured object suitable for
2233
+ * ClientRuntime.applyUpdate().
2234
+ */
2235
+
2236
+ interface DecodedDisplay {
2237
+ id: number;
2238
+ originX: number;
2239
+ originY: number;
2240
+ width: number;
2241
+ height: number;
2242
+ paletteSlot: number;
2243
+ scalingMode: ScalingMode;
2244
+ cellWidth: number;
2245
+ cellHeight: number;
2246
+ renderPasses?: {
2247
+ id: number;
2248
+ zMin: number;
2249
+ zMax: number;
2250
+ enabled: boolean;
2251
+ }[];
2252
+ postProcess: PostProcessConfig;
2253
+ }
2254
+ interface DecodedLayer {
2255
+ id: number;
2256
+ enabled: boolean;
2257
+ isMacro: boolean;
2258
+ is16bit: boolean;
2259
+ /** True when the server sent new orders this tick. When false, the client should preserve its existing orders. */
2260
+ hasOrders: boolean;
2261
+ zIndex: number;
2262
+ originX: number;
2263
+ originY: number;
2264
+ width: number;
2265
+ height: number;
2266
+ orders: Order[];
2267
+ /** Wire size in bytes consumed by this layer (header + orders). */
2268
+ byteSize: number;
2269
+ }
2270
+ interface DecodedPalette {
2271
+ slot: number;
2272
+ colors: {
2273
+ colorId: number;
2274
+ r: number;
2275
+ g: number;
2276
+ b: number;
2277
+ a: number;
2278
+ }[];
2279
+ }
2280
+ interface DecodedTickPacket {
2281
+ displays: DecodedDisplay[];
2282
+ palettes: DecodedPalette[];
2283
+ layers: DecodedLayer[];
2284
+ audioOrders: AudioOrder[];
2285
+ vibrationOrders: VibrationOrder[];
2286
+ macroDefines: MacroDefine[];
2287
+ macroOrders: MacroOrder[];
2288
+ /** Input binding definitions (only present in LoadBundle / full snapshot). */
2289
+ inputBindings?: InputBindingLoadPacket;
2290
+ /** Wire byte sizes of each packet section (for traffic tracking). */
2291
+ sectionSizes: {
2292
+ displays: number;
2293
+ palettes: number;
2294
+ layers: number;
2295
+ audio: number;
2296
+ vibration: number;
2297
+ macroDefines: number;
2298
+ macroOrders: number;
2299
+ total: number;
2300
+ };
2301
+ }
2302
+ declare class TickPacketDecoder {
2303
+ /**
2304
+ * Decode a binary tick packet into a structured object.
2305
+ */
2306
+ static decode(buffer: Uint8Array): DecodedTickPacket;
2307
+ /**
2308
+ * Decode N orders from the reader.
2309
+ *
2310
+ * Delegates directly to OrderDecoder.decodeN() which reads exactly
2311
+ * `count` orders from the shared BinaryReader, advancing its offset.
2312
+ * No skip pass needed - single-pass decoding.
2313
+ */
2314
+ private static decodeOrders;
2315
+ private static decodeAudioOrder;
2316
+ private static decodeSoundTarget;
2317
+ private static decodeVibrationOrder;
2318
+ private static decodeMacroDefine;
2319
+ private static decodeMacroOrder;
2320
+ /**
2321
+ * Decode PostProcessConfig from the binary stream.
2322
+ * Mirrors TickPacketEncoder.encodePostProcess().
2323
+ */
2324
+ private static decodePostProcess;
2325
+ }
2326
+
2327
+ /**
2328
+ * Unicode to IBM CP437 Conversion Table
2329
+ *
2330
+ * ROBUST VERSION: Uses only numeric codepoints, no literal characters.
2331
+ * This prevents any encoding issues (UTF-8, Latin-1, Windows-1252, etc.)
2332
+ *
2333
+ * Maps Unicode codepoints to CP437 byte values (0-255).
2334
+ */
2335
+ /**
2336
+ * Unicode -> CP437 Map (built from the numeric table above)
2337
+ */
2338
+ declare const UNICODE_TO_CP437: Map<number, number>;
2339
+ /**
2340
+ * Convert Unicode codepoint to CP437 byte value.
2341
+ *
2342
+ * @param unicodeChar - Unicode codepoint (from string.charCodeAt())
2343
+ * @returns CP437 byte value (0-255)
2344
+ *
2345
+ * @example
2346
+ * unicodeToCp437(0x2591) // -> 176 (░ Light Shade)
2347
+ * unicodeToCp437(0x0041) // -> 65 (A)
2348
+ * unicodeToCp437('░'.charCodeAt(0)) // -> 176
2349
+ */
2350
+ declare function unicodeToCp437(unicodeChar: number): number;
2351
+ /**
2352
+ * Convert a JavaScript string to CP437 byte array.
2353
+ *
2354
+ * @param text - Unicode string
2355
+ * @returns Uint8Array of CP437 byte values
2356
+ *
2357
+ * @example
2358
+ * stringToCp437('░▒▓') // -> Uint8Array [176, 177, 178]
2359
+ */
2360
+ declare function stringToCp437(text: string): Uint8Array;
2361
+ /**
2362
+ * Convert CP437 byte value to Unicode codepoint.
2363
+ *
2364
+ * @param cp437Byte - CP437 byte value (0-255)
2365
+ * @returns Unicode codepoint
2366
+ *
2367
+ * @example
2368
+ * cp437ToUnicode(176) // -> 0x2591 (░)
2369
+ */
2370
+ declare function cp437ToUnicodeCodepoint(cp437Byte: number): number;
2371
+ /**
2372
+ * Convert CP437 byte value to Unicode character string.
2373
+ *
2374
+ * @param cp437Byte - CP437 byte value (0-255)
2375
+ * @returns Unicode character
2376
+ *
2377
+ * @example
2378
+ * cp437ToUnicode(176) // -> '░'
2379
+ */
2380
+ declare function cp437ToUnicode(cp437Byte: number): string;
2381
+ /**
2382
+ * Check if a Unicode codepoint has a CP437 mapping.
2383
+ *
2384
+ * @param unicodeChar - Unicode codepoint
2385
+ * @returns true if character can be mapped to CP437
2386
+ */
2387
+ declare function hasCP437Mapping(unicodeChar: number): boolean;
2388
+ /**
2389
+ * Encodes a string into CP437 character codes packed into a string.
2390
+ */
2391
+ declare function encodeCp437String(text: string): string;
2392
+
2393
+ /**
2394
+ * Lightweight Event Emitter
2395
+ * Browser/Node compatible implementation to avoid 'events' dependency.
2396
+ */
2397
+ declare class EventEmitter<T = any> {
2398
+ private listeners;
2399
+ on(event: string, callback: (data: T) => void): void;
2400
+ off(event: string, callback: (data: T) => void): void;
2401
+ emit(event: string, data?: T): void;
2402
+ removeAllListeners(): void;
2403
+ }
2404
+
2405
+ /**
2406
+ * Primitiv Core Constants
2407
+ */
2408
+ /**
2409
+ * COLOR_SKIP (255)
2410
+ * Used as a special color index to signify transparency/skipping in the rendering pipeline.
2411
+ * Matches UTSP parity.
2412
+ */
2413
+ declare const COLOR_SKIP = 255;
2414
+ /**
2415
+ * LAYER_SIZE
2416
+ * Maximum width/height for a single layer grid.
2417
+ */
2418
+ declare const LAYER_SIZE = 256;
2419
+
2420
+ export { BinaryReader, COLOR_SKIP, CellStruct, Display, DisplayCompositor, Engine, EngineStats, EventEmitter, FontType, Grid, ImageFont, ImageFontRegistry, InputBindingRegistry, LAYER_SIZE, Layer, LayerRasterizer, MacroRegistry, OrderBuilder, OrderDecoder, OrderEncoder, SoundRegistry, SpriteRegistry, TickPacketDecoder, TickPacketEncoder, UNICODE_TO_CP437, User, UserUpdateBuilder, UserUpdateParser, cp437ToUnicode, cp437ToUnicodeCodepoint, decodeCompressedInput, encodeCompressedInput, encodeCp437String, getAtlasColumns, getAtlasDimensions, getAtlasLayout, getAtlasRows, getMaxCharCode, hasCP437Mapping, nextPow2, stringToCp437, unicodeToCp437 };
2421
+ export type { AtlasBlocks, AtlasLayout, CharCodeMode, CreateInstanceConfig, DecodedDisplay, DecodedLayer, DecodedPalette, DecodedTickPacket, EngineMode, EngineOptions, EngineStatsSnapshot, GlyphSize, ImageFontConfig, ImageFontOptions, LayerOptions, MacroInstanceState, SoundEntry, TickPackets };