@opsydyn/effect-three-rapier 0.3.0 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.4](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.6.3...effect-three-rapier-v0.6.4) (2026-10-30)
4
+
5
+ ### Miscellaneous Chores
6
+
7
+ - **effect-three-rapier:** Synchronize effect-three versions
8
+
9
+ ## [0.6.3](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.6.2...effect-three-rapier-v0.6.3) (2026-10-29)
10
+
11
+ ### Miscellaneous Chores
12
+
13
+ - **effect-three-rapier:** Synchronize effect-three versions
14
+
15
+ ## [0.6.2](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.6.1...effect-three-rapier-v0.6.2) (2026-10-28)
16
+
17
+ ### Miscellaneous Chores
18
+
19
+ - **effect-three-rapier:** Synchronize effect-three versions
20
+
21
+ ## [0.6.1](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.6.0...effect-three-rapier-v0.6.1) (2026-10-27)
22
+
23
+ ### Miscellaneous Chores
24
+
25
+ - **effect-three-rapier:** Synchronize effect-three versions
26
+
27
+ ## [0.6.0](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.5.0...effect-three-rapier-v0.6.0) (2026-10-21)
28
+
29
+ ### Features
30
+
31
+ - **effect-three-rapier:** snapshots of Rapier worlds, in the page and in a worker ([89a8e32](https://github.com/opsydyn/fold-kit-experiments/commit/89a8e32ac0c23c055100ee9ec1c8349610f998f4))
32
+
33
+ ## [0.5.0](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.4.0...effect-three-rapier-v0.5.0) (2026-10-20)
34
+
35
+ ### Features
36
+
37
+ - **effect-three-rapier:** Rapier in a worker behind the same engine contract ([e30566c](https://github.com/opsydyn/fold-kit-experiments/commit/e30566cf3326cdddf1863d85c36a98034b30ecec))
38
+ - **effect-three-rapier:** Rapier's deterministic build, as its own entry ([21e0020](https://github.com/opsydyn/fold-kit-experiments/commit/21e002012cb6422730c1877a72fc48ca7b46c070))
39
+
40
+ ## [0.4.0](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.3.0...effect-three-rapier-v0.4.0) (2026-10-20)
41
+
42
+ ### Miscellaneous Chores
43
+
44
+ - **effect-three-rapier:** Synchronize effect-three versions
45
+
3
46
  ## [0.3.0](https://github.com/opsydyn/fold-kit-experiments/compare/effect-three-rapier-v0.2.0...effect-three-rapier-v0.3.0) (2026-10-19)
4
47
 
5
48
  ### Miscellaneous Chores
package/README.md CHANGED
@@ -41,3 +41,64 @@ scene({
41
41
 
42
42
  Rapier (`@dimforge/rapier3d-compat`, Apache-2.0) embeds its WebAssembly, so nothing else is
43
43
  fetched; load it only on pages that need physics.
44
+
45
+ ## Deterministic
46
+
47
+ Where peers must get the same world (a lockstep session between machines, a replay shared
48
+ as a link), load Rapier's deterministic build instead: the same engine, bit-identical on
49
+ every platform for the same inputs at the same steps. Install its build alongside (an
50
+ optional peer), and drive the world with `physics({ until })`
51
+ ([ADR-014](../../docs/effect-three/adr/014-physics-in-lockstep.md)):
52
+
53
+ ```sh
54
+ npm install @dimforge/rapier3d-deterministic-compat
55
+ ```
56
+
57
+ ```ts
58
+ import { loadRapier } from '@opsydyn/effect-three-rapier/deterministic';
59
+
60
+ const environment = EffectThreeFoldkit.makeEnvironment(window, { physics: loadRapier() });
61
+ ```
62
+
63
+ The engine is deterministic; what the scene feeds it must agree too. Give every peer the
64
+ same bodies in the same order, and prefer colliders sized as data (`ballCollider`,
65
+ `cuboidCollider`) to ones measured from curved geometry: browsers may round sines and
66
+ cosines differently.
67
+
68
+ ## Snapshots
69
+
70
+ Worlds take snapshots (`physics({ snapshotAt })` reports one) and start from them
71
+ (`physics({ from })`), exactly: a world restored from a snapshot goes on as the one it was
72
+ taken from, bit for bit with the deterministic build. A newcomer to a lockstep session can
73
+ start from the leader's snapshot instead of replaying the game
74
+ ([ADR-018](../../docs/effect-three/adr/018-snapshot-welcome.md)). Snapshots work in a
75
+ worker too; each build restores its own.
76
+
77
+ ## In a worker
78
+
79
+ To keep stepping off the page's thread, run Rapier in a worker behind the same engine
80
+ contract ([ADR-017](../../docs/effect-three/adr/017-physics-in-a-worker.md)). The worker
81
+ serves worlds with either build; the page gets an engine from `remotePhysics`, and does
82
+ not load Rapier's WebAssembly itself:
83
+
84
+ ```ts
85
+ // physics.worker.ts
86
+ import { loadRapier } from '@opsydyn/effect-three-rapier/deterministic';
87
+ import { servePhysics } from '@opsydyn/effect-three-rapier/worker';
88
+
89
+ servePhysics(globalThis, loadRapier());
90
+ ```
91
+
92
+ ```ts
93
+ // the page
94
+ import { remotePhysics } from '@opsydyn/effect-three-rapier/worker';
95
+
96
+ const worker = new Worker(new URL('./physics.worker.ts', import.meta.url), { type: 'module' });
97
+ const environment = EffectThreeFoldkit.makeEnvironment(window, { physics: remotePhysics(worker) });
98
+ ```
99
+
100
+ What the scene graph asks of a world in a frame goes in one message, and the worker
101
+ answers with that frame's collisions and forces and every body's pose. What you see lags
102
+ by about a frame. A world on `physics({ until })` is reported as there once the worker has
103
+ answered everything it was asked, so its checksum is the one an engine in the page gives,
104
+ a frame later; peers in the page and in workers play one session together.
@@ -0,0 +1,7 @@
1
+ import type { PhysicsEngine } from '@opsydyn/effect-three';
2
+ /**
3
+ * Loads the deterministic Rapier build's WebAssembly and returns the engine. Call once
4
+ * per page.
5
+ */
6
+ export declare const loadRapier: () => Promise<PhysicsEngine>;
7
+ //# sourceMappingURL=deterministic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deterministic.d.ts","sourceRoot":"","sources":["../src/deterministic.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,aAAa,CAMxD,CAAC"}
@@ -0,0 +1,387 @@
1
+ // src/deterministic.ts
2
+ import RAPIER from "@dimforge/rapier3d-deterministic-compat";
3
+
4
+ // src/engine.ts
5
+ import { interactionBits } from "@opsydyn/effect-three";
6
+
7
+ // src/snapshot.ts
8
+ var format = 1;
9
+ var encoder = new TextEncoder;
10
+ var decoder = new TextDecoder;
11
+ var writeSnapshot = (index, world) => {
12
+ const parts = [Uint8Array.of(format)];
13
+ const count = (value) => {
14
+ const bytes = new Uint8Array(4);
15
+ new DataView(bytes.buffer).setUint32(0, value, true);
16
+ parts.push(bytes);
17
+ };
18
+ const handle = (value) => {
19
+ const bytes = new Uint8Array(8);
20
+ new DataView(bytes.buffer).setFloat64(0, value, true);
21
+ parts.push(bytes);
22
+ };
23
+ const text = (value) => {
24
+ const bytes = encoder.encode(value);
25
+ count(bytes.length);
26
+ parts.push(bytes);
27
+ };
28
+ count(index.bodies.length);
29
+ for (const body of index.bodies) {
30
+ text(body.key);
31
+ handle(body.handle);
32
+ count(body.colliders.length);
33
+ for (const collider of body.colliders) {
34
+ handle(collider.handle);
35
+ text(collider.part === undefined ? "" : `:${collider.part}`);
36
+ }
37
+ }
38
+ count(index.joints.length);
39
+ for (const joint of index.joints) {
40
+ text(joint.id);
41
+ handle(joint.handle);
42
+ text(joint.a);
43
+ text(joint.b);
44
+ }
45
+ parts.push(world);
46
+ const out = new Uint8Array(parts.reduce((length, part) => length + part.length, 0));
47
+ let at = 0;
48
+ for (const part of parts) {
49
+ out.set(part, at);
50
+ at += part.length;
51
+ }
52
+ return out;
53
+ };
54
+ var readSnapshot = (snapshot) => {
55
+ if (snapshot[0] !== format)
56
+ throw new Error("Not a snapshot of an effect-three Rapier world");
57
+ const view = new DataView(snapshot.buffer, snapshot.byteOffset, snapshot.byteLength);
58
+ let at = 1;
59
+ const count = () => {
60
+ const value = view.getUint32(at, true);
61
+ at += 4;
62
+ return value;
63
+ };
64
+ const handle = () => {
65
+ const value = view.getFloat64(at, true);
66
+ at += 8;
67
+ return value;
68
+ };
69
+ const text = () => {
70
+ const length = count();
71
+ const value = decoder.decode(snapshot.subarray(at, at + length));
72
+ at += length;
73
+ return value;
74
+ };
75
+ function collider() {
76
+ const colliderHandle = handle();
77
+ const part = text();
78
+ return part === "" ? { handle: colliderHandle } : { handle: colliderHandle, part: part.slice(1) };
79
+ }
80
+ function body() {
81
+ const key = text();
82
+ const bodyHandle = handle();
83
+ return { key, handle: bodyHandle, colliders: Array.from({ length: count() }, collider) };
84
+ }
85
+ const bodies = Array.from({ length: count() }, body);
86
+ const joints = Array.from({ length: count() }, () => ({
87
+ id: text(),
88
+ handle: handle(),
89
+ a: text(),
90
+ b: text()
91
+ }));
92
+ return { index: { bodies, joints }, world: snapshot.subarray(at) };
93
+ };
94
+
95
+ // src/engine.ts
96
+ var vector = ([x, y, z]) => ({ x, y, z });
97
+ var rotation = ([x, y, z, w]) => ({ x, y, z, w });
98
+ var bodyType = (rapier, type) => ({
99
+ dynamic: rapier.RigidBodyType.Dynamic,
100
+ fixed: rapier.RigidBodyType.Fixed,
101
+ kinematic: rapier.RigidBodyType.KinematicPositionBased
102
+ })[type];
103
+ var shapeDesc = (rapier, shape) => {
104
+ switch (shape._tag) {
105
+ case "Cuboid":
106
+ return rapier.ColliderDesc.cuboid(...shape.halfExtents);
107
+ case "Ball":
108
+ return rapier.ColliderDesc.ball(shape.radius);
109
+ case "Hull":
110
+ return rapier.ColliderDesc.convexHull(shape.points) ?? rapier.ColliderDesc.ball(0.001);
111
+ case "Capsule":
112
+ return rapier.ColliderDesc.capsule(shape.halfHeight, shape.radius);
113
+ case "Cylinder":
114
+ return rapier.ColliderDesc.cylinder(shape.halfHeight, shape.radius);
115
+ case "Cone":
116
+ return rapier.ColliderDesc.cone(shape.halfHeight, shape.radius);
117
+ case "Trimesh":
118
+ return rapier.ColliderDesc.trimesh(shape.vertices, shape.indices);
119
+ }
120
+ };
121
+ var colliderDesc = (rapier, collider) => shapeDesc(rapier, collider.shape).setTranslation(...collider.translation).setRotation(rotation(collider.rotation));
122
+ var reporting = (rapier, colliders, body) => {
123
+ for (const collider of colliders) {
124
+ if (body.contactForces === null) {
125
+ collider.setActiveEvents(rapier.ActiveEvents.COLLISION_EVENTS);
126
+ continue;
127
+ }
128
+ collider.setActiveEvents(rapier.ActiveEvents.COLLISION_EVENTS | rapier.ActiveEvents.CONTACT_FORCE_EVENTS);
129
+ collider.setContactForceEventThreshold(body.contactForces);
130
+ }
131
+ };
132
+ var surface = (colliders, body) => {
133
+ for (const collider of colliders) {
134
+ collider.setFriction(body.friction);
135
+ collider.setRestitution(body.restitution);
136
+ collider.setSensor(body.sensor);
137
+ if (body.mass === null)
138
+ collider.setDensity(1);
139
+ else
140
+ collider.setMass(body.mass / colliders.length);
141
+ collider.setCollisionGroups(interactionBits(body.collisionGroups));
142
+ collider.setSolverGroups(interactionBits(body.solverGroups));
143
+ }
144
+ };
145
+ var motion = (rapier, rigidBody, body) => {
146
+ rigidBody.setBodyType(bodyType(rapier, body.type), true);
147
+ rigidBody.setLinearDamping(body.linearDamping);
148
+ rigidBody.setAngularDamping(body.angularDamping);
149
+ rigidBody.setGravityScale(body.gravityScale, true);
150
+ rigidBody.enableCcd(body.ccd);
151
+ };
152
+ var limitsOf = (joint) => joint.kind._tag === "Revolute" || joint.kind._tag === "Prismatic" ? joint.kind.limits : null;
153
+ var motorOf = (joint) => joint.kind._tag === "Revolute" || joint.kind._tag === "Prismatic" ? joint.kind.motor : null;
154
+ var drive = (rapier, made, motor) => {
155
+ if (motor !== null && made instanceof rapier.UnitImpulseJoint) {
156
+ made.configureMotor(motor.position, motor.velocity, motor.stiffness, motor.damping);
157
+ }
158
+ };
159
+ var limit = (rapier, made, limits) => {
160
+ if (limits !== null && made instanceof rapier.UnitImpulseJoint)
161
+ made.setLimits(...limits);
162
+ };
163
+ var jointData = (rapier, joint) => {
164
+ const a = vector(joint.anchorA);
165
+ const b = vector(joint.anchorB);
166
+ const { kind } = joint;
167
+ switch (kind._tag) {
168
+ case "Fixed":
169
+ return rapier.JointData.fixed(a, rotation(kind.frameA), b, rotation(kind.frameB));
170
+ case "Spherical":
171
+ return rapier.JointData.spherical(a, b);
172
+ case "Revolute":
173
+ return rapier.JointData.revolute(a, b, vector(kind.axis));
174
+ case "Prismatic":
175
+ return rapier.JointData.prismatic(a, b, vector(kind.axis));
176
+ case "Rope":
177
+ return rapier.JointData.rope(kind.length, a, b);
178
+ case "Spring":
179
+ return rapier.JointData.spring(kind.restLength, kind.stiffness, kind.damping, a, b);
180
+ }
181
+ };
182
+ var pair = (a, b) => ({
183
+ a: a.key,
184
+ b: b.key,
185
+ ...a.part === undefined ? {} : { aPart: a.part },
186
+ ...b.part === undefined ? {} : { bPart: b.part }
187
+ });
188
+ var hostWorld = (rapier) => (world, index = { bodies: [], joints: [] }) => {
189
+ const events = new rapier.EventQueue(true);
190
+ const bodies = new Map(index.bodies.map((body) => [
191
+ body.key,
192
+ {
193
+ rigidBody: world.getRigidBody(body.handle),
194
+ colliders: body.colliders.map((collider) => world.getCollider(collider.handle))
195
+ }
196
+ ]));
197
+ const keysByCollider = new Map(index.bodies.flatMap(({ key, colliders }) => colliders.map(({ handle, part }) => [handle, part === undefined ? { key } : { key, part }])));
198
+ const joints = new Map(index.joints.map(({ id, handle, a, b }) => [
199
+ id,
200
+ { joint: world.getImpulseJoint(handle), a, b }
201
+ ]));
202
+ const add = (key, body, colliders, pose) => {
203
+ const desc = new rapier.RigidBodyDesc(bodyType(rapier, body.type)).setTranslation(...pose.position).setRotation(rotation(pose.quaternion)).setLinvel(...body.linearVelocity).setAngvel(vector(body.angularVelocity)).setLinearDamping(body.linearDamping).setAngularDamping(body.angularDamping).setGravityScale(body.gravityScale).setCcdEnabled(body.ccd);
204
+ const rigidBody = world.createRigidBody(desc);
205
+ const made = colliders.map((collider) => world.createCollider(colliderDesc(rapier, collider), rigidBody));
206
+ surface(made, body);
207
+ reporting(rapier, made, body);
208
+ bodies.set(key, { rigidBody, colliders: made });
209
+ made.forEach((collider, i) => {
210
+ const part = colliders[i]?.part;
211
+ keysByCollider.set(collider.handle, { key, ...part === undefined ? {} : { part } });
212
+ });
213
+ };
214
+ const remove = (key) => {
215
+ const held = bodies.get(key);
216
+ if (held === undefined)
217
+ return;
218
+ for (const collider of held.colliders)
219
+ keysByCollider.delete(collider.handle);
220
+ for (const [id, joined] of joints)
221
+ if (joined.a === key || joined.b === key)
222
+ joints.delete(id);
223
+ world.removeRigidBody(held.rigidBody);
224
+ bodies.delete(key);
225
+ };
226
+ const addJoint = (id, joint, a, b) => {
227
+ const first = bodies.get(a);
228
+ const second = bodies.get(b);
229
+ if (first === undefined || second === undefined)
230
+ return;
231
+ const made = world.createImpulseJoint(jointData(rapier, joint), first.rigidBody, second.rigidBody, true);
232
+ limit(rapier, made, limitsOf(joint));
233
+ drive(rapier, made, motorOf(joint));
234
+ made.setContactsEnabled(joint.contacts);
235
+ joints.set(id, { joint: made, a, b });
236
+ };
237
+ const removeJoint = (id) => {
238
+ const joined = joints.get(id);
239
+ if (joined === undefined)
240
+ return;
241
+ world.removeImpulseJoint(joined.joint, true);
242
+ joints.delete(id);
243
+ };
244
+ const collisionsOf = () => {
245
+ const collisions = [];
246
+ events.drainCollisionEvents((first, second, started) => {
247
+ const a = keysByCollider.get(first);
248
+ const b = keysByCollider.get(second);
249
+ if (a !== undefined && b !== undefined)
250
+ collisions.push({ ...pair(a, b), started });
251
+ });
252
+ return collisions;
253
+ };
254
+ let forces = [];
255
+ function recordForce(event) {
256
+ const a = keysByCollider.get(event.collider1());
257
+ const b = keysByCollider.get(event.collider2());
258
+ if (a === undefined || b === undefined)
259
+ return;
260
+ const total = event.totalForce();
261
+ const direction = event.maxForceDirection();
262
+ forces.push({
263
+ ...pair(a, b),
264
+ totalForce: [total.x, total.y, total.z],
265
+ totalForceMagnitude: event.totalForceMagnitude(),
266
+ maxForceDirection: [direction.x, direction.y, direction.z],
267
+ maxForceMagnitude: event.maxForceMagnitude()
268
+ });
269
+ }
270
+ const drainForces = () => events.drainContactForceEvents(recordForce);
271
+ function indexed(collider) {
272
+ const part = keysByCollider.get(collider.handle)?.part;
273
+ return part === undefined ? { handle: collider.handle } : { handle: collider.handle, part };
274
+ }
275
+ return {
276
+ configure: (physics) => {
277
+ world.gravity = vector(physics.gravity);
278
+ },
279
+ add,
280
+ update: (key, body) => {
281
+ const held = bodies.get(key);
282
+ if (held === undefined)
283
+ return;
284
+ motion(rapier, held.rigidBody, body);
285
+ surface(held.colliders, body);
286
+ reporting(rapier, held.colliders, body);
287
+ },
288
+ teleport: (key, pose) => {
289
+ const held = bodies.get(key);
290
+ if (held === undefined)
291
+ return;
292
+ held.rigidBody.setTranslation(vector(pose.position), true);
293
+ held.rigidBody.setRotation(rotation(pose.quaternion), true);
294
+ held.rigidBody.setLinvel({ x: 0, y: 0, z: 0 }, true);
295
+ held.rigidBody.setAngvel({ x: 0, y: 0, z: 0 }, true);
296
+ },
297
+ moveKinematic: (key, pose) => {
298
+ const held = bodies.get(key);
299
+ if (held === undefined)
300
+ return;
301
+ held.rigidBody.setNextKinematicTranslation(vector(pose.position));
302
+ held.rigidBody.setNextKinematicRotation(rotation(pose.quaternion));
303
+ },
304
+ applyImpulse: (key, impulse) => {
305
+ bodies.get(key)?.rigidBody.applyImpulse(vector(impulse), true);
306
+ },
307
+ remove,
308
+ addJoint,
309
+ removeJoint,
310
+ step: (seconds) => {
311
+ world.timestep = seconds;
312
+ world.step(events);
313
+ drainForces();
314
+ return collisionsOf();
315
+ },
316
+ contactForces: () => {
317
+ const drained = forces;
318
+ forces = [];
319
+ return drained;
320
+ },
321
+ debugLines: () => {
322
+ const { vertices, colors } = world.debugRender();
323
+ return { vertices, colors };
324
+ },
325
+ pose: (key) => {
326
+ const held = bodies.get(key);
327
+ if (held === undefined)
328
+ return;
329
+ const { x, y, z } = held.rigidBody.translation();
330
+ const turn = held.rigidBody.rotation();
331
+ return { position: [x, y, z], quaternion: [turn.x, turn.y, turn.z, turn.w] };
332
+ },
333
+ awake: () => {
334
+ for (const { rigidBody } of bodies.values()) {
335
+ if (rigidBody.isDynamic() && !rigidBody.isSleeping())
336
+ return true;
337
+ }
338
+ return false;
339
+ },
340
+ snapshot: () => writeSnapshot({
341
+ bodies: [...bodies].map(([key, held]) => ({
342
+ key,
343
+ handle: held.rigidBody.handle,
344
+ colliders: held.colliders.map(indexed)
345
+ })),
346
+ joints: [...joints].map(([id, { joint, a, b }]) => ({
347
+ id,
348
+ handle: joint.handle,
349
+ a,
350
+ b
351
+ }))
352
+ }, world.takeSnapshot()),
353
+ dispose: () => {
354
+ bodies.clear();
355
+ keysByCollider.clear();
356
+ joints.clear();
357
+ events.free();
358
+ world.free();
359
+ }
360
+ };
361
+ };
362
+ var engineOf = (rapier) => {
363
+ const host = hostWorld(rapier);
364
+ return {
365
+ createWorld: (initial) => host(new rapier.World(vector(initial.gravity))),
366
+ restoreWorld: (_physics, snapshot) => {
367
+ const { index, world } = readSnapshot(snapshot);
368
+ return {
369
+ world: host(rapier.World.restoreSnapshot(world), index),
370
+ bodies: index.bodies.map((body) => body.key),
371
+ joints: index.joints.map((joint) => joint.id)
372
+ };
373
+ }
374
+ };
375
+ };
376
+
377
+ // src/deterministic.ts
378
+ var loadRapier = async () => {
379
+ await RAPIER.init();
380
+ return engineOf(RAPIER);
381
+ };
382
+ export {
383
+ loadRapier
384
+ };
385
+
386
+ //# debugId=12558C73F1BEA2D564756E2164756E21
387
+ //# sourceMappingURL=deterministic.js.map
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/deterministic.ts", "../src/engine.ts", "../src/snapshot.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Rapier's deterministic build for `@opsydyn/effect-three`: the same engine as the main\n * entry, over `@dimforge/rapier3d-deterministic-compat` (install it alongside), which\n * gives bit-identical results on every platform for the same inputs at the same steps.\n * Use it where peers must agree (ADR-014): a lockstep session between machines, or a\n * replay shared as a link.\n *\n * ```ts\n * import { loadRapier } from '@opsydyn/effect-three-rapier/deterministic';\n * const physics = await loadRapier();\n * ```\n *\n * Determinism covers the engine. What a scene feeds it must agree too: the same bodies,\n * added in the same order, with the same colliders, at the same steps.\n *\n * @module\n */\nimport RAPIER from '@dimforge/rapier3d-deterministic-compat';\nimport type { PhysicsEngine } from '@opsydyn/effect-three';\n\nimport { engineOf, type Rapier } from './engine.ts';\n\n/**\n * Loads the deterministic Rapier build's WebAssembly and returns the engine. Call once\n * per page.\n */\nexport const loadRapier = async (): Promise<PhysicsEngine> => {\n await RAPIER.init();\n // SAFETY: the deterministic build is the same source as `rapier3d-compat` at the same\n // version, built with another feature: the same API, typed by separate declarations\n // that TypeScript keeps apart only by their private fields. The tests run it.\n return engineOf(RAPIER as unknown as Rapier);\n};\n",
6
+ "/**\n * The engine itself, for whichever Rapier build is loaded: the standard one\n * (`@dimforge/rapier3d-compat`, from the package's main entry) or the deterministic one\n * (`/deterministic`). Both have the same API.\n *\n * @module\n */\nimport type RAPIER from '@dimforge/rapier3d-compat';\nimport { interactionBits } from '@opsydyn/effect-three';\nimport type {\n Body,\n BodyPose,\n Collider,\n ColliderShape,\n Collision,\n Physics,\n ContactForce,\n JointLimits,\n JointMotor,\n PhysicsEngine,\n PhysicsJoint,\n PhysicsWorld,\n Vec3,\n} from '@opsydyn/effect-three';\n\nimport { type IndexedBody, readSnapshot, type SnapshotIndex, writeSnapshot } from './snapshot.ts';\n\n/** A loaded Rapier module: either build. */\nexport type Rapier = typeof RAPIER;\n\nconst vector = ([x, y, z]: Vec3) => ({ x, y, z });\n\nconst rotation = ([x, y, z, w]: BodyPose['quaternion']) => ({ x, y, z, w });\n\n/** Body types by our names. Kinematic bodies are position based, as react-three-rapier's default. */\nconst bodyType = (rapier: Rapier, type: Body['type']): RAPIER.RigidBodyType =>\n ({\n dynamic: rapier.RigidBodyType.Dynamic,\n fixed: rapier.RigidBodyType.Fixed,\n kinematic: rapier.RigidBodyType.KinematicPositionBased,\n })[type];\n\n/** The collider description for a shape; a hull Rapier cannot build becomes a small ball. */\nconst shapeDesc = (rapier: Rapier, shape: ColliderShape): RAPIER.ColliderDesc => {\n switch (shape._tag) {\n case 'Cuboid':\n return rapier.ColliderDesc.cuboid(...shape.halfExtents);\n case 'Ball':\n return rapier.ColliderDesc.ball(shape.radius);\n case 'Hull':\n return rapier.ColliderDesc.convexHull(shape.points) ?? rapier.ColliderDesc.ball(1e-3);\n case 'Capsule':\n return rapier.ColliderDesc.capsule(shape.halfHeight, shape.radius);\n case 'Cylinder':\n return rapier.ColliderDesc.cylinder(shape.halfHeight, shape.radius);\n case 'Cone':\n return rapier.ColliderDesc.cone(shape.halfHeight, shape.radius);\n case 'Trimesh':\n return rapier.ColliderDesc.trimesh(shape.vertices, shape.indices);\n }\n};\n\n/** A collider placed in its body. */\nconst colliderDesc = (rapier: Rapier, collider: Collider): RAPIER.ColliderDesc =>\n shapeDesc(rapier, collider.shape)\n .setTranslation(...collider.translation)\n .setRotation(rotation(collider.rotation));\n\n/**\n * The events a body's colliders report: collisions always, contact forces over its\n * threshold when it has one (react-three-rapier's `onContactForce` turns on\n * `CONTACT_FORCE_EVENTS`).\n */\nconst reporting = (rapier: Rapier, colliders: ReadonlyArray<RAPIER.Collider>, body: Body): void => {\n for (const collider of colliders) {\n if (body.contactForces === null) {\n collider.setActiveEvents(rapier.ActiveEvents.COLLISION_EVENTS);\n continue;\n }\n collider.setActiveEvents(\n rapier.ActiveEvents.COLLISION_EVENTS | rapier.ActiveEvents.CONTACT_FORCE_EVENTS,\n );\n collider.setContactForceEventThreshold(body.contactForces);\n }\n};\n\n/**\n * Applies a body's surface and mass settings to its colliders. A given mass is shared\n * among them; otherwise each has density 1.\n */\nconst surface = (colliders: ReadonlyArray<RAPIER.Collider>, body: Body): void => {\n for (const collider of colliders) {\n collider.setFriction(body.friction);\n collider.setRestitution(body.restitution);\n collider.setSensor(body.sensor);\n if (body.mass === null) collider.setDensity(1);\n else collider.setMass(body.mass / colliders.length);\n collider.setCollisionGroups(interactionBits(body.collisionGroups));\n collider.setSolverGroups(interactionBits(body.solverGroups));\n }\n};\n\n/** Applies a body's motion settings. */\nconst motion = (rapier: Rapier, rigidBody: RAPIER.RigidBody, body: Body): void => {\n rigidBody.setBodyType(bodyType(rapier, body.type), true);\n rigidBody.setLinearDamping(body.linearDamping);\n rigidBody.setAngularDamping(body.angularDamping);\n rigidBody.setGravityScale(body.gravityScale, true);\n rigidBody.enableCcd(body.ccd);\n};\n\n/** The limits a joint has, if it is a hinge or slider with limits. */\nconst limitsOf = (joint: PhysicsJoint): JointLimits | null =>\n joint.kind._tag === 'Revolute' || joint.kind._tag === 'Prismatic' ? joint.kind.limits : null;\n\n/** The motor a joint has, if it is a hinge or slider with one. */\nconst motorOf = (joint: PhysicsJoint): JointMotor | null =>\n joint.kind._tag === 'Revolute' || joint.kind._tag === 'Prismatic' ? joint.kind.motor : null;\n\n/** Drives a hinge or slider once made: Rapier's `configureMotor`, set on the joint. */\nconst drive = (rapier: Rapier, made: RAPIER.ImpulseJoint, motor: JointMotor | null): void => {\n if (motor !== null && made instanceof rapier.UnitImpulseJoint) {\n made.configureMotor(motor.position, motor.velocity, motor.stiffness, motor.damping);\n }\n};\n\n/**\n * Limits a hinge or slider once made. React-three-rapier sets them on the joint data, but\n * Rapier's `JointData.intoRaw` (0.21) passes them on for prismatic joints only, so a\n * hinge's would be lost: they are set on the joint instead.\n */\nconst limit = (rapier: Rapier, made: RAPIER.ImpulseJoint, limits: JointLimits | null): void => {\n if (limits !== null && made instanceof rapier.UnitImpulseJoint) made.setLimits(...limits);\n};\n\n/** Rapier's joint data for a joint, anchors in each body's space. */\nconst jointData = (rapier: Rapier, joint: PhysicsJoint): RAPIER.JointData => {\n const a = vector(joint.anchorA);\n const b = vector(joint.anchorB);\n const { kind } = joint;\n switch (kind._tag) {\n case 'Fixed':\n return rapier.JointData.fixed(a, rotation(kind.frameA), b, rotation(kind.frameB));\n case 'Spherical':\n return rapier.JointData.spherical(a, b);\n case 'Revolute':\n return rapier.JointData.revolute(a, b, vector(kind.axis));\n case 'Prismatic':\n return rapier.JointData.prismatic(a, b, vector(kind.axis));\n case 'Rope':\n return rapier.JointData.rope(kind.length, a, b);\n case 'Spring':\n return rapier.JointData.spring(kind.restLength, kind.stiffness, kind.damping, a, b);\n }\n};\n\n/** Which body a collider belongs to, and which part of it, by name. */\ntype Owner = { readonly key: string; readonly part?: string };\n\n/** Two colliders' owners as an event's `a` and `b`, with their parts. */\nconst pair = (a: Owner, b: Owner) => ({\n a: a.key,\n b: b.key,\n ...(a.part === undefined ? {} : { aPart: a.part }),\n ...(b.part === undefined ? {} : { bPart: b.part }),\n});\n\ntype Held = {\n readonly rigidBody: RAPIER.RigidBody;\n readonly colliders: ReadonlyArray<RAPIER.Collider>;\n};\n\ntype Joined = { readonly joint: RAPIER.ImpulseJoint; readonly a: string; readonly b: string };\n\n/**\n * A Rapier world as a `PhysicsWorld`: a new one, or one restored from a snapshot with the\n * index of what it holds.\n */\nconst hostWorld =\n (rapier: Rapier) =>\n (world: RAPIER.World, index: SnapshotIndex = { bodies: [], joints: [] }): PhysicsWorld => {\n const events = new rapier.EventQueue(true);\n const bodies = new Map<string, Held>(\n index.bodies.map((body) => [\n body.key,\n {\n rigidBody: world.getRigidBody(body.handle),\n colliders: body.colliders.map((collider) => world.getCollider(collider.handle)),\n },\n ]),\n );\n /** Each collider's body, and the part of it the collider is (when named). */\n const keysByCollider = new Map<number, Owner>(\n index.bodies.flatMap(({ key, colliders }) =>\n colliders.map(({ handle, part }) => [handle, part === undefined ? { key } : { key, part }]),\n ),\n );\n const joints = new Map<string, Joined>(\n index.joints.map(({ id, handle, a, b }) => [\n id,\n { joint: world.getImpulseJoint(handle), a, b },\n ]),\n );\n\n const add: PhysicsWorld['add'] = (key, body, colliders, pose) => {\n const desc = new rapier.RigidBodyDesc(bodyType(rapier, body.type))\n .setTranslation(...pose.position)\n .setRotation(rotation(pose.quaternion))\n .setLinvel(...body.linearVelocity)\n .setAngvel(vector(body.angularVelocity))\n .setLinearDamping(body.linearDamping)\n .setAngularDamping(body.angularDamping)\n .setGravityScale(body.gravityScale)\n .setCcdEnabled(body.ccd);\n const rigidBody = world.createRigidBody(desc);\n const made = colliders.map((collider) =>\n world.createCollider(colliderDesc(rapier, collider), rigidBody),\n );\n surface(made, body);\n reporting(rapier, made, body);\n bodies.set(key, { rigidBody, colliders: made });\n made.forEach((collider, i) => {\n const part = colliders[i]?.part;\n keysByCollider.set(collider.handle, { key, ...(part === undefined ? {} : { part }) });\n });\n };\n\n const remove: PhysicsWorld['remove'] = (key) => {\n const held = bodies.get(key);\n if (held === undefined) return;\n for (const collider of held.colliders) keysByCollider.delete(collider.handle);\n // Rapier removes the body's joints with it; forget them, as their handles are reused.\n for (const [id, joined] of joints)\n if (joined.a === key || joined.b === key) joints.delete(id);\n world.removeRigidBody(held.rigidBody);\n bodies.delete(key);\n };\n\n const addJoint: PhysicsWorld['addJoint'] = (id, joint, a, b) => {\n const first = bodies.get(a);\n const second = bodies.get(b);\n if (first === undefined || second === undefined) return;\n const made = world.createImpulseJoint(\n jointData(rapier, joint),\n first.rigidBody,\n second.rigidBody,\n true,\n );\n limit(rapier, made, limitsOf(joint));\n drive(rapier, made, motorOf(joint));\n made.setContactsEnabled(joint.contacts);\n joints.set(id, { joint: made, a, b });\n };\n\n const removeJoint: PhysicsWorld['removeJoint'] = (id) => {\n const joined = joints.get(id);\n if (joined === undefined) return;\n world.removeImpulseJoint(joined.joint, true);\n joints.delete(id);\n };\n\n const collisionsOf = (): ReadonlyArray<Collision> => {\n const collisions: Array<Collision> = [];\n events.drainCollisionEvents((first, second, started) => {\n const a = keysByCollider.get(first);\n const b = keysByCollider.get(second);\n if (a !== undefined && b !== undefined) collisions.push({ ...pair(a, b), started });\n });\n return collisions;\n };\n\n /** Contact force events since the last call, kept across steps until asked for. */\n let forces: Array<ContactForce> = [];\n function recordForce(event: RAPIER.TempContactForceEvent): void {\n const a = keysByCollider.get(event.collider1());\n const b = keysByCollider.get(event.collider2());\n if (a === undefined || b === undefined) return;\n const total = event.totalForce();\n const direction = event.maxForceDirection();\n forces.push({\n ...pair(a, b),\n totalForce: [total.x, total.y, total.z],\n totalForceMagnitude: event.totalForceMagnitude(),\n maxForceDirection: [direction.x, direction.y, direction.z],\n maxForceMagnitude: event.maxForceMagnitude(),\n });\n }\n const drainForces = (): void => events.drainContactForceEvents(recordForce);\n\n /** A collider as a snapshot indexes it: its handle, and its part when named. */\n function indexed(collider: RAPIER.Collider): IndexedBody['colliders'][number] {\n const part = keysByCollider.get(collider.handle)?.part;\n return part === undefined ? { handle: collider.handle } : { handle: collider.handle, part };\n }\n\n return {\n configure: (physics) => {\n world.gravity = vector(physics.gravity);\n },\n add,\n update: (key, body) => {\n const held = bodies.get(key);\n if (held === undefined) return;\n motion(rapier, held.rigidBody, body);\n surface(held.colliders, body);\n reporting(rapier, held.colliders, body);\n },\n teleport: (key, pose) => {\n const held = bodies.get(key);\n if (held === undefined) return;\n held.rigidBody.setTranslation(vector(pose.position), true);\n held.rigidBody.setRotation(rotation(pose.quaternion), true);\n held.rigidBody.setLinvel({ x: 0, y: 0, z: 0 }, true);\n held.rigidBody.setAngvel({ x: 0, y: 0, z: 0 }, true);\n },\n moveKinematic: (key, pose) => {\n const held = bodies.get(key);\n if (held === undefined) return;\n held.rigidBody.setNextKinematicTranslation(vector(pose.position));\n held.rigidBody.setNextKinematicRotation(rotation(pose.quaternion));\n },\n applyImpulse: (key, impulse) => {\n bodies.get(key)?.rigidBody.applyImpulse(vector(impulse), true);\n },\n remove,\n addJoint,\n removeJoint,\n step: (seconds) => {\n world.timestep = seconds;\n world.step(events);\n drainForces();\n return collisionsOf();\n },\n contactForces: () => {\n const drained = forces;\n forces = [];\n return drained;\n },\n // react-three-rapier's Debug: Rapier's own line rendering of colliders and joints.\n debugLines: () => {\n const { vertices, colors } = world.debugRender();\n return { vertices, colors };\n },\n pose: (key) => {\n const held = bodies.get(key);\n if (held === undefined) return undefined;\n const { x, y, z } = held.rigidBody.translation();\n const turn = held.rigidBody.rotation();\n return { position: [x, y, z], quaternion: [turn.x, turn.y, turn.z, turn.w] };\n },\n awake: () => {\n for (const { rigidBody } of bodies.values()) {\n if (rigidBody.isDynamic() && !rigidBody.isSleeping()) return true;\n }\n return false;\n },\n // Rapier's world, and which of its bodies, colliders and joints are which.\n snapshot: () =>\n writeSnapshot(\n {\n bodies: [...bodies].map(([key, held]) => ({\n key,\n handle: held.rigidBody.handle,\n colliders: held.colliders.map(indexed),\n })),\n joints: [...joints].map(([id, { joint, a, b }]) => ({\n id,\n handle: joint.handle,\n a,\n b,\n })),\n },\n world.takeSnapshot(),\n ),\n dispose: () => {\n bodies.clear();\n keysByCollider.clear();\n joints.clear();\n events.free();\n world.free();\n },\n };\n };\n\n/** The engine over a loaded Rapier module. */\nexport const engineOf = (rapier: Rapier): PhysicsEngine => {\n const host = hostWorld(rapier);\n return {\n createWorld: (initial: Physics) => host(new rapier.World(vector(initial.gravity))),\n // A snapshot carries its gravity and everything else in Rapier's world.\n restoreWorld: (_physics, snapshot) => {\n const { index, world } = readSnapshot(snapshot);\n return {\n world: host(rapier.World.restoreSnapshot(world), index),\n bodies: index.bodies.map((body) => body.key),\n joints: index.joints.map((joint) => joint.id),\n };\n },\n };\n};\n",
7
+ "/**\n * A snapshot of one of this package's worlds: Rapier's own (`World.takeSnapshot`), and an\n * index of which of its bodies, colliders and joints are which, by the keys the scene\n * graph knows them by. Nothing here needs Rapier, so the page side of a worker\n * (`remotePhysics`) can read the index of a snapshot the worker took.\n *\n * The layout: a format byte; the bodies (each its key, handle, and colliders with their\n * handles and parts); the joints (each its id, handle and bodies); then Rapier's bytes.\n * Counts and string lengths are 32-bit, handles 64-bit floats (Rapier's own numbers),\n * all little-endian.\n *\n * @module\n */\n\n/** A body in a snapshot: its key, Rapier handle, and its colliders'. */\nexport type IndexedBody = {\n readonly key: string;\n readonly handle: number;\n readonly colliders: ReadonlyArray<{ readonly handle: number; readonly part?: string }>;\n};\n\n/** A joint in a snapshot: its id, Rapier handle, and the keys of its bodies. */\nexport type IndexedJoint = {\n readonly id: string;\n readonly handle: number;\n readonly a: string;\n readonly b: string;\n};\n\nexport type SnapshotIndex = {\n readonly bodies: ReadonlyArray<IndexedBody>;\n readonly joints: ReadonlyArray<IndexedJoint>;\n};\n\n/** The format byte this version writes and reads. */\nconst format = 1;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n/** Writes `index` and Rapier's `world` bytes as one snapshot. */\nexport const writeSnapshot = (index: SnapshotIndex, world: Uint8Array): Uint8Array => {\n const parts: Array<Uint8Array> = [Uint8Array.of(format)];\n const count = (value: number): void => {\n const bytes = new Uint8Array(4);\n new DataView(bytes.buffer).setUint32(0, value, true);\n parts.push(bytes);\n };\n const handle = (value: number): void => {\n const bytes = new Uint8Array(8);\n new DataView(bytes.buffer).setFloat64(0, value, true);\n parts.push(bytes);\n };\n const text = (value: string): void => {\n const bytes = encoder.encode(value);\n count(bytes.length);\n parts.push(bytes);\n };\n count(index.bodies.length);\n for (const body of index.bodies) {\n text(body.key);\n handle(body.handle);\n count(body.colliders.length);\n for (const collider of body.colliders) {\n handle(collider.handle);\n // A part is written with a leading mark, so that no part and an empty one differ.\n text(collider.part === undefined ? '' : `:${collider.part}`);\n }\n }\n count(index.joints.length);\n for (const joint of index.joints) {\n text(joint.id);\n handle(joint.handle);\n text(joint.a);\n text(joint.b);\n }\n parts.push(world);\n const out = new Uint8Array(parts.reduce((length, part) => length + part.length, 0));\n let at = 0;\n for (const part of parts) {\n out.set(part, at);\n at += part.length;\n }\n return out;\n};\n\n/** Reads a snapshot written by `writeSnapshot`: its index, and Rapier's bytes. */\nexport const readSnapshot = (\n snapshot: Uint8Array,\n): { readonly index: SnapshotIndex; readonly world: Uint8Array } => {\n if (snapshot[0] !== format) throw new Error('Not a snapshot of an effect-three Rapier world');\n const view = new DataView(snapshot.buffer, snapshot.byteOffset, snapshot.byteLength);\n let at = 1;\n const count = (): number => {\n const value = view.getUint32(at, true);\n at += 4;\n return value;\n };\n const handle = (): number => {\n const value = view.getFloat64(at, true);\n at += 8;\n return value;\n };\n const text = (): string => {\n const length = count();\n const value = decoder.decode(snapshot.subarray(at, at + length));\n at += length;\n return value;\n };\n function collider(): IndexedBody['colliders'][number] {\n const colliderHandle = handle();\n const part = text();\n return part === ''\n ? { handle: colliderHandle }\n : { handle: colliderHandle, part: part.slice(1) };\n }\n function body(): IndexedBody {\n const key = text();\n const bodyHandle = handle();\n return { key, handle: bodyHandle, colliders: Array.from({ length: count() }, collider) };\n }\n const bodies: Array<IndexedBody> = Array.from({ length: count() }, body);\n const joints: Array<IndexedJoint> = Array.from({ length: count() }, () => ({\n id: text(),\n handle: handle(),\n a: text(),\n b: text(),\n }));\n return { index: { bodies, joints }, world: snapshot.subarray(at) };\n};\n"
8
+ ],
9
+ "mappings": ";AAiBA;;;ACTA;;;AC2BA,IAAM,SAAS;AAEf,IAAM,UAAU,IAAI;AACpB,IAAM,UAAU,IAAI;AAGb,IAAM,gBAAgB,CAAC,OAAsB,UAAkC;AAAA,EACpF,MAAM,QAA2B,CAAC,WAAW,GAAG,MAAM,CAAC;AAAA,EACvD,MAAM,QAAQ,CAAC,UAAwB;AAAA,IACrC,MAAM,QAAQ,IAAI,WAAW,CAAC;AAAA,IAC9B,IAAI,SAAS,MAAM,MAAM,EAAE,UAAU,GAAG,OAAO,IAAI;AAAA,IACnD,MAAM,KAAK,KAAK;AAAA;AAAA,EAElB,MAAM,SAAS,CAAC,UAAwB;AAAA,IACtC,MAAM,QAAQ,IAAI,WAAW,CAAC;AAAA,IAC9B,IAAI,SAAS,MAAM,MAAM,EAAE,WAAW,GAAG,OAAO,IAAI;AAAA,IACpD,MAAM,KAAK,KAAK;AAAA;AAAA,EAElB,MAAM,OAAO,CAAC,UAAwB;AAAA,IACpC,MAAM,QAAQ,QAAQ,OAAO,KAAK;AAAA,IAClC,MAAM,MAAM,MAAM;AAAA,IAClB,MAAM,KAAK,KAAK;AAAA;AAAA,EAElB,MAAM,MAAM,OAAO,MAAM;AAAA,EACzB,WAAW,QAAQ,MAAM,QAAQ;AAAA,IAC/B,KAAK,KAAK,GAAG;AAAA,IACb,OAAO,KAAK,MAAM;AAAA,IAClB,MAAM,KAAK,UAAU,MAAM;AAAA,IAC3B,WAAW,YAAY,KAAK,WAAW;AAAA,MACrC,OAAO,SAAS,MAAM;AAAA,MAEtB,KAAK,SAAS,SAAS,YAAY,KAAK,IAAI,SAAS,MAAM;AAAA,IAC7D;AAAA,EACF;AAAA,EACA,MAAM,MAAM,OAAO,MAAM;AAAA,EACzB,WAAW,SAAS,MAAM,QAAQ;AAAA,IAChC,KAAK,MAAM,EAAE;AAAA,IACb,OAAO,MAAM,MAAM;AAAA,IACnB,KAAK,MAAM,CAAC;AAAA,IACZ,KAAK,MAAM,CAAC;AAAA,EACd;AAAA,EACA,MAAM,KAAK,KAAK;AAAA,EAChB,MAAM,MAAM,IAAI,WAAW,MAAM,OAAO,CAAC,QAAQ,SAAS,SAAS,KAAK,QAAQ,CAAC,CAAC;AAAA,EAClF,IAAI,KAAK;AAAA,EACT,WAAW,QAAQ,OAAO;AAAA,IACxB,IAAI,IAAI,MAAM,EAAE;AAAA,IAChB,MAAM,KAAK;AAAA,EACb;AAAA,EACA,OAAO;AAAA;AAIF,IAAM,eAAe,CAC1B,aACkE;AAAA,EAClE,IAAI,SAAS,OAAO;AAAA,IAAQ,MAAM,IAAI,MAAM,gDAAgD;AAAA,EAC5F,MAAM,OAAO,IAAI,SAAS,SAAS,QAAQ,SAAS,YAAY,SAAS,UAAU;AAAA,EACnF,IAAI,KAAK;AAAA,EACT,MAAM,QAAQ,MAAc;AAAA,IAC1B,MAAM,QAAQ,KAAK,UAAU,IAAI,IAAI;AAAA,IACrC,MAAM;AAAA,IACN,OAAO;AAAA;AAAA,EAET,MAAM,SAAS,MAAc;AAAA,IAC3B,MAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AAAA,IACtC,MAAM;AAAA,IACN,OAAO;AAAA;AAAA,EAET,MAAM,OAAO,MAAc;AAAA,IACzB,MAAM,SAAS,MAAM;AAAA,IACrB,MAAM,QAAQ,QAAQ,OAAO,SAAS,SAAS,IAAI,KAAK,MAAM,CAAC;AAAA,IAC/D,MAAM;AAAA,IACN,OAAO;AAAA;AAAA,EAET,SAAS,QAAQ,GAAqC;AAAA,IACpD,MAAM,iBAAiB,OAAO;AAAA,IAC9B,MAAM,OAAO,KAAK;AAAA,IAClB,OAAO,SAAS,KACZ,EAAE,QAAQ,eAAe,IACzB,EAAE,QAAQ,gBAAgB,MAAM,KAAK,MAAM,CAAC,EAAE;AAAA;AAAA,EAEpD,SAAS,IAAI,GAAgB;AAAA,IAC3B,MAAM,MAAM,KAAK;AAAA,IACjB,MAAM,aAAa,OAAO;AAAA,IAC1B,OAAO,EAAE,KAAK,QAAQ,YAAY,WAAW,MAAM,KAAK,EAAE,QAAQ,MAAM,EAAE,GAAG,QAAQ,EAAE;AAAA;AAAA,EAEzF,MAAM,SAA6B,MAAM,KAAK,EAAE,QAAQ,MAAM,EAAE,GAAG,IAAI;AAAA,EACvE,MAAM,SAA8B,MAAM,KAAK,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO;AAAA,IACzE,IAAI,KAAK;AAAA,IACT,QAAQ,OAAO;AAAA,IACf,GAAG,KAAK;AAAA,IACR,GAAG,KAAK;AAAA,EACV,EAAE;AAAA,EACF,OAAO,EAAE,OAAO,EAAE,QAAQ,OAAO,GAAG,OAAO,SAAS,SAAS,EAAE,EAAE;AAAA;;;ADlGnE,IAAM,SAAS,EAAE,GAAG,GAAG,QAAc,EAAE,GAAG,GAAG,EAAE;AAE/C,IAAM,WAAW,EAAE,GAAG,GAAG,GAAG,QAAgC,EAAE,GAAG,GAAG,GAAG,EAAE;AAGzE,IAAM,WAAW,CAAC,QAAgB,UAC/B;AAAA,EACC,SAAS,OAAO,cAAc;AAAA,EAC9B,OAAO,OAAO,cAAc;AAAA,EAC5B,WAAW,OAAO,cAAc;AAClC,GAAG;AAGL,IAAM,YAAY,CAAC,QAAgB,UAA8C;AAAA,EAC/E,QAAQ,MAAM;AAAA,SACP;AAAA,MACH,OAAO,OAAO,aAAa,OAAO,GAAG,MAAM,WAAW;AAAA,SACnD;AAAA,MACH,OAAO,OAAO,aAAa,KAAK,MAAM,MAAM;AAAA,SACzC;AAAA,MACH,OAAO,OAAO,aAAa,WAAW,MAAM,MAAM,KAAK,OAAO,aAAa,KAAK,KAAI;AAAA,SACjF;AAAA,MACH,OAAO,OAAO,aAAa,QAAQ,MAAM,YAAY,MAAM,MAAM;AAAA,SAC9D;AAAA,MACH,OAAO,OAAO,aAAa,SAAS,MAAM,YAAY,MAAM,MAAM;AAAA,SAC/D;AAAA,MACH,OAAO,OAAO,aAAa,KAAK,MAAM,YAAY,MAAM,MAAM;AAAA,SAC3D;AAAA,MACH,OAAO,OAAO,aAAa,QAAQ,MAAM,UAAU,MAAM,OAAO;AAAA;AAAA;AAKtE,IAAM,eAAe,CAAC,QAAgB,aACpC,UAAU,QAAQ,SAAS,KAAK,EAC7B,eAAe,GAAG,SAAS,WAAW,EACtC,YAAY,SAAS,SAAS,QAAQ,CAAC;AAO5C,IAAM,YAAY,CAAC,QAAgB,WAA2C,SAAqB;AAAA,EACjG,WAAW,YAAY,WAAW;AAAA,IAChC,IAAI,KAAK,kBAAkB,MAAM;AAAA,MAC/B,SAAS,gBAAgB,OAAO,aAAa,gBAAgB;AAAA,MAC7D;AAAA,IACF;AAAA,IACA,SAAS,gBACP,OAAO,aAAa,mBAAmB,OAAO,aAAa,oBAC7D;AAAA,IACA,SAAS,8BAA8B,KAAK,aAAa;AAAA,EAC3D;AAAA;AAOF,IAAM,UAAU,CAAC,WAA2C,SAAqB;AAAA,EAC/E,WAAW,YAAY,WAAW;AAAA,IAChC,SAAS,YAAY,KAAK,QAAQ;AAAA,IAClC,SAAS,eAAe,KAAK,WAAW;AAAA,IACxC,SAAS,UAAU,KAAK,MAAM;AAAA,IAC9B,IAAI,KAAK,SAAS;AAAA,MAAM,SAAS,WAAW,CAAC;AAAA,IACxC;AAAA,eAAS,QAAQ,KAAK,OAAO,UAAU,MAAM;AAAA,IAClD,SAAS,mBAAmB,gBAAgB,KAAK,eAAe,CAAC;AAAA,IACjE,SAAS,gBAAgB,gBAAgB,KAAK,YAAY,CAAC;AAAA,EAC7D;AAAA;AAIF,IAAM,SAAS,CAAC,QAAgB,WAA6B,SAAqB;AAAA,EAChF,UAAU,YAAY,SAAS,QAAQ,KAAK,IAAI,GAAG,IAAI;AAAA,EACvD,UAAU,iBAAiB,KAAK,aAAa;AAAA,EAC7C,UAAU,kBAAkB,KAAK,cAAc;AAAA,EAC/C,UAAU,gBAAgB,KAAK,cAAc,IAAI;AAAA,EACjD,UAAU,UAAU,KAAK,GAAG;AAAA;AAI9B,IAAM,WAAW,CAAC,UAChB,MAAM,KAAK,SAAS,cAAc,MAAM,KAAK,SAAS,cAAc,MAAM,KAAK,SAAS;AAG1F,IAAM,UAAU,CAAC,UACf,MAAM,KAAK,SAAS,cAAc,MAAM,KAAK,SAAS,cAAc,MAAM,KAAK,QAAQ;AAGzF,IAAM,QAAQ,CAAC,QAAgB,MAA2B,UAAmC;AAAA,EAC3F,IAAI,UAAU,QAAQ,gBAAgB,OAAO,kBAAkB;AAAA,IAC7D,KAAK,eAAe,MAAM,UAAU,MAAM,UAAU,MAAM,WAAW,MAAM,OAAO;AAAA,EACpF;AAAA;AAQF,IAAM,QAAQ,CAAC,QAAgB,MAA2B,WAAqC;AAAA,EAC7F,IAAI,WAAW,QAAQ,gBAAgB,OAAO;AAAA,IAAkB,KAAK,UAAU,GAAG,MAAM;AAAA;AAI1F,IAAM,YAAY,CAAC,QAAgB,UAA0C;AAAA,EAC3E,MAAM,IAAI,OAAO,MAAM,OAAO;AAAA,EAC9B,MAAM,IAAI,OAAO,MAAM,OAAO;AAAA,EAC9B,QAAQ,SAAS;AAAA,EACjB,QAAQ,KAAK;AAAA,SACN;AAAA,MACH,OAAO,OAAO,UAAU,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,GAAG,SAAS,KAAK,MAAM,CAAC;AAAA,SAC7E;AAAA,MACH,OAAO,OAAO,UAAU,UAAU,GAAG,CAAC;AAAA,SACnC;AAAA,MACH,OAAO,OAAO,UAAU,SAAS,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC;AAAA,SACrD;AAAA,MACH,OAAO,OAAO,UAAU,UAAU,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC;AAAA,SACtD;AAAA,MACH,OAAO,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG,CAAC;AAAA,SAC3C;AAAA,MACH,OAAO,OAAO,UAAU,OAAO,KAAK,YAAY,KAAK,WAAW,KAAK,SAAS,GAAG,CAAC;AAAA;AAAA;AAQxF,IAAM,OAAO,CAAC,GAAU,OAAc;AAAA,EACpC,GAAG,EAAE;AAAA,EACL,GAAG,EAAE;AAAA,KACD,EAAE,SAAS,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,KAC5C,EAAE,SAAS,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK;AAClD;AAaA,IAAM,YACJ,CAAC,WACD,CAAC,OAAqB,QAAuB,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,MAAoB;AAAA,EACxF,MAAM,SAAS,IAAI,OAAO,WAAW,IAAI;AAAA,EACzC,MAAM,SAAS,IAAI,IACjB,MAAM,OAAO,IAAI,CAAC,SAAS;AAAA,IACzB,KAAK;AAAA,IACL;AAAA,MACE,WAAW,MAAM,aAAa,KAAK,MAAM;AAAA,MACzC,WAAW,KAAK,UAAU,IAAI,CAAC,aAAa,MAAM,YAAY,SAAS,MAAM,CAAC;AAAA,IAChF;AAAA,EACF,CAAC,CACH;AAAA,EAEA,MAAM,iBAAiB,IAAI,IACzB,MAAM,OAAO,QAAQ,GAAG,KAAK,gBAC3B,UAAU,IAAI,GAAG,QAAQ,WAAW,CAAC,QAAQ,SAAS,YAAY,EAAE,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC,CAC5F,CACF;AAAA,EACA,MAAM,SAAS,IAAI,IACjB,MAAM,OAAO,IAAI,GAAG,IAAI,QAAQ,GAAG,QAAQ;AAAA,IACzC;AAAA,IACA,EAAE,OAAO,MAAM,gBAAgB,MAAM,GAAG,GAAG,EAAE;AAAA,EAC/C,CAAC,CACH;AAAA,EAEA,MAAM,MAA2B,CAAC,KAAK,MAAM,WAAW,SAAS;AAAA,IAC/D,MAAM,OAAO,IAAI,OAAO,cAAc,SAAS,QAAQ,KAAK,IAAI,CAAC,EAC9D,eAAe,GAAG,KAAK,QAAQ,EAC/B,YAAY,SAAS,KAAK,UAAU,CAAC,EACrC,UAAU,GAAG,KAAK,cAAc,EAChC,UAAU,OAAO,KAAK,eAAe,CAAC,EACtC,iBAAiB,KAAK,aAAa,EACnC,kBAAkB,KAAK,cAAc,EACrC,gBAAgB,KAAK,YAAY,EACjC,cAAc,KAAK,GAAG;AAAA,IACzB,MAAM,YAAY,MAAM,gBAAgB,IAAI;AAAA,IAC5C,MAAM,OAAO,UAAU,IAAI,CAAC,aAC1B,MAAM,eAAe,aAAa,QAAQ,QAAQ,GAAG,SAAS,CAChE;AAAA,IACA,QAAQ,MAAM,IAAI;AAAA,IAClB,UAAU,QAAQ,MAAM,IAAI;AAAA,IAC5B,OAAO,IAAI,KAAK,EAAE,WAAW,WAAW,KAAK,CAAC;AAAA,IAC9C,KAAK,QAAQ,CAAC,UAAU,MAAM;AAAA,MAC5B,MAAM,OAAO,UAAU,IAAI;AAAA,MAC3B,eAAe,IAAI,SAAS,QAAQ,EAAE,QAAS,SAAS,YAAY,CAAC,IAAI,EAAE,KAAK,EAAG,CAAC;AAAA,KACrF;AAAA;AAAA,EAGH,MAAM,SAAiC,CAAC,QAAQ;AAAA,IAC9C,MAAM,OAAO,OAAO,IAAI,GAAG;AAAA,IAC3B,IAAI,SAAS;AAAA,MAAW;AAAA,IACxB,WAAW,YAAY,KAAK;AAAA,MAAW,eAAe,OAAO,SAAS,MAAM;AAAA,IAE5E,YAAY,IAAI,WAAW;AAAA,MACzB,IAAI,OAAO,MAAM,OAAO,OAAO,MAAM;AAAA,QAAK,OAAO,OAAO,EAAE;AAAA,IAC5D,MAAM,gBAAgB,KAAK,SAAS;AAAA,IACpC,OAAO,OAAO,GAAG;AAAA;AAAA,EAGnB,MAAM,WAAqC,CAAC,IAAI,OAAO,GAAG,MAAM;AAAA,IAC9D,MAAM,QAAQ,OAAO,IAAI,CAAC;AAAA,IAC1B,MAAM,SAAS,OAAO,IAAI,CAAC;AAAA,IAC3B,IAAI,UAAU,aAAa,WAAW;AAAA,MAAW;AAAA,IACjD,MAAM,OAAO,MAAM,mBACjB,UAAU,QAAQ,KAAK,GACvB,MAAM,WACN,OAAO,WACP,IACF;AAAA,IACA,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,IACnC,MAAM,QAAQ,MAAM,QAAQ,KAAK,CAAC;AAAA,IAClC,KAAK,mBAAmB,MAAM,QAAQ;AAAA,IACtC,OAAO,IAAI,IAAI,EAAE,OAAO,MAAM,GAAG,EAAE,CAAC;AAAA;AAAA,EAGtC,MAAM,cAA2C,CAAC,OAAO;AAAA,IACvD,MAAM,SAAS,OAAO,IAAI,EAAE;AAAA,IAC5B,IAAI,WAAW;AAAA,MAAW;AAAA,IAC1B,MAAM,mBAAmB,OAAO,OAAO,IAAI;AAAA,IAC3C,OAAO,OAAO,EAAE;AAAA;AAAA,EAGlB,MAAM,eAAe,MAAgC;AAAA,IACnD,MAAM,aAA+B,CAAC;AAAA,IACtC,OAAO,qBAAqB,CAAC,OAAO,QAAQ,YAAY;AAAA,MACtD,MAAM,IAAI,eAAe,IAAI,KAAK;AAAA,MAClC,MAAM,IAAI,eAAe,IAAI,MAAM;AAAA,MACnC,IAAI,MAAM,aAAa,MAAM;AAAA,QAAW,WAAW,KAAK,KAAK,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC;AAAA,KACnF;AAAA,IACD,OAAO;AAAA;AAAA,EAIT,IAAI,SAA8B,CAAC;AAAA,EACnC,SAAS,WAAW,CAAC,OAA2C;AAAA,IAC9D,MAAM,IAAI,eAAe,IAAI,MAAM,UAAU,CAAC;AAAA,IAC9C,MAAM,IAAI,eAAe,IAAI,MAAM,UAAU,CAAC;AAAA,IAC9C,IAAI,MAAM,aAAa,MAAM;AAAA,MAAW;AAAA,IACxC,MAAM,QAAQ,MAAM,WAAW;AAAA,IAC/B,MAAM,YAAY,MAAM,kBAAkB;AAAA,IAC1C,OAAO,KAAK;AAAA,SACP,KAAK,GAAG,CAAC;AAAA,MACZ,YAAY,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAAA,MACtC,qBAAqB,MAAM,oBAAoB;AAAA,MAC/C,mBAAmB,CAAC,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AAAA,MACzD,mBAAmB,MAAM,kBAAkB;AAAA,IAC7C,CAAC;AAAA;AAAA,EAEH,MAAM,cAAc,MAAY,OAAO,wBAAwB,WAAW;AAAA,EAG1E,SAAS,OAAO,CAAC,UAA6D;AAAA,IAC5E,MAAM,OAAO,eAAe,IAAI,SAAS,MAAM,GAAG;AAAA,IAClD,OAAO,SAAS,YAAY,EAAE,QAAQ,SAAS,OAAO,IAAI,EAAE,QAAQ,SAAS,QAAQ,KAAK;AAAA;AAAA,EAG5F,OAAO;AAAA,IACL,WAAW,CAAC,YAAY;AAAA,MACtB,MAAM,UAAU,OAAO,QAAQ,OAAO;AAAA;AAAA,IAExC;AAAA,IACA,QAAQ,CAAC,KAAK,SAAS;AAAA,MACrB,MAAM,OAAO,OAAO,IAAI,GAAG;AAAA,MAC3B,IAAI,SAAS;AAAA,QAAW;AAAA,MACxB,OAAO,QAAQ,KAAK,WAAW,IAAI;AAAA,MACnC,QAAQ,KAAK,WAAW,IAAI;AAAA,MAC5B,UAAU,QAAQ,KAAK,WAAW,IAAI;AAAA;AAAA,IAExC,UAAU,CAAC,KAAK,SAAS;AAAA,MACvB,MAAM,OAAO,OAAO,IAAI,GAAG;AAAA,MAC3B,IAAI,SAAS;AAAA,QAAW;AAAA,MACxB,KAAK,UAAU,eAAe,OAAO,KAAK,QAAQ,GAAG,IAAI;AAAA,MACzD,KAAK,UAAU,YAAY,SAAS,KAAK,UAAU,GAAG,IAAI;AAAA,MAC1D,KAAK,UAAU,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI;AAAA,MACnD,KAAK,UAAU,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI;AAAA;AAAA,IAErD,eAAe,CAAC,KAAK,SAAS;AAAA,MAC5B,MAAM,OAAO,OAAO,IAAI,GAAG;AAAA,MAC3B,IAAI,SAAS;AAAA,QAAW;AAAA,MACxB,KAAK,UAAU,4BAA4B,OAAO,KAAK,QAAQ,CAAC;AAAA,MAChE,KAAK,UAAU,yBAAyB,SAAS,KAAK,UAAU,CAAC;AAAA;AAAA,IAEnE,cAAc,CAAC,KAAK,YAAY;AAAA,MAC9B,OAAO,IAAI,GAAG,GAAG,UAAU,aAAa,OAAO,OAAO,GAAG,IAAI;AAAA;AAAA,IAE/D;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,CAAC,YAAY;AAAA,MACjB,MAAM,WAAW;AAAA,MACjB,MAAM,KAAK,MAAM;AAAA,MACjB,YAAY;AAAA,MACZ,OAAO,aAAa;AAAA;AAAA,IAEtB,eAAe,MAAM;AAAA,MACnB,MAAM,UAAU;AAAA,MAChB,SAAS,CAAC;AAAA,MACV,OAAO;AAAA;AAAA,IAGT,YAAY,MAAM;AAAA,MAChB,QAAQ,UAAU,WAAW,MAAM,YAAY;AAAA,MAC/C,OAAO,EAAE,UAAU,OAAO;AAAA;AAAA,IAE5B,MAAM,CAAC,QAAQ;AAAA,MACb,MAAM,OAAO,OAAO,IAAI,GAAG;AAAA,MAC3B,IAAI,SAAS;AAAA,QAAW;AAAA,MACxB,QAAQ,GAAG,GAAG,MAAM,KAAK,UAAU,YAAY;AAAA,MAC/C,MAAM,OAAO,KAAK,UAAU,SAAS;AAAA,MACrC,OAAO,EAAE,UAAU,CAAC,GAAG,GAAG,CAAC,GAAG,YAAY,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,EAAE;AAAA;AAAA,IAE7E,OAAO,MAAM;AAAA,MACX,aAAa,eAAe,OAAO,OAAO,GAAG;AAAA,QAC3C,IAAI,UAAU,UAAU,KAAK,CAAC,UAAU,WAAW;AAAA,UAAG,OAAO;AAAA,MAC/D;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,UAAU,MACR,cACE;AAAA,MACE,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,WAAW;AAAA,QACxC;AAAA,QACA,QAAQ,KAAK,UAAU;AAAA,QACvB,WAAW,KAAK,UAAU,IAAI,OAAO;AAAA,MACvC,EAAE;AAAA,MACF,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,GAAG,UAAU;AAAA,QAClD;AAAA,QACA,QAAQ,MAAM;AAAA,QACd;AAAA,QACA;AAAA,MACF,EAAE;AAAA,IACJ,GACA,MAAM,aAAa,CACrB;AAAA,IACF,SAAS,MAAM;AAAA,MACb,OAAO,MAAM;AAAA,MACb,eAAe,MAAM;AAAA,MACrB,OAAO,MAAM;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA;AAAA,EAEf;AAAA;AAIG,IAAM,WAAW,CAAC,WAAkC;AAAA,EACzD,MAAM,OAAO,UAAU,MAAM;AAAA,EAC7B,OAAO;AAAA,IACL,aAAa,CAAC,YAAqB,KAAK,IAAI,OAAO,MAAM,OAAO,QAAQ,OAAO,CAAC,CAAC;AAAA,IAEjF,cAAc,CAAC,UAAU,aAAa;AAAA,MACpC,QAAQ,OAAO,UAAU,aAAa,QAAQ;AAAA,MAC9C,OAAO;AAAA,QACL,OAAO,KAAK,OAAO,MAAM,gBAAgB,KAAK,GAAG,KAAK;AAAA,QACtD,QAAQ,MAAM,OAAO,IAAI,CAAC,SAAS,KAAK,GAAG;AAAA,QAC3C,QAAQ,MAAM,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,MAC9C;AAAA;AAAA,EAEJ;AAAA;;;ADpXK,IAAM,aAAa,YAAoC;AAAA,EAC5D,MAAM,OAAO,KAAK;AAAA,EAIlB,OAAO,SAAS,MAA2B;AAAA;",
10
+ "debugId": "12558C73F1BEA2D564756E2164756E21",
11
+ "names": []
12
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The engine itself, for whichever Rapier build is loaded: the standard one
3
+ * (`@dimforge/rapier3d-compat`, from the package's main entry) or the deterministic one
4
+ * (`/deterministic`). Both have the same API.
5
+ *
6
+ * @module
7
+ */
8
+ import type RAPIER from '@dimforge/rapier3d-compat';
9
+ import type { PhysicsEngine } from '@opsydyn/effect-three';
10
+ /** A loaded Rapier module: either build. */
11
+ export type Rapier = typeof RAPIER;
12
+ /** The engine over a loaded Rapier module. */
13
+ export declare const engineOf: (rapier: Rapier) => PhysicsEngine;
14
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,MAAM,MAAM,2BAA2B,CAAC;AAEpD,OAAO,KAAK,EAUV,aAAa,EAId,MAAM,uBAAuB,CAAC;AAI/B,4CAA4C;AAC5C,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC;AAoWnC,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,WAAY,MAAM,KAAG,aAczC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAUV,aAAa,EAId,MAAM,uBAAuB,CAAC;AA0T/B;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,aAAa,CAGxD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,aAAa,CAGxD,CAAC"}