@woosh/meep-engine 2.138.0 → 2.138.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/package.json +1 -1
  4. package/src/core/assert.d.ts +6 -0
  5. package/src/core/assert.d.ts.map +1 -1
  6. package/src/core/assert.js +16 -3
  7. package/src/core/binary/half_to_float_uint16.js +1 -1
  8. package/src/core/binary/to_half_float_uint16.d.ts.map +1 -1
  9. package/src/core/binary/to_half_float_uint16.js +9 -4
  10. package/src/core/collection/table/RowFirstTableSpec.js +1 -1
  11. package/src/core/events/signal/Signal.d.ts.map +1 -1
  12. package/src/core/events/signal/Signal.js +53 -0
  13. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts +3 -3
  14. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.js +3 -3
  15. package/src/engine/Clock.d.ts +2 -2
  16. package/src/engine/Clock.js +2 -2
  17. package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.d.ts.map +1 -1
  18. package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.js +17 -29
  19. package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.d.ts.map +1 -1
  20. package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.js +18 -31
  21. package/src/engine/network/NetworkSession.d.ts +386 -0
  22. package/src/engine/network/NetworkSession.d.ts.map +1 -0
  23. package/src/engine/network/NetworkSession.js +1841 -0
  24. package/src/engine/network/PriorityFetch.d.ts.map +1 -1
  25. package/src/engine/network/PriorityFetch.js +3 -2
  26. package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts +14 -0
  27. package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts.map +1 -0
  28. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +44 -0
  29. package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts +18 -0
  30. package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts.map +1 -0
  31. package/src/engine/network/adapters/TransformInterpolationAdapter.js +79 -0
  32. package/src/engine/network/adapters/TransformReplicationAdapter.d.ts +37 -0
  33. package/src/engine/network/adapters/TransformReplicationAdapter.d.ts.map +1 -0
  34. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -0
  35. package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts +18 -0
  36. package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts.map +1 -0
  37. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -0
  38. package/src/engine/network/convertPathToURL.js +107 -107
  39. package/src/engine/network/core/quantize/quantize_float.d.ts +54 -0
  40. package/src/engine/network/core/quantize/quantize_float.d.ts.map +1 -0
  41. package/src/engine/network/core/quantize/quantize_float.js +66 -0
  42. package/src/engine/network/core/quantize/quantize_position.d.ts +44 -0
  43. package/src/engine/network/core/quantize/quantize_position.d.ts.map +1 -0
  44. package/src/engine/network/core/quantize/quantize_position.js +54 -0
  45. package/src/engine/network/core/sequence/ack_bitfield.d.ts +47 -0
  46. package/src/engine/network/core/sequence/ack_bitfield.d.ts.map +1 -0
  47. package/src/engine/network/core/sequence/ack_bitfield.js +77 -0
  48. package/src/engine/network/core/sequence/seq16.d.ts +53 -0
  49. package/src/engine/network/core/sequence/seq16.d.ts.map +1 -0
  50. package/src/engine/network/core/sequence/seq16.js +69 -0
  51. package/src/engine/network/core/sequence/seq32.d.ts +55 -0
  52. package/src/engine/network/core/sequence/seq32.d.ts.map +1 -0
  53. package/src/engine/network/core/sequence/seq32.js +73 -0
  54. package/src/engine/network/diagnostics/BandwidthMeter.d.ts +76 -0
  55. package/src/engine/network/diagnostics/BandwidthMeter.d.ts.map +1 -0
  56. package/src/engine/network/diagnostics/BandwidthMeter.js +155 -0
  57. package/src/engine/network/diagnostics/ReplayLog.d.ts +74 -0
  58. package/src/engine/network/diagnostics/ReplayLog.d.ts.map +1 -0
  59. package/src/engine/network/diagnostics/ReplayLog.js +137 -0
  60. package/src/engine/network/diagnostics/SyncTest.d.ts +74 -0
  61. package/src/engine/network/diagnostics/SyncTest.d.ts.map +1 -0
  62. package/src/engine/network/diagnostics/SyncTest.js +151 -0
  63. package/src/engine/network/ecs/NetworkSystem.d.ts +57 -0
  64. package/src/engine/network/ecs/NetworkSystem.d.ts.map +1 -0
  65. package/src/engine/network/ecs/NetworkSystem.js +84 -0
  66. package/src/engine/network/ecs/components/NetworkIdentity.d.ts +58 -0
  67. package/src/engine/network/ecs/components/NetworkIdentity.d.ts.map +1 -0
  68. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -0
  69. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.d.ts +40 -0
  70. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.d.ts.map +1 -0
  71. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -0
  72. package/src/engine/network/orchestrator/NetworkPeer.d.ts +389 -0
  73. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -0
  74. package/src/engine/network/orchestrator/NetworkPeer.js +1107 -0
  75. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +260 -0
  76. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -0
  77. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +425 -0
  78. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +217 -0
  79. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -0
  80. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +562 -0
  81. package/src/engine/network/replication/Replicator.d.ts +134 -0
  82. package/src/engine/network/replication/Replicator.d.ts.map +1 -0
  83. package/src/engine/network/replication/Replicator.js +334 -0
  84. package/src/engine/network/replication/ScopeFilter.d.ts +64 -0
  85. package/src/engine/network/replication/ScopeFilter.d.ts.map +1 -0
  86. package/src/engine/network/replication/ScopeFilter.js +71 -0
  87. package/src/engine/network/sim/ActionLog.d.ts +94 -0
  88. package/src/engine/network/sim/ActionLog.d.ts.map +1 -0
  89. package/src/engine/network/sim/ActionLog.js +189 -0
  90. package/src/engine/network/sim/BinaryInterpolationAdapter.d.ts +58 -0
  91. package/src/engine/network/sim/BinaryInterpolationAdapter.d.ts.map +1 -0
  92. package/src/engine/network/sim/BinaryInterpolationAdapter.js +56 -0
  93. package/src/engine/network/sim/InterpolationLog.d.ts +165 -0
  94. package/src/engine/network/sim/InterpolationLog.d.ts.map +1 -0
  95. package/src/engine/network/sim/InterpolationLog.js +583 -0
  96. package/src/engine/network/sim/ReplicatedComponentRegistry.d.ts +59 -0
  97. package/src/engine/network/sim/ReplicatedComponentRegistry.d.ts.map +1 -0
  98. package/src/engine/network/sim/ReplicatedComponentRegistry.js +140 -0
  99. package/src/engine/network/sim/RewindEngine.d.ts +66 -0
  100. package/src/engine/network/sim/RewindEngine.d.ts.map +1 -0
  101. package/src/engine/network/sim/RewindEngine.js +182 -0
  102. package/src/engine/network/sim/SimAction.d.ts +133 -0
  103. package/src/engine/network/sim/SimAction.d.ts.map +1 -0
  104. package/src/engine/network/sim/SimAction.js +273 -0
  105. package/src/engine/network/sim/SimActionExecutor.d.ts +109 -0
  106. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -0
  107. package/src/engine/network/sim/SimActionExecutor.js +238 -0
  108. package/src/engine/network/sim/SimActionRegistry.d.ts +60 -0
  109. package/src/engine/network/sim/SimActionRegistry.d.ts.map +1 -0
  110. package/src/engine/network/sim/SimActionRegistry.js +128 -0
  111. package/src/engine/network/sim/SmoothingState.d.ts +87 -0
  112. package/src/engine/network/sim/SmoothingState.d.ts.map +1 -0
  113. package/src/engine/network/sim/SmoothingState.js +223 -0
  114. package/src/engine/network/sim/Snapshotter.d.ts +98 -0
  115. package/src/engine/network/sim/Snapshotter.d.ts.map +1 -0
  116. package/src/engine/network/sim/Snapshotter.js +206 -0
  117. package/src/engine/network/sim/SpeculationLog.d.ts +53 -0
  118. package/src/engine/network/sim/SpeculationLog.d.ts.map +1 -0
  119. package/src/engine/network/sim/SpeculationLog.js +84 -0
  120. package/src/engine/network/state/Baseline.d.ts +48 -0
  121. package/src/engine/network/state/Baseline.d.ts.map +1 -0
  122. package/src/engine/network/state/Baseline.js +83 -0
  123. package/src/engine/network/state/ChangedEntitySet.d.ts +94 -0
  124. package/src/engine/network/state/ChangedEntitySet.d.ts.map +1 -0
  125. package/src/engine/network/state/ChangedEntitySet.js +256 -0
  126. package/src/engine/network/state/InputRing.d.ts +90 -0
  127. package/src/engine/network/state/InputRing.d.ts.map +1 -0
  128. package/src/engine/network/state/InputRing.js +173 -0
  129. package/src/engine/network/state/MutationLedger.d.ts +82 -0
  130. package/src/engine/network/state/MutationLedger.d.ts.map +1 -0
  131. package/src/engine/network/state/MutationLedger.js +182 -0
  132. package/src/engine/network/state/PriorityAccumulator.d.ts +104 -0
  133. package/src/engine/network/state/PriorityAccumulator.d.ts.map +1 -0
  134. package/src/engine/network/state/PriorityAccumulator.js +180 -0
  135. package/src/engine/network/state/ReplicationSlotTable.d.ts +78 -0
  136. package/src/engine/network/state/ReplicationSlotTable.d.ts.map +1 -0
  137. package/src/engine/network/state/ReplicationSlotTable.js +211 -0
  138. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +128 -0
  139. package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -0
  140. package/src/engine/network/time/AdaptiveRenderDelay.js +258 -0
  141. package/src/engine/network/time/JitterBuffer.d.ts +58 -0
  142. package/src/engine/network/time/JitterBuffer.d.ts.map +1 -0
  143. package/src/engine/network/time/JitterBuffer.js +116 -0
  144. package/src/engine/network/time/TimeDilation.d.ts +49 -0
  145. package/src/engine/network/time/TimeDilation.d.ts.map +1 -0
  146. package/src/engine/network/time/TimeDilation.js +62 -0
  147. package/src/engine/network/time/TimeSync.d.ts +68 -0
  148. package/src/engine/network/time/TimeSync.d.ts.map +1 -0
  149. package/src/engine/network/time/TimeSync.js +153 -0
  150. package/src/engine/network/transport/Channel.d.ts +74 -0
  151. package/src/engine/network/transport/Channel.d.ts.map +1 -0
  152. package/src/engine/network/transport/Channel.js +272 -0
  153. package/src/engine/network/transport/LoopbackTransport.d.ts +59 -0
  154. package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -0
  155. package/src/engine/network/transport/LoopbackTransport.js +194 -0
  156. package/src/engine/network/transport/ReliableCommandPipeline.d.ts +139 -0
  157. package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +1 -0
  158. package/src/engine/network/transport/ReliableCommandPipeline.js +291 -0
  159. package/src/engine/network/transport/Transport.d.ts +109 -0
  160. package/src/engine/network/transport/Transport.d.ts.map +1 -0
  161. package/src/engine/network/transport/Transport.js +119 -0
  162. package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts +60 -0
  163. package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -0
  164. package/src/engine/network/transport/adapters/NodeUDPTransport.js +206 -0
  165. package/src/engine/network/transport/adapters/SimulatedTransport.d.ts +110 -0
  166. package/src/engine/network/transport/adapters/SimulatedTransport.d.ts.map +1 -0
  167. package/src/engine/network/transport/adapters/SimulatedTransport.js +252 -0
  168. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts +33 -0
  169. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -0
  170. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +131 -0
  171. package/src/engine/network/transport/adapters/WebSocketTransport.d.ts +49 -0
  172. package/src/engine/network/transport/adapters/WebSocketTransport.d.ts.map +1 -0
  173. package/src/engine/network/transport/adapters/WebSocketTransport.js +180 -0
  174. package/src/engine/network/transport/adapters/WebTransportTransport.d.ts +73 -0
  175. package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -0
  176. package/src/engine/network/transport/adapters/WebTransportTransport.js +210 -0
  177. package/src/engine/network/transport/fragments/FragmentAssembler.d.ts +104 -0
  178. package/src/engine/network/transport/fragments/FragmentAssembler.d.ts.map +1 -0
  179. package/src/engine/network/transport/fragments/FragmentAssembler.js +291 -0
  180. package/src/engine/network/transport/fragments/FragmentRetention.d.ts +103 -0
  181. package/src/engine/network/transport/fragments/FragmentRetention.d.ts.map +1 -0
  182. package/src/engine/network/transport/fragments/FragmentRetention.js +194 -0
  183. package/src/engine/network/transport/fragments/fragment_send.d.ts +53 -0
  184. package/src/engine/network/transport/fragments/fragment_send.d.ts.map +1 -0
  185. package/src/engine/network/transport/fragments/fragment_send.js +147 -0
  186. package/src/engine/network/transport/fragments/packet_size.d.ts +93 -0
  187. package/src/engine/network/transport/fragments/packet_size.d.ts.map +1 -0
  188. package/src/engine/network/transport/fragments/packet_size.js +101 -0
  189. package/src/engine/network/xhr.js +23 -23
  190. package/src/engine/simulation/Ticker.d.ts +7 -0
  191. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  192. package/src/engine/simulation/Ticker.js +15 -4
  193. package/src/engine/network/DataChannel.js +0 -1210
  194. package/src/engine/network/RemoteController.d.ts +0 -23
  195. package/src/engine/network/RemoteController.d.ts.map +0 -1
  196. package/src/engine/network/RemoteController.js +0 -114
  197. package/src/engine/network/remoteEditor.d.ts +0 -2
  198. package/src/engine/network/remoteEditor.d.ts.map +0 -1
  199. package/src/engine/network/remoteEditor.js +0 -142
@@ -0,0 +1,189 @@
1
+ import { assert } from "../../../core/assert.js";
2
+ import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
3
+
4
+ /**
5
+ * Per-frame ring of action records.
6
+ *
7
+ * Each frame's `BinaryBuffer` holds a sequence of action records. One record per
8
+ * `SimActionExecutor.execute` call:
9
+ *
10
+ * ```
11
+ * varint: prior_state_count
12
+ * loop:
13
+ * varint: entity_id
14
+ * uint8: component_type_id (assigned by the ReplicatedComponentRegistry)
15
+ * uint32: prior_payload_len
16
+ * bytes: prior_payload (adapter.serialize of the component's prior state)
17
+ * uint8: action_type_id
18
+ * uint8: sender_id (peer that originated the action; local-only,
19
+ * STRIPPED by Replicator before send)
20
+ * uint32: action_payload_len
21
+ * bytes: action_payload (the action's own serialize output)
22
+ * ```
23
+ *
24
+ * Self-describing: records can be skipped without consulting the action registry,
25
+ * which means rewind code can walk records forward to find boundaries, then
26
+ * iterate backward to apply prior states — no need to instantiate any actions.
27
+ *
28
+ * Note that `sender_id` is recorded in-buffer for local rollback orchestrators
29
+ * (stable-sort tie-breaking by sender on replay) but never crosses the wire —
30
+ * {@link Replicator#pack_for_peer} strips it and the receiver derives sender
31
+ * from the inbound packet's peer_id, so a hostile peer cannot impersonate.
32
+ *
33
+ * Ring depth is set at construction. When the ring fills, the oldest frame's
34
+ * buffer is recycled for the new frame.
35
+ *
36
+ * @author Alex Goldring
37
+ * @copyright Company Named Limited (c) 2025
38
+ */
39
+ export class ActionLog {
40
+ #buffers;
41
+ #frame_numbers;
42
+ #write_ends;
43
+ #current_frame;
44
+
45
+
46
+ /**
47
+ * @param {{ frame_capacity: number, initial_buffer_size?: number }} options
48
+ */
49
+ constructor({ frame_capacity, initial_buffer_size = 4096 }) {
50
+ if (!Number.isInteger(frame_capacity) || frame_capacity <= 0) {
51
+ throw new Error(`ActionLog: frame_capacity must be a positive integer, got ${frame_capacity}`);
52
+ }
53
+
54
+ /**
55
+ * @readonly
56
+ * @type {number}
57
+ */
58
+ this.frame_capacity = frame_capacity;
59
+
60
+ /**
61
+ * Per-frame buffers. Index by `frame % frame_capacity`.
62
+ * @type {BinaryBuffer[]}
63
+ * @private
64
+ */
65
+ this.#buffers = new Array(frame_capacity);
66
+
67
+ /**
68
+ * Per-frame absolute frame numbers (so we can detect "this slot is stale").
69
+ * `-1` means the slot has not yet been used.
70
+ * @type {Int32Array}
71
+ * @private
72
+ */
73
+ this.#frame_numbers = new Int32Array(frame_capacity).fill(-1);
74
+
75
+ /**
76
+ * Per-frame "write end" position. The buffer's own `position` is reused
77
+ * when actively writing; this is captured at frame_end so readers know
78
+ * where the meaningful data ends.
79
+ * @type {Int32Array}
80
+ * @private
81
+ */
82
+ this.#write_ends = new Int32Array(frame_capacity);
83
+
84
+ for (let i = 0; i < frame_capacity; i++) {
85
+ this.#buffers[i] = new BinaryBuffer();
86
+ this.#buffers[i].setCapacity(initial_buffer_size);
87
+ }
88
+
89
+ /**
90
+ * Frame number currently being written to, or -1 if no frame is open.
91
+ * @type {number}
92
+ * @private
93
+ */
94
+ this.#current_frame = -1;
95
+ }
96
+
97
+ /**
98
+ * Open a new frame for writing. Recycles the oldest slot if the ring is full.
99
+ *
100
+ * @param {number} frame absolute frame number
101
+ */
102
+ begin_frame(frame) {
103
+ assert.isNonNegativeInteger(frame, 'frame');
104
+
105
+ if (this.#current_frame !== -1) {
106
+ throw new Error(`ActionLog.begin_frame: previous frame ${this.#current_frame} still open; call end_frame first`);
107
+ }
108
+
109
+ const slot = frame % this.frame_capacity;
110
+ const buffer = this.#buffers[slot];
111
+
112
+ buffer.position = 0;
113
+ this.#frame_numbers[slot] = frame;
114
+ this.#current_frame = frame;
115
+ }
116
+
117
+ /**
118
+ * Close the currently-open frame.
119
+ */
120
+ end_frame() {
121
+ if (this.#current_frame === -1) {
122
+ throw new Error(`ActionLog.end_frame: no frame is open`);
123
+ }
124
+ const slot = this.#current_frame % this.frame_capacity;
125
+ this.#write_ends[slot] = this.#buffers[slot].position;
126
+ this.#current_frame = -1;
127
+ }
128
+
129
+ /**
130
+ * Get the buffer for the currently-open frame for direct writing.
131
+ *
132
+ * @returns {BinaryBuffer}
133
+ */
134
+ current_buffer() {
135
+ if (this.#current_frame === -1) {
136
+ throw new Error(`ActionLog.current_buffer: no frame is open`);
137
+ }
138
+ return this.#buffers[this.#current_frame % this.frame_capacity];
139
+ }
140
+
141
+ /**
142
+ * Has the given frame number ever been written, and is it still in the ring?
143
+ *
144
+ * @param {number} frame
145
+ * @returns {boolean}
146
+ */
147
+ has_frame(frame) {
148
+ assert.isNonNegativeInteger(frame, 'frame');
149
+ const slot = frame % this.frame_capacity;
150
+ return this.#frame_numbers[slot] === frame;
151
+ }
152
+
153
+ /**
154
+ * Read-only access to a closed frame's buffer. Throws if the frame is not in the ring.
155
+ * The buffer's `position` will be set to 0 and its valid byte length is `write_end_for(frame)`.
156
+ *
157
+ * **Only valid for frames that have been closed via {@link end_frame}.** While a
158
+ * frame is open, `__write_ends[slot]` still holds the previous occupant's
159
+ * length — `buffer_for`/`write_end_for` would return mismatched
160
+ * buffer-contents-vs-length and any reader would walk garbage.
161
+ *
162
+ * @param {number} frame
163
+ * @returns {BinaryBuffer}
164
+ */
165
+ buffer_for(frame) {
166
+ assert.isNonNegativeInteger(frame, 'frame');
167
+ if (!this.has_frame(frame)) {
168
+ throw new Error(`ActionLog.buffer_for: frame ${frame} is not present in the ring`);
169
+ }
170
+ const slot = frame % this.frame_capacity;
171
+ const buffer = this.#buffers[slot];
172
+ buffer.position = 0;
173
+ return buffer;
174
+ }
175
+
176
+ /**
177
+ * Number of valid bytes written to the given frame's buffer.
178
+ * @param {number} frame
179
+ * @returns {number}
180
+ */
181
+ write_end_for(frame) {
182
+ assert.isNonNegativeInteger(frame, 'frame');
183
+ if (!this.has_frame(frame)) {
184
+ throw new Error(`ActionLog.write_end_for: frame ${frame} is not present in the ring`);
185
+ }
186
+ const slot = frame % this.frame_capacity;
187
+ return this.#write_ends[slot];
188
+ }
189
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The blend math an adapter performs. Read by higher-level wiring to
3
+ * decide whether the adapter is compatible with the current rendering
4
+ * pipeline.
5
+ */
6
+ export type InterpolationKind = number;
7
+ /**
8
+ * The blend math an adapter performs. Read by higher-level wiring to
9
+ * decide whether the adapter is compatible with the current rendering
10
+ * pipeline.
11
+ *
12
+ * @readonly
13
+ * @enum {number}
14
+ */
15
+ export const InterpolationKind: Readonly<{
16
+ /** No blending — output is one of the two snapshots exactly. */
17
+ Discrete: 0;
18
+ /** Linear blend at fractional `t ∈ [0, 1]` between two snapshots. */
19
+ Linear: 1;
20
+ /** Cubic between four samples. Reserved; not yet supported. */
21
+ Cubic: 2;
22
+ }>;
23
+ /**
24
+ * Per-component-type interpolator: reads two encoded snapshots of one
25
+ * component from `source`, blends by `t`, writes the result to
26
+ * `out_buffer` in the SAME wire format so the receiver can deserialize
27
+ * directly via the corresponding `BinaryClassSerializationAdapter`.
28
+ *
29
+ * Pair with {@link InterpolationLog}, which resolves
30
+ * `(network_id, type_id, tick) → byte offset` so the adapter only sees
31
+ * offsets.
32
+ *
33
+ * Subclasses override `kind` if their blend math is non-linear; the
34
+ * default is `Linear`.
35
+ *
36
+ * @author Alex Goldring
37
+ * @copyright Company Named Limited (c) 2025
38
+ */
39
+ export class BinaryInterpolationAdapter {
40
+ /** @type {number} one of {@link InterpolationKind} */
41
+ kind: number;
42
+ /**
43
+ * Advance `out_buffer.position` past the bytes written. `source.position`
44
+ * may be mutated freely (the log restores it).
45
+ *
46
+ * `first_offset === second_offset` is the degenerate "snap to single
47
+ * snapshot" case — implementations don't need to special-case it; the
48
+ * blend at any `t` reduces to the input.
49
+ *
50
+ * @param {BinaryBuffer} out_buffer
51
+ * @param {BinaryBuffer} source
52
+ * @param {number} first_offset byte position of snapshot A
53
+ * @param {number} second_offset byte position of snapshot B
54
+ * @param {number} t blend fraction in [0, 1]; 0 ⇒ A, 1 ⇒ B
55
+ */
56
+ interpolate(out_buffer: BinaryBuffer, source: BinaryBuffer, first_offset: number, second_offset: number, t: number): void;
57
+ }
58
+ //# sourceMappingURL=BinaryInterpolationAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryInterpolationAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/sim/BinaryInterpolationAdapter.js"],"names":[],"mappings":";;;;;gCAMU,MAAM;AANhB;;;;;;;GAOG;AACH;IACI,gEAAgE;;IAEhE,qEAAqE;;IAErE,+DAA+D;;GAEhE;AAEH;;;;;;;;;;;;;;;GAeG;AACH;IAEI,sDAAsD;IACtD,MADW,MAAM,CACe;IAEhC;;;;;;;;;;;;;OAaG;IACH,0EAJW,MAAM,iBACN,MAAM,KACN,MAAM,QAIhB;CACJ"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The blend math an adapter performs. Read by higher-level wiring to
3
+ * decide whether the adapter is compatible with the current rendering
4
+ * pipeline.
5
+ *
6
+ * @readonly
7
+ * @enum {number}
8
+ */
9
+ export const InterpolationKind = Object.freeze({
10
+ /** No blending — output is one of the two snapshots exactly. */
11
+ Discrete: 0,
12
+ /** Linear blend at fractional `t ∈ [0, 1]` between two snapshots. */
13
+ Linear: 1,
14
+ /** Cubic between four samples. Reserved; not yet supported. */
15
+ Cubic: 2,
16
+ });
17
+
18
+ /**
19
+ * Per-component-type interpolator: reads two encoded snapshots of one
20
+ * component from `source`, blends by `t`, writes the result to
21
+ * `out_buffer` in the SAME wire format so the receiver can deserialize
22
+ * directly via the corresponding `BinaryClassSerializationAdapter`.
23
+ *
24
+ * Pair with {@link InterpolationLog}, which resolves
25
+ * `(network_id, type_id, tick) → byte offset` so the adapter only sees
26
+ * offsets.
27
+ *
28
+ * Subclasses override `kind` if their blend math is non-linear; the
29
+ * default is `Linear`.
30
+ *
31
+ * @author Alex Goldring
32
+ * @copyright Company Named Limited (c) 2025
33
+ */
34
+ export class BinaryInterpolationAdapter {
35
+
36
+ /** @type {number} one of {@link InterpolationKind} */
37
+ kind = InterpolationKind.Linear;
38
+
39
+ /**
40
+ * Advance `out_buffer.position` past the bytes written. `source.position`
41
+ * may be mutated freely (the log restores it).
42
+ *
43
+ * `first_offset === second_offset` is the degenerate "snap to single
44
+ * snapshot" case — implementations don't need to special-case it; the
45
+ * blend at any `t` reduces to the input.
46
+ *
47
+ * @param {BinaryBuffer} out_buffer
48
+ * @param {BinaryBuffer} source
49
+ * @param {number} first_offset byte position of snapshot A
50
+ * @param {number} second_offset byte position of snapshot B
51
+ * @param {number} t blend fraction in [0, 1]; 0 ⇒ A, 1 ⇒ B
52
+ */
53
+ interpolate(out_buffer, source, first_offset, second_offset, t) {
54
+ throw new Error('BinaryInterpolationAdapter subclasses must override interpolate(out, src, off_a, off_b, t).');
55
+ }
56
+ }
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Per-tick recording of replicated component state for snapshot interpolation.
3
+ *
4
+ * Two ring buffers — both wrap at tick boundaries only:
5
+ *
6
+ * - `__buffer` (BinaryBuffer): raw component bytes, written via `begin_record`
7
+ * / `end_record`. Variable size per record.
8
+ *
9
+ * - `__records` (Uint32Array): the metadata table, holding one row per
10
+ * `(network_id, type_id, byte_offset, byte_length)` plus a bloom-filter
11
+ * header every {@link METADATA_PAGE_SIZE} records. The structure:
12
+ *
13
+ * page = [bloom_0..7] [rec_0_n, _t, _o, _l] ... [rec_38_n, _t, _o, _l]
14
+ *
15
+ * A new page header is written at `begin_tick` and then again every 39
16
+ * records within a tick. The bloom filter is keyed by `network_id`, so a
17
+ * `locate(network_id, type_id)` can skip whole pages with a single 256-bit
18
+ * check before falling back to a per-record scan inside the page. Pages
19
+ * never straddle tick boundaries.
20
+ *
21
+ * Per-tick metadata is small: byte range + word range in `__records` + record
22
+ * count. The oldest tick is tracked explicitly (`__oldest_tick`) so the squash
23
+ * check at each {@link begin_tick} is amortized O(1) — squash the oldest while
24
+ * it overlaps the new write region, advance the pointer, repeat.
25
+ *
26
+ * Pair with {@link BinaryInterpolationAdapter} concrete subclasses (e.g.
27
+ * {@link Vector3InterpolationAdapter}) which know each component type's
28
+ * encoding and blend math.
29
+ *
30
+ * Typical receive-side use:
31
+ * ```
32
+ * onFrameApplied(_, frame_number) {
33
+ * log.begin_tick(frame_number);
34
+ * const buf = log.begin_record(network_id, type_id);
35
+ * adapter.serialize(buf, value);
36
+ * log.end_record();
37
+ * log.end_tick();
38
+ * }
39
+ * ```
40
+ *
41
+ * Typical render-time use:
42
+ * ```
43
+ * const ok = log.interpolate(out_buffer, network_id, type_id, tick_a, tick_b, t, adapter);
44
+ * if (ok) { /* deserialize from out_buffer into the live component }
45
+ * ```
46
+ *
47
+ * @author Alex Goldring
48
+ * @copyright Company Named Limited (c) 2025
49
+ */
50
+ export class InterpolationLog {
51
+ /**
52
+ * @param {{ buffer_capacity_bytes?: number, records_capacity?: number }} [options]
53
+ * `records_capacity` is in *records* (not bytes); the underlying word
54
+ * array is sized large enough to fit that many records plus their pages'
55
+ * bloom-filter headers.
56
+ */
57
+ constructor({ buffer_capacity_bytes, records_capacity }?: {
58
+ buffer_capacity_bytes?: number;
59
+ records_capacity?: number;
60
+ });
61
+ /** @readonly @type {number} */
62
+ readonly buffer_capacity: number;
63
+ /** @readonly @type {number} */
64
+ readonly records_capacity: number;
65
+ /**
66
+ * Open a new tick for recording. May wrap either ring at this point — but
67
+ * never mid-tick, so a single tick's data is always contiguous in both
68
+ * the byte buffer and the metadata table. After wrapping, any old tick
69
+ * whose data overlaps the new write region is squashed (in oldest-first
70
+ * order) and `__oldest_tick` advances.
71
+ *
72
+ * @param {number} tick non-negative integer
73
+ */
74
+ begin_tick(tick: number): void;
75
+ /**
76
+ * Begin recording one component. Returns the underlying byte buffer
77
+ * positioned at the next write slot — the caller writes the component
78
+ * payload directly (e.g. via a `BinaryClassSerializationAdapter.serialize`
79
+ * call), then calls {@link end_record} to finalize the (offset, length).
80
+ *
81
+ * Splitting begin/end (vs. taking a write callback) avoids the per-record
82
+ * closure allocation and lets the caller pass the buffer straight to an
83
+ * adapter without wrapping.
84
+ *
85
+ * @param {number} network_id
86
+ * @param {number} type_id component type id (small integer; matches the registry)
87
+ * @returns {BinaryBuffer} the log's byte buffer, positioned for writing the payload
88
+ */
89
+ begin_record(network_id: number, type_id: number): BinaryBuffer;
90
+ /**
91
+ * Finalize the in-progress record opened by {@link begin_record}. Reads
92
+ * the buffer's current position to compute the payload length, inserts
93
+ * the network_id into the current page's bloom filter, writes the row to
94
+ * the metadata table, and advances the cursors.
95
+ */
96
+ end_record(): void;
97
+ /**
98
+ * Close the currently-open tick. Updates the max-observed-tick sizes so
99
+ * the next {@link begin_tick} can size its wrap heuristic correctly.
100
+ *
101
+ * Throws if a record is still open — silently dropping the in-progress
102
+ * record's metadata (offset/length) would leak buffer space and produce
103
+ * stale bytes that no one can locate.
104
+ */
105
+ end_tick(): void;
106
+ /**
107
+ * @param {number} tick
108
+ * @returns {boolean} true if the tick has live (non-squashed) data
109
+ */
110
+ has_tick(tick: number): boolean;
111
+ /**
112
+ * Find a component's stored slice within a tick. Walks the tick's pages,
113
+ * bloom-filter-skipping pages that don't contain `network_id`, and
114
+ * scanning records inside any page where the bloom hits.
115
+ *
116
+ * On success, writes `out[out_offset+0] = byte_offset` and
117
+ * `out[out_offset+1] = byte_length`.
118
+ *
119
+ * @param {number[]|Uint32Array} out
120
+ * @param {number} out_offset
121
+ * @param {number} tick
122
+ * @param {number} network_id
123
+ * @param {number} type_id
124
+ * @returns {boolean} false if the tick is missing/squashed or doesn't carry this component
125
+ */
126
+ locate(out: number[] | Uint32Array, out_offset: number, tick: number, network_id: number, type_id: number): boolean;
127
+ /**
128
+ * Interpolate one component between two ticks via `adapter` and write the
129
+ * result to `out_buffer` at its current position.
130
+ *
131
+ * Outcome by available data:
132
+ * - Both ticks carry the component → adapter blends them at `t`.
133
+ * - Only one carries it → adapter is called with the same offset twice
134
+ * (snap to the surviving snapshot; `t` is irrelevant).
135
+ * - Neither carries it → returns false; `out_buffer` is unchanged.
136
+ *
137
+ * @param {BinaryBuffer} out_buffer
138
+ * @param {number} network_id
139
+ * @param {number} type_id
140
+ * @param {number} tick_a
141
+ * @param {number} tick_b
142
+ * @param {number} t
143
+ * @param {BinaryInterpolationAdapter} adapter
144
+ * @returns {boolean} true if a payload was written; false if neither tick has the component
145
+ */
146
+ interpolate(out_buffer: BinaryBuffer, network_id: number, type_id: number, tick_a: number, tick_b: number, t: number, adapter: BinaryInterpolationAdapter): boolean;
147
+ /**
148
+ * Number of ticks currently held. Squashed ticks are excluded.
149
+ * @returns {number}
150
+ */
151
+ size(): number;
152
+ /**
153
+ * Tick number of the oldest live tick, or -1 if empty.
154
+ * @returns {number}
155
+ */
156
+ oldest_tick(): number;
157
+ /**
158
+ * Drop all recorded ticks. Resets both ring cursors to 0. Useful on
159
+ * reconnect or level transition.
160
+ */
161
+ clear(): void;
162
+ #private;
163
+ }
164
+ import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
165
+ //# sourceMappingURL=InterpolationLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InterpolationLog.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/sim/InterpolationLog.js"],"names":[],"mappings":"AA6EA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH;IAkBI;;;;;OAKG;IACH,0DALW;QAAE,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,EAkGvE;IA9EG,+BAA+B;IAC/B,0BADqB,MAAM,CACiB;IAe5C,+BAA+B;IAC/B,2BADqB,MAAM,CACa;IA+D5C;;;;;;;;OAQG;IACH,iBAFW,MAAM,QAkEhB;IAED;;;;;;;;;;;;;OAaG;IACH,yBAJW,MAAM,WACN,MAAM,GACJ,YAAY,CAmCxB;IAED;;;;;OAKG;IACH,mBAsDC;IAED;;;;;;;OAOG;IACH,iBAeC;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;;;;;;;;OAcG;IACH,YAPW,MAAM,EAAE,GAAC,WAAW,cACpB,MAAM,QACN,MAAM,cACN,MAAM,WACN,MAAM,GACJ,OAAO,CA+BnB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,wBATW,YAAY,cACZ,MAAM,WACN,MAAM,UACN,MAAM,UACN,MAAM,KACN,MAAM,wCAEJ,OAAO,CAuBnB;IAED;;;OAGG;IACH,QAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,eAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,cASC;;CACJ;6BArkB4B,sCAAsC"}