@newkrok/nape-js 3.31.0 → 3.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-263GQ5UK.js +2 -0
- package/dist/chunk-CA2F5ISB.cjs +2 -0
- package/dist/chunk-GPGT7DYQ.js +2 -0
- package/dist/chunk-HQH77APJ.cjs +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +352 -1
- package/dist/index.d.ts +352 -1
- package/dist/index.js +1 -1
- package/dist/replay/index.cjs +2 -0
- package/dist/replay/index.d.cts +266 -0
- package/dist/replay/index.d.ts +266 -0
- package/dist/replay/index.js +2 -0
- package/dist/serialization/index.cjs +1 -1
- package/dist/serialization/index.js +1 -1
- package/llms-full.txt +225 -3
- package/llms.txt +65 -52
- package/package.json +14 -4
- package/dist/chunk-OFVSWS4I.cjs +0 -2
- package/dist/chunk-ZNBQE3PX.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkCA2F5ISB_cjs=require('../chunk-CA2F5ISB.cjs');require('../chunk-HQH77APJ.cjs');var _=class{constructor(t,e={}){this._inputs=[];this._keyframes=[];this._frame=0;this._finished=false;if(t==null)throw new Error("Recorder: space is required");let i=e.keyframeEvery;if(i!=null&&(!Number.isFinite(i)||i<0||(i|0)!==i))throw new Error(`Recorder: keyframeEvery must be a non-negative integer (got ${i})`);this._space=t,this._keyframeEvery=i??60,this._initialSnapshot=chunkCA2F5ISB_cjs.b(t);}get frame(){return this._frame}get finished(){return this._finished}recordFrame(t){if(this._finished)throw new Error("Recorder: cannot record after finish()");if(this._keyframeEvery>0&&this._frame>0&&this._frame%this._keyframeEvery===0&&this._keyframes.push({frame:this._frame,snapshot:chunkCA2F5ISB_cjs.b(this._space)}),t!=null){let e=v(t);this._inputs.push({frame:this._frame,payload:e});}this._frame++;}finish(){return this._finished=true,{version:f,initialSnapshot:this._initialSnapshot,inputs:this._inputs.slice(),keyframes:this._keyframes.slice(),frameCount:this._frame}}},f=1;function v(r){let t=typeof r;return r===null||t==="number"||t==="string"||t==="boolean"?r:JSON.parse(JSON.stringify(r))}var d=class{constructor(t,e=null,i={}){this._space=null;this._frame=0;if(t==null)throw new Error("Player: replay is required");this._replay=t,this._applyInput=e,this._dt=i.dt??1/60,this._velocityIterations=i.velocityIterations??8,this._positionIterations=i.positionIterations??3;}restore(){return this._space=chunkCA2F5ISB_cjs.c(this._replay.initialSnapshot),this._frame=0,this._space}get space(){if(this._space==null)throw new Error("Player: call restore() before reading space");return this._space}get frame(){return this._frame}get frameCount(){return this._replay.frameCount}get finished(){return this._frame>=this._replay.frameCount}get replay(){return this._replay}get applyInput(){return this._applyInput}set applyInput(t){this._applyInput=t;}step(){if(this._space==null)throw new Error("Player: call restore() before step()");if(this._frame>=this._replay.frameCount)throw new Error(`Player: already at end of replay (frame ${this._frame}/${this._replay.frameCount})`);let t=I(this._replay.inputs,this._frame);t!=null&&this._applyInput!=null&&this._applyInput(t.payload,this._space,this._frame),this._space.step(this._dt,this._velocityIterations,this._positionIterations),this._frame++;}stepTo(t){if(!Number.isFinite(t)||t<0||t>this._replay.frameCount)throw new Error(`Player: target frame ${t} out of range [0, ${this._replay.frameCount}]`);if(this._space==null&&this.restore(),t<this._frame){let e=S(this._replay.keyframes,t);e!=null?(this._space=chunkCA2F5ISB_cjs.c(e.snapshot),this._frame=e.frame):this.restore();}for(;this._frame<t;)this.step();}};function I(r,t){let e=0,i=r.length-1;for(;e<=i;){let a=e+i>>>1,o=r[a].frame;if(o===t)return r[a];o<t?e=a+1:i=a-1;}return null}function S(r,t){let e=0,i=r.length-1,a=null;for(;e<=i;){let o=e+i>>>1,n=r[o];n.frame<=t?(a=n,e=o+1):i=o-1;}return a}var R=1380994137,T=new TextEncoder,E=new TextDecoder;function U(r){let t=[];for(let s of r.inputs){let u=JSON.stringify(s.payload);t.push({frame:s.frame,bytes:T.encode(u??"null")});}let e=14+r.initialSnapshot.byteLength;e+=4;for(let s of t)e+=8+s.bytes.byteLength;e+=4;for(let s of r.keyframes)e+=8+s.snapshot.byteLength;let i=new ArrayBuffer(e),a=new DataView(i),o=new Uint8Array(i),n=0;a.setUint32(n,R,false),n+=4,a.setUint16(n,r.version,true),n+=2,a.setUint32(n,r.frameCount,true),n+=4,a.setUint32(n,r.initialSnapshot.byteLength,true),n+=4,o.set(r.initialSnapshot,n),n+=r.initialSnapshot.byteLength,a.setUint32(n,t.length,true),n+=4;for(let s of t)a.setUint32(n,s.frame,true),n+=4,a.setUint32(n,s.bytes.byteLength,true),n+=4,o.set(s.bytes,n),n+=s.bytes.byteLength;a.setUint32(n,r.keyframes.length,true),n+=4;for(let s of r.keyframes)a.setUint32(n,s.frame,true),n+=4,a.setUint32(n,s.snapshot.byteLength,true),n+=4,o.set(s.snapshot,n),n+=s.snapshot.byteLength;return o}function k(r){let t=new DataView(r.buffer,r.byteOffset,r.byteLength),e=0,i=t.getUint32(e,false);if(e+=4,i!==R)throw new Error(`decodeReplay: invalid magic 0x${i.toString(16).padStart(8,"0")} (expected 0x${R.toString(16)})`);let a=t.getUint16(e,true);if(e+=2,a!==f)throw new Error(`decodeReplay: unsupported version ${a} (expected ${f})`);let o=t.getUint32(e,true);e+=4;let n=t.getUint32(e,true);e+=4;let s=r.slice(e,e+n);e+=n;let u=t.getUint32(e,true);e+=4;let b=new Array(u);for(let p=0;p<u;p++){let m=t.getUint32(e,true);e+=4;let l=t.getUint32(e,true);e+=4;let y=E.decode(r.subarray(e,e+l));e+=l,b[p]={frame:m,payload:JSON.parse(y)};}let g=t.getUint32(e,true);e+=4;let w=new Array(g);for(let p=0;p<g;p++){let m=t.getUint32(e,true);e+=4;let l=t.getUint32(e,true);e+=4;let y=r.slice(e,e+l);e+=l,w[p]={frame:m,snapshot:y};}return {version:a,initialSnapshot:s,inputs:b,keyframes:w,frameCount:o}}function A(r){let t=[];return r==null?{ok:false,warnings:["space is null"]}:(r.deterministic||t.push("space.deterministic is false \u2014 replays will drift from the recording. Set space.deterministic = true."),{ok:t.length===0,warnings:t})}exports.Player=d;exports.REPLAY_VERSION=f;exports.Recorder=_;exports.decodeReplay=k;exports.encodeReplay=U;exports.validateDeterministicConfig=A;//# sourceMappingURL=index.cjs.map
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { j as Space } from '../ConvexResult-DTGB_nRO.cjs';
|
|
2
|
+
import '../PhysicsMetrics-QzFDRdGh.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Per-frame callback that translates a user-defined input payload into engine
|
|
6
|
+
* mutations on the supplied {@link Space}. Called by {@link Player} once per
|
|
7
|
+
* frame during playback, BEFORE `space.step()`.
|
|
8
|
+
*
|
|
9
|
+
* The callback receives the payload exactly as supplied to
|
|
10
|
+
* {@link Recorder.recordFrame} during recording — the recorder JSON-clones the
|
|
11
|
+
* payload, so mutations made between frames don't leak into the log.
|
|
12
|
+
*
|
|
13
|
+
* @typeParam T - User input payload type (must be JSON-serializable).
|
|
14
|
+
*/
|
|
15
|
+
type ReplayInputApplier<T> = (input: T, space: Space, frame: number) => void;
|
|
16
|
+
/** Configuration options for {@link Recorder}. */
|
|
17
|
+
interface RecorderOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Capture a full snapshot every N frames in addition to the initial one.
|
|
20
|
+
* Enables fast random-access scrubbing in {@link Player.stepTo}: a backward
|
|
21
|
+
* jump restores the latest keyframe at or before the target frame, then
|
|
22
|
+
* steps forward through the input log.
|
|
23
|
+
*
|
|
24
|
+
* Set to `0` to disable keyframes (only the initial snapshot is captured).
|
|
25
|
+
* Cost: each keyframe is roughly the size of one full snapshot
|
|
26
|
+
* (~150-300 bytes per body), times `frameCount / keyframeEvery`.
|
|
27
|
+
*
|
|
28
|
+
* @default `60` (one keyframe per second at 60 fps)
|
|
29
|
+
*/
|
|
30
|
+
keyframeEvery?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A recorded simulation: an initial state snapshot plus a per-frame input log
|
|
34
|
+
* (and optional intermediate keyframes for fast scrubbing). Lossless when
|
|
35
|
+
* the user's `applyInput` callback is deterministic and `space.deterministic`
|
|
36
|
+
* was set on the recording space.
|
|
37
|
+
*
|
|
38
|
+
* @typeParam T - User input payload type.
|
|
39
|
+
*/
|
|
40
|
+
interface Replay<T = unknown> {
|
|
41
|
+
/** Replay format version — bumped on breaking layout changes. */
|
|
42
|
+
readonly version: number;
|
|
43
|
+
/**
|
|
44
|
+
* Binary snapshot of the space at frame 0, before any input was applied or
|
|
45
|
+
* any step was taken. Produced via `spaceToBinary`.
|
|
46
|
+
*/
|
|
47
|
+
readonly initialSnapshot: Uint8Array;
|
|
48
|
+
/**
|
|
49
|
+
* Sparse input log. Each entry is the payload supplied to
|
|
50
|
+
* {@link Recorder.recordFrame} for the matching frame. Frames with no input
|
|
51
|
+
* are absent from the array (saving space when most frames are idle).
|
|
52
|
+
*/
|
|
53
|
+
readonly inputs: ReadonlyArray<ReplayFrameInput<T>>;
|
|
54
|
+
/**
|
|
55
|
+
* Intermediate snapshots for fast scrub. Always sorted by `frame` ascending
|
|
56
|
+
* and never includes frame 0 (use {@link initialSnapshot} for that). Empty
|
|
57
|
+
* when `keyframeEvery: 0` was used during recording.
|
|
58
|
+
*/
|
|
59
|
+
readonly keyframes: ReadonlyArray<ReplayKeyframe>;
|
|
60
|
+
/**
|
|
61
|
+
* Total number of frames captured. After playback reaches `frameCount`,
|
|
62
|
+
* the space has been stepped `frameCount` times.
|
|
63
|
+
*/
|
|
64
|
+
readonly frameCount: number;
|
|
65
|
+
}
|
|
66
|
+
/** One entry in the {@link Replay.inputs} log. */
|
|
67
|
+
interface ReplayFrameInput<T = unknown> {
|
|
68
|
+
/** Zero-based frame index — applied BEFORE the step at that frame. */
|
|
69
|
+
readonly frame: number;
|
|
70
|
+
/** User-defined payload (deep-cloned from the value passed to `recordFrame`). */
|
|
71
|
+
readonly payload: T;
|
|
72
|
+
}
|
|
73
|
+
/** One entry in the {@link Replay.keyframes} list. */
|
|
74
|
+
interface ReplayKeyframe {
|
|
75
|
+
/** Zero-based frame index. The space at this frame is the deserialised snapshot. */
|
|
76
|
+
readonly frame: number;
|
|
77
|
+
/** Binary snapshot from `spaceToBinary` at that frame. */
|
|
78
|
+
readonly snapshot: Uint8Array;
|
|
79
|
+
}
|
|
80
|
+
/** Result of {@link validateDeterministicConfig}. */
|
|
81
|
+
interface DeterminismValidation {
|
|
82
|
+
/** True if no critical issues were found. Warnings may still be present. */
|
|
83
|
+
ok: boolean;
|
|
84
|
+
/** Human-readable diagnostic messages. */
|
|
85
|
+
warnings: string[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Records a deterministic simulation by capturing an initial snapshot plus a
|
|
90
|
+
* per-frame log of user-supplied inputs. The resulting {@link Replay} can be
|
|
91
|
+
* encoded to binary, shared, and replayed elsewhere via {@link Player}.
|
|
92
|
+
*
|
|
93
|
+
* **Recording loop pattern:**
|
|
94
|
+
* ```ts
|
|
95
|
+
* const recorder = new Recorder<MyInput>(space);
|
|
96
|
+
* for (let frame = 0; frame < N; frame++) {
|
|
97
|
+
* const input = readUserInput();
|
|
98
|
+
* recorder.recordFrame(input);
|
|
99
|
+
* applyInputToSpace(input, space); // user's own logic
|
|
100
|
+
* space.step(1 / 60);
|
|
101
|
+
* }
|
|
102
|
+
* const replay = recorder.finish();
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* **For deterministic replay**, the recording space MUST satisfy:
|
|
106
|
+
* - `space.deterministic = true` (set before any bodies are added).
|
|
107
|
+
* - Step with a fixed `dt` and matching velocity / position iteration counts.
|
|
108
|
+
* - Bodies must be added in the same order on the playback side — captured
|
|
109
|
+
* automatically by the snapshot, but any post-restore logic must respect it.
|
|
110
|
+
* - User's `applyInput` callback must be a pure function of `(input, space, frame)`
|
|
111
|
+
* (no `Math.random()`, no wall-clock reads).
|
|
112
|
+
*
|
|
113
|
+
* @typeParam T - JSON-serializable user input payload.
|
|
114
|
+
*/
|
|
115
|
+
declare class Recorder<T = unknown> {
|
|
116
|
+
private readonly _initialSnapshot;
|
|
117
|
+
private readonly _inputs;
|
|
118
|
+
private readonly _keyframes;
|
|
119
|
+
private readonly _keyframeEvery;
|
|
120
|
+
private _frame;
|
|
121
|
+
private _finished;
|
|
122
|
+
private readonly _space;
|
|
123
|
+
/**
|
|
124
|
+
* Snapshot the supplied space at frame 0 and start a new recording.
|
|
125
|
+
* The space reference is retained — keyframe captures sample its current
|
|
126
|
+
* state, so the user MUST keep stepping the same space instance.
|
|
127
|
+
*/
|
|
128
|
+
constructor(space: Space, options?: RecorderOptions);
|
|
129
|
+
/** Number of frames recorded so far. */
|
|
130
|
+
get frame(): number;
|
|
131
|
+
/** True after {@link finish} has been called. Further recording throws. */
|
|
132
|
+
get finished(): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Log an input payload for the current frame, then advance the frame
|
|
135
|
+
* counter. If `keyframeEvery > 0` and the new frame index is a multiple
|
|
136
|
+
* of it, also captures a snapshot from the recording space.
|
|
137
|
+
*
|
|
138
|
+
* Pass `null` (or omit) for frames with no input — only frames with a
|
|
139
|
+
* payload are stored, keeping the log compact.
|
|
140
|
+
*
|
|
141
|
+
* @param input - User payload. Deep-cloned via JSON before storage.
|
|
142
|
+
*/
|
|
143
|
+
recordFrame(input?: T | null): void;
|
|
144
|
+
/**
|
|
145
|
+
* Seal the recording and return the final {@link Replay} object. After
|
|
146
|
+
* calling, further {@link recordFrame} calls throw.
|
|
147
|
+
*/
|
|
148
|
+
finish(): Replay<T>;
|
|
149
|
+
}
|
|
150
|
+
/** Replay structure version — bumped on breaking layout changes. */
|
|
151
|
+
declare const REPLAY_VERSION = 1;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Plays back a {@link Replay} produced by {@link Recorder}.
|
|
155
|
+
*
|
|
156
|
+
* The player owns its own {@link Space} (deserialised from the replay's
|
|
157
|
+
* initial snapshot). Each call to {@link step} advances exactly one frame —
|
|
158
|
+
* applying the recorded input via the user's callback, then stepping physics.
|
|
159
|
+
*
|
|
160
|
+
* For random access, {@link stepTo} jumps to the nearest keyframe at or
|
|
161
|
+
* before the target frame, then steps forward through the input log. Backward
|
|
162
|
+
* jumps require keyframes to be present (otherwise the player must re-step
|
|
163
|
+
* from frame 0, which still works but costs O(target) time).
|
|
164
|
+
*
|
|
165
|
+
* @typeParam T - User input payload type (must match the recorder's).
|
|
166
|
+
*/
|
|
167
|
+
declare class Player<T = unknown> {
|
|
168
|
+
private readonly _replay;
|
|
169
|
+
private _applyInput;
|
|
170
|
+
private _space;
|
|
171
|
+
private _frame;
|
|
172
|
+
private _velocityIterations;
|
|
173
|
+
private _positionIterations;
|
|
174
|
+
private _dt;
|
|
175
|
+
/**
|
|
176
|
+
* @param replay - Replay to play.
|
|
177
|
+
* @param applyInput - Callback that translates input payloads into Space
|
|
178
|
+
* mutations. Required for replays with non-empty input logs; replays with
|
|
179
|
+
* only physics state (no user input) can pass `null`.
|
|
180
|
+
* @param options - Playback config matching the recorder's step parameters.
|
|
181
|
+
* Defaults: `dt = 1/60`, `velocityIterations = 8`, `positionIterations = 3`.
|
|
182
|
+
*/
|
|
183
|
+
constructor(replay: Replay<T>, applyInput?: ReplayInputApplier<T> | null, options?: {
|
|
184
|
+
dt?: number;
|
|
185
|
+
velocityIterations?: number;
|
|
186
|
+
positionIterations?: number;
|
|
187
|
+
});
|
|
188
|
+
/**
|
|
189
|
+
* Restore the initial snapshot. Must be called before {@link step} or
|
|
190
|
+
* {@link stepTo}. Re-calling rewinds to frame 0 (useful for looping).
|
|
191
|
+
*/
|
|
192
|
+
restore(): Space;
|
|
193
|
+
/** The active space. Throws if {@link restore} has not been called. */
|
|
194
|
+
get space(): Space;
|
|
195
|
+
/** Current frame index. 0 means "initial state, not yet stepped". */
|
|
196
|
+
get frame(): number;
|
|
197
|
+
/** Total frames in the replay. */
|
|
198
|
+
get frameCount(): number;
|
|
199
|
+
/** True when the player has reached the final frame. */
|
|
200
|
+
get finished(): boolean;
|
|
201
|
+
/** The replay being played. */
|
|
202
|
+
get replay(): Replay<T>;
|
|
203
|
+
get applyInput(): ReplayInputApplier<T> | null;
|
|
204
|
+
set applyInput(fn: ReplayInputApplier<T> | null);
|
|
205
|
+
/**
|
|
206
|
+
* Advance one frame: look up the input for the current frame (if any),
|
|
207
|
+
* apply it via the callback, then step physics by `dt`.
|
|
208
|
+
*
|
|
209
|
+
* Throws if the player is at the end or {@link restore} hasn't been called.
|
|
210
|
+
*/
|
|
211
|
+
step(): void;
|
|
212
|
+
/**
|
|
213
|
+
* Jump to a specific frame. Forward jumps step through the log; backward
|
|
214
|
+
* jumps restore the latest keyframe ≤ `target` (or the initial snapshot if
|
|
215
|
+
* none) and step forward from there.
|
|
216
|
+
*
|
|
217
|
+
* After this call, {@link space} reflects the state AFTER `target` steps.
|
|
218
|
+
* If `target === 0`, the space is the initial snapshot (pre-step).
|
|
219
|
+
*
|
|
220
|
+
* @param target - Target frame index in `[0, frameCount]`.
|
|
221
|
+
*/
|
|
222
|
+
stepTo(target: number): void;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Binary encoding for {@link Replay} — pairs with {@link decodeReplay}.
|
|
227
|
+
*
|
|
228
|
+
* Format (little-endian unless noted):
|
|
229
|
+
* - Magic "RPLY" (4 B, big-endian u32 0x52504C59)
|
|
230
|
+
* - Version u16
|
|
231
|
+
* - Frame count u32
|
|
232
|
+
* - Initial snapshot: length u32, bytes
|
|
233
|
+
* - Input count u32, then for each input: frame u32, JSON byte-length u32, UTF-8 bytes
|
|
234
|
+
* - Keyframe count u32, then for each keyframe: frame u32, snapshot length u32, bytes
|
|
235
|
+
*
|
|
236
|
+
* The user payload is encoded as UTF-8 JSON. Binary payloads (e.g. ArrayBuffer)
|
|
237
|
+
* are not supported directly — the user can base64-encode them into strings if
|
|
238
|
+
* needed.
|
|
239
|
+
*/
|
|
240
|
+
|
|
241
|
+
/** Encode a {@link Replay} into a compact `Uint8Array`. */
|
|
242
|
+
declare function encodeReplay<T>(replay: Replay<T>): Uint8Array;
|
|
243
|
+
/** Decode a `Uint8Array` produced by {@link encodeReplay} into a {@link Replay}. */
|
|
244
|
+
declare function decodeReplay<T = unknown>(bytes: Uint8Array): Replay<T>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Inspect a {@link Space} and warn about configuration that prevents
|
|
248
|
+
* deterministic replay. Pure inspection — does not mutate the space.
|
|
249
|
+
*
|
|
250
|
+
* Currently checks:
|
|
251
|
+
* - `space.deterministic` is enabled.
|
|
252
|
+
* - The space has been stepped at least once (sleep state can leak otherwise).
|
|
253
|
+
*
|
|
254
|
+
* Returns `{ ok: true }` with no warnings when the space looks ready for
|
|
255
|
+
* recording; otherwise returns `ok: false` with a list of human-readable
|
|
256
|
+
* messages.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const { ok, warnings } = validateDeterministicConfig(space);
|
|
261
|
+
* if (!ok) console.warn("Replay may drift:", warnings);
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
declare function validateDeterministicConfig(space: Space): DeterminismValidation;
|
|
265
|
+
|
|
266
|
+
export { type DeterminismValidation, Player, REPLAY_VERSION, Recorder, type RecorderOptions, type Replay, type ReplayFrameInput, type ReplayInputApplier, type ReplayKeyframe, decodeReplay, encodeReplay, validateDeterministicConfig };
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { j as Space } from '../ConvexResult-BsMBE06r.js';
|
|
2
|
+
import '../PhysicsMetrics-QzFDRdGh.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Per-frame callback that translates a user-defined input payload into engine
|
|
6
|
+
* mutations on the supplied {@link Space}. Called by {@link Player} once per
|
|
7
|
+
* frame during playback, BEFORE `space.step()`.
|
|
8
|
+
*
|
|
9
|
+
* The callback receives the payload exactly as supplied to
|
|
10
|
+
* {@link Recorder.recordFrame} during recording — the recorder JSON-clones the
|
|
11
|
+
* payload, so mutations made between frames don't leak into the log.
|
|
12
|
+
*
|
|
13
|
+
* @typeParam T - User input payload type (must be JSON-serializable).
|
|
14
|
+
*/
|
|
15
|
+
type ReplayInputApplier<T> = (input: T, space: Space, frame: number) => void;
|
|
16
|
+
/** Configuration options for {@link Recorder}. */
|
|
17
|
+
interface RecorderOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Capture a full snapshot every N frames in addition to the initial one.
|
|
20
|
+
* Enables fast random-access scrubbing in {@link Player.stepTo}: a backward
|
|
21
|
+
* jump restores the latest keyframe at or before the target frame, then
|
|
22
|
+
* steps forward through the input log.
|
|
23
|
+
*
|
|
24
|
+
* Set to `0` to disable keyframes (only the initial snapshot is captured).
|
|
25
|
+
* Cost: each keyframe is roughly the size of one full snapshot
|
|
26
|
+
* (~150-300 bytes per body), times `frameCount / keyframeEvery`.
|
|
27
|
+
*
|
|
28
|
+
* @default `60` (one keyframe per second at 60 fps)
|
|
29
|
+
*/
|
|
30
|
+
keyframeEvery?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A recorded simulation: an initial state snapshot plus a per-frame input log
|
|
34
|
+
* (and optional intermediate keyframes for fast scrubbing). Lossless when
|
|
35
|
+
* the user's `applyInput` callback is deterministic and `space.deterministic`
|
|
36
|
+
* was set on the recording space.
|
|
37
|
+
*
|
|
38
|
+
* @typeParam T - User input payload type.
|
|
39
|
+
*/
|
|
40
|
+
interface Replay<T = unknown> {
|
|
41
|
+
/** Replay format version — bumped on breaking layout changes. */
|
|
42
|
+
readonly version: number;
|
|
43
|
+
/**
|
|
44
|
+
* Binary snapshot of the space at frame 0, before any input was applied or
|
|
45
|
+
* any step was taken. Produced via `spaceToBinary`.
|
|
46
|
+
*/
|
|
47
|
+
readonly initialSnapshot: Uint8Array;
|
|
48
|
+
/**
|
|
49
|
+
* Sparse input log. Each entry is the payload supplied to
|
|
50
|
+
* {@link Recorder.recordFrame} for the matching frame. Frames with no input
|
|
51
|
+
* are absent from the array (saving space when most frames are idle).
|
|
52
|
+
*/
|
|
53
|
+
readonly inputs: ReadonlyArray<ReplayFrameInput<T>>;
|
|
54
|
+
/**
|
|
55
|
+
* Intermediate snapshots for fast scrub. Always sorted by `frame` ascending
|
|
56
|
+
* and never includes frame 0 (use {@link initialSnapshot} for that). Empty
|
|
57
|
+
* when `keyframeEvery: 0` was used during recording.
|
|
58
|
+
*/
|
|
59
|
+
readonly keyframes: ReadonlyArray<ReplayKeyframe>;
|
|
60
|
+
/**
|
|
61
|
+
* Total number of frames captured. After playback reaches `frameCount`,
|
|
62
|
+
* the space has been stepped `frameCount` times.
|
|
63
|
+
*/
|
|
64
|
+
readonly frameCount: number;
|
|
65
|
+
}
|
|
66
|
+
/** One entry in the {@link Replay.inputs} log. */
|
|
67
|
+
interface ReplayFrameInput<T = unknown> {
|
|
68
|
+
/** Zero-based frame index — applied BEFORE the step at that frame. */
|
|
69
|
+
readonly frame: number;
|
|
70
|
+
/** User-defined payload (deep-cloned from the value passed to `recordFrame`). */
|
|
71
|
+
readonly payload: T;
|
|
72
|
+
}
|
|
73
|
+
/** One entry in the {@link Replay.keyframes} list. */
|
|
74
|
+
interface ReplayKeyframe {
|
|
75
|
+
/** Zero-based frame index. The space at this frame is the deserialised snapshot. */
|
|
76
|
+
readonly frame: number;
|
|
77
|
+
/** Binary snapshot from `spaceToBinary` at that frame. */
|
|
78
|
+
readonly snapshot: Uint8Array;
|
|
79
|
+
}
|
|
80
|
+
/** Result of {@link validateDeterministicConfig}. */
|
|
81
|
+
interface DeterminismValidation {
|
|
82
|
+
/** True if no critical issues were found. Warnings may still be present. */
|
|
83
|
+
ok: boolean;
|
|
84
|
+
/** Human-readable diagnostic messages. */
|
|
85
|
+
warnings: string[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Records a deterministic simulation by capturing an initial snapshot plus a
|
|
90
|
+
* per-frame log of user-supplied inputs. The resulting {@link Replay} can be
|
|
91
|
+
* encoded to binary, shared, and replayed elsewhere via {@link Player}.
|
|
92
|
+
*
|
|
93
|
+
* **Recording loop pattern:**
|
|
94
|
+
* ```ts
|
|
95
|
+
* const recorder = new Recorder<MyInput>(space);
|
|
96
|
+
* for (let frame = 0; frame < N; frame++) {
|
|
97
|
+
* const input = readUserInput();
|
|
98
|
+
* recorder.recordFrame(input);
|
|
99
|
+
* applyInputToSpace(input, space); // user's own logic
|
|
100
|
+
* space.step(1 / 60);
|
|
101
|
+
* }
|
|
102
|
+
* const replay = recorder.finish();
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* **For deterministic replay**, the recording space MUST satisfy:
|
|
106
|
+
* - `space.deterministic = true` (set before any bodies are added).
|
|
107
|
+
* - Step with a fixed `dt` and matching velocity / position iteration counts.
|
|
108
|
+
* - Bodies must be added in the same order on the playback side — captured
|
|
109
|
+
* automatically by the snapshot, but any post-restore logic must respect it.
|
|
110
|
+
* - User's `applyInput` callback must be a pure function of `(input, space, frame)`
|
|
111
|
+
* (no `Math.random()`, no wall-clock reads).
|
|
112
|
+
*
|
|
113
|
+
* @typeParam T - JSON-serializable user input payload.
|
|
114
|
+
*/
|
|
115
|
+
declare class Recorder<T = unknown> {
|
|
116
|
+
private readonly _initialSnapshot;
|
|
117
|
+
private readonly _inputs;
|
|
118
|
+
private readonly _keyframes;
|
|
119
|
+
private readonly _keyframeEvery;
|
|
120
|
+
private _frame;
|
|
121
|
+
private _finished;
|
|
122
|
+
private readonly _space;
|
|
123
|
+
/**
|
|
124
|
+
* Snapshot the supplied space at frame 0 and start a new recording.
|
|
125
|
+
* The space reference is retained — keyframe captures sample its current
|
|
126
|
+
* state, so the user MUST keep stepping the same space instance.
|
|
127
|
+
*/
|
|
128
|
+
constructor(space: Space, options?: RecorderOptions);
|
|
129
|
+
/** Number of frames recorded so far. */
|
|
130
|
+
get frame(): number;
|
|
131
|
+
/** True after {@link finish} has been called. Further recording throws. */
|
|
132
|
+
get finished(): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Log an input payload for the current frame, then advance the frame
|
|
135
|
+
* counter. If `keyframeEvery > 0` and the new frame index is a multiple
|
|
136
|
+
* of it, also captures a snapshot from the recording space.
|
|
137
|
+
*
|
|
138
|
+
* Pass `null` (or omit) for frames with no input — only frames with a
|
|
139
|
+
* payload are stored, keeping the log compact.
|
|
140
|
+
*
|
|
141
|
+
* @param input - User payload. Deep-cloned via JSON before storage.
|
|
142
|
+
*/
|
|
143
|
+
recordFrame(input?: T | null): void;
|
|
144
|
+
/**
|
|
145
|
+
* Seal the recording and return the final {@link Replay} object. After
|
|
146
|
+
* calling, further {@link recordFrame} calls throw.
|
|
147
|
+
*/
|
|
148
|
+
finish(): Replay<T>;
|
|
149
|
+
}
|
|
150
|
+
/** Replay structure version — bumped on breaking layout changes. */
|
|
151
|
+
declare const REPLAY_VERSION = 1;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Plays back a {@link Replay} produced by {@link Recorder}.
|
|
155
|
+
*
|
|
156
|
+
* The player owns its own {@link Space} (deserialised from the replay's
|
|
157
|
+
* initial snapshot). Each call to {@link step} advances exactly one frame —
|
|
158
|
+
* applying the recorded input via the user's callback, then stepping physics.
|
|
159
|
+
*
|
|
160
|
+
* For random access, {@link stepTo} jumps to the nearest keyframe at or
|
|
161
|
+
* before the target frame, then steps forward through the input log. Backward
|
|
162
|
+
* jumps require keyframes to be present (otherwise the player must re-step
|
|
163
|
+
* from frame 0, which still works but costs O(target) time).
|
|
164
|
+
*
|
|
165
|
+
* @typeParam T - User input payload type (must match the recorder's).
|
|
166
|
+
*/
|
|
167
|
+
declare class Player<T = unknown> {
|
|
168
|
+
private readonly _replay;
|
|
169
|
+
private _applyInput;
|
|
170
|
+
private _space;
|
|
171
|
+
private _frame;
|
|
172
|
+
private _velocityIterations;
|
|
173
|
+
private _positionIterations;
|
|
174
|
+
private _dt;
|
|
175
|
+
/**
|
|
176
|
+
* @param replay - Replay to play.
|
|
177
|
+
* @param applyInput - Callback that translates input payloads into Space
|
|
178
|
+
* mutations. Required for replays with non-empty input logs; replays with
|
|
179
|
+
* only physics state (no user input) can pass `null`.
|
|
180
|
+
* @param options - Playback config matching the recorder's step parameters.
|
|
181
|
+
* Defaults: `dt = 1/60`, `velocityIterations = 8`, `positionIterations = 3`.
|
|
182
|
+
*/
|
|
183
|
+
constructor(replay: Replay<T>, applyInput?: ReplayInputApplier<T> | null, options?: {
|
|
184
|
+
dt?: number;
|
|
185
|
+
velocityIterations?: number;
|
|
186
|
+
positionIterations?: number;
|
|
187
|
+
});
|
|
188
|
+
/**
|
|
189
|
+
* Restore the initial snapshot. Must be called before {@link step} or
|
|
190
|
+
* {@link stepTo}. Re-calling rewinds to frame 0 (useful for looping).
|
|
191
|
+
*/
|
|
192
|
+
restore(): Space;
|
|
193
|
+
/** The active space. Throws if {@link restore} has not been called. */
|
|
194
|
+
get space(): Space;
|
|
195
|
+
/** Current frame index. 0 means "initial state, not yet stepped". */
|
|
196
|
+
get frame(): number;
|
|
197
|
+
/** Total frames in the replay. */
|
|
198
|
+
get frameCount(): number;
|
|
199
|
+
/** True when the player has reached the final frame. */
|
|
200
|
+
get finished(): boolean;
|
|
201
|
+
/** The replay being played. */
|
|
202
|
+
get replay(): Replay<T>;
|
|
203
|
+
get applyInput(): ReplayInputApplier<T> | null;
|
|
204
|
+
set applyInput(fn: ReplayInputApplier<T> | null);
|
|
205
|
+
/**
|
|
206
|
+
* Advance one frame: look up the input for the current frame (if any),
|
|
207
|
+
* apply it via the callback, then step physics by `dt`.
|
|
208
|
+
*
|
|
209
|
+
* Throws if the player is at the end or {@link restore} hasn't been called.
|
|
210
|
+
*/
|
|
211
|
+
step(): void;
|
|
212
|
+
/**
|
|
213
|
+
* Jump to a specific frame. Forward jumps step through the log; backward
|
|
214
|
+
* jumps restore the latest keyframe ≤ `target` (or the initial snapshot if
|
|
215
|
+
* none) and step forward from there.
|
|
216
|
+
*
|
|
217
|
+
* After this call, {@link space} reflects the state AFTER `target` steps.
|
|
218
|
+
* If `target === 0`, the space is the initial snapshot (pre-step).
|
|
219
|
+
*
|
|
220
|
+
* @param target - Target frame index in `[0, frameCount]`.
|
|
221
|
+
*/
|
|
222
|
+
stepTo(target: number): void;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Binary encoding for {@link Replay} — pairs with {@link decodeReplay}.
|
|
227
|
+
*
|
|
228
|
+
* Format (little-endian unless noted):
|
|
229
|
+
* - Magic "RPLY" (4 B, big-endian u32 0x52504C59)
|
|
230
|
+
* - Version u16
|
|
231
|
+
* - Frame count u32
|
|
232
|
+
* - Initial snapshot: length u32, bytes
|
|
233
|
+
* - Input count u32, then for each input: frame u32, JSON byte-length u32, UTF-8 bytes
|
|
234
|
+
* - Keyframe count u32, then for each keyframe: frame u32, snapshot length u32, bytes
|
|
235
|
+
*
|
|
236
|
+
* The user payload is encoded as UTF-8 JSON. Binary payloads (e.g. ArrayBuffer)
|
|
237
|
+
* are not supported directly — the user can base64-encode them into strings if
|
|
238
|
+
* needed.
|
|
239
|
+
*/
|
|
240
|
+
|
|
241
|
+
/** Encode a {@link Replay} into a compact `Uint8Array`. */
|
|
242
|
+
declare function encodeReplay<T>(replay: Replay<T>): Uint8Array;
|
|
243
|
+
/** Decode a `Uint8Array` produced by {@link encodeReplay} into a {@link Replay}. */
|
|
244
|
+
declare function decodeReplay<T = unknown>(bytes: Uint8Array): Replay<T>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Inspect a {@link Space} and warn about configuration that prevents
|
|
248
|
+
* deterministic replay. Pure inspection — does not mutate the space.
|
|
249
|
+
*
|
|
250
|
+
* Currently checks:
|
|
251
|
+
* - `space.deterministic` is enabled.
|
|
252
|
+
* - The space has been stepped at least once (sleep state can leak otherwise).
|
|
253
|
+
*
|
|
254
|
+
* Returns `{ ok: true }` with no warnings when the space looks ready for
|
|
255
|
+
* recording; otherwise returns `ok: false` with a list of human-readable
|
|
256
|
+
* messages.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const { ok, warnings } = validateDeterministicConfig(space);
|
|
261
|
+
* if (!ok) console.warn("Replay may drift:", warnings);
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
declare function validateDeterministicConfig(space: Space): DeterminismValidation;
|
|
265
|
+
|
|
266
|
+
export { type DeterminismValidation, Player, REPLAY_VERSION, Recorder, type RecorderOptions, type Replay, type ReplayFrameInput, type ReplayInputApplier, type ReplayKeyframe, decodeReplay, encodeReplay, validateDeterministicConfig };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {b,c}from'../chunk-GPGT7DYQ.js';import'../chunk-263GQ5UK.js';var _=class{constructor(t,e={}){this._inputs=[];this._keyframes=[];this._frame=0;this._finished=false;if(t==null)throw new Error("Recorder: space is required");let i=e.keyframeEvery;if(i!=null&&(!Number.isFinite(i)||i<0||(i|0)!==i))throw new Error(`Recorder: keyframeEvery must be a non-negative integer (got ${i})`);this._space=t,this._keyframeEvery=i??60,this._initialSnapshot=b(t);}get frame(){return this._frame}get finished(){return this._finished}recordFrame(t){if(this._finished)throw new Error("Recorder: cannot record after finish()");if(this._keyframeEvery>0&&this._frame>0&&this._frame%this._keyframeEvery===0&&this._keyframes.push({frame:this._frame,snapshot:b(this._space)}),t!=null){let e=v(t);this._inputs.push({frame:this._frame,payload:e});}this._frame++;}finish(){return this._finished=true,{version:f,initialSnapshot:this._initialSnapshot,inputs:this._inputs.slice(),keyframes:this._keyframes.slice(),frameCount:this._frame}}},f=1;function v(r){let t=typeof r;return r===null||t==="number"||t==="string"||t==="boolean"?r:JSON.parse(JSON.stringify(r))}var d=class{constructor(t,e=null,i={}){this._space=null;this._frame=0;if(t==null)throw new Error("Player: replay is required");this._replay=t,this._applyInput=e,this._dt=i.dt??1/60,this._velocityIterations=i.velocityIterations??8,this._positionIterations=i.positionIterations??3;}restore(){return this._space=c(this._replay.initialSnapshot),this._frame=0,this._space}get space(){if(this._space==null)throw new Error("Player: call restore() before reading space");return this._space}get frame(){return this._frame}get frameCount(){return this._replay.frameCount}get finished(){return this._frame>=this._replay.frameCount}get replay(){return this._replay}get applyInput(){return this._applyInput}set applyInput(t){this._applyInput=t;}step(){if(this._space==null)throw new Error("Player: call restore() before step()");if(this._frame>=this._replay.frameCount)throw new Error(`Player: already at end of replay (frame ${this._frame}/${this._replay.frameCount})`);let t=I(this._replay.inputs,this._frame);t!=null&&this._applyInput!=null&&this._applyInput(t.payload,this._space,this._frame),this._space.step(this._dt,this._velocityIterations,this._positionIterations),this._frame++;}stepTo(t){if(!Number.isFinite(t)||t<0||t>this._replay.frameCount)throw new Error(`Player: target frame ${t} out of range [0, ${this._replay.frameCount}]`);if(this._space==null&&this.restore(),t<this._frame){let e=S(this._replay.keyframes,t);e!=null?(this._space=c(e.snapshot),this._frame=e.frame):this.restore();}for(;this._frame<t;)this.step();}};function I(r,t){let e=0,i=r.length-1;for(;e<=i;){let a=e+i>>>1,o=r[a].frame;if(o===t)return r[a];o<t?e=a+1:i=a-1;}return null}function S(r,t){let e=0,i=r.length-1,a=null;for(;e<=i;){let o=e+i>>>1,n=r[o];n.frame<=t?(a=n,e=o+1):i=o-1;}return a}var R=1380994137,T=new TextEncoder,E=new TextDecoder;function U(r){let t=[];for(let s of r.inputs){let u=JSON.stringify(s.payload);t.push({frame:s.frame,bytes:T.encode(u??"null")});}let e=14+r.initialSnapshot.byteLength;e+=4;for(let s of t)e+=8+s.bytes.byteLength;e+=4;for(let s of r.keyframes)e+=8+s.snapshot.byteLength;let i=new ArrayBuffer(e),a=new DataView(i),o=new Uint8Array(i),n=0;a.setUint32(n,R,false),n+=4,a.setUint16(n,r.version,true),n+=2,a.setUint32(n,r.frameCount,true),n+=4,a.setUint32(n,r.initialSnapshot.byteLength,true),n+=4,o.set(r.initialSnapshot,n),n+=r.initialSnapshot.byteLength,a.setUint32(n,t.length,true),n+=4;for(let s of t)a.setUint32(n,s.frame,true),n+=4,a.setUint32(n,s.bytes.byteLength,true),n+=4,o.set(s.bytes,n),n+=s.bytes.byteLength;a.setUint32(n,r.keyframes.length,true),n+=4;for(let s of r.keyframes)a.setUint32(n,s.frame,true),n+=4,a.setUint32(n,s.snapshot.byteLength,true),n+=4,o.set(s.snapshot,n),n+=s.snapshot.byteLength;return o}function k(r){let t=new DataView(r.buffer,r.byteOffset,r.byteLength),e=0,i=t.getUint32(e,false);if(e+=4,i!==R)throw new Error(`decodeReplay: invalid magic 0x${i.toString(16).padStart(8,"0")} (expected 0x${R.toString(16)})`);let a=t.getUint16(e,true);if(e+=2,a!==f)throw new Error(`decodeReplay: unsupported version ${a} (expected ${f})`);let o=t.getUint32(e,true);e+=4;let n=t.getUint32(e,true);e+=4;let s=r.slice(e,e+n);e+=n;let u=t.getUint32(e,true);e+=4;let b=new Array(u);for(let p=0;p<u;p++){let m=t.getUint32(e,true);e+=4;let l=t.getUint32(e,true);e+=4;let y=E.decode(r.subarray(e,e+l));e+=l,b[p]={frame:m,payload:JSON.parse(y)};}let g=t.getUint32(e,true);e+=4;let w=new Array(g);for(let p=0;p<g;p++){let m=t.getUint32(e,true);e+=4;let l=t.getUint32(e,true);e+=4;let y=r.slice(e,e+l);e+=l,w[p]={frame:m,snapshot:y};}return {version:a,initialSnapshot:s,inputs:b,keyframes:w,frameCount:o}}function A(r){let t=[];return r==null?{ok:false,warnings:["space is null"]}:(r.deterministic||t.push("space.deterministic is false \u2014 replays will drift from the recording. Set space.deterministic = true."),{ok:t.length===0,warnings:t})}export{d as Player,f as REPLAY_VERSION,_ as Recorder,k as decodeReplay,U as encodeReplay,A as validateDeterministicConfig};//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var chunkOFVSWS4I_cjs=require('../chunk-OFVSWS4I.cjs');var at=1;function b(t){return {x:t.x,y:t.y}}function ut(t){if(t==null)return null;try{let o=JSON.stringify(t);return o==="{}"?null:JSON.parse(o)}catch{return null}}function mt(t){return {elasticity:t.elasticity,dynamicFriction:t.dynamicFriction,staticFriction:t.staticFriction,density:t.density,rollingFriction:t.rollingFriction}}function yt(t){return {collisionGroup:t.collisionGroup,collisionMask:t.collisionMask,sensorGroup:t.sensorGroup,sensorMask:t.sensorMask,fluidGroup:t.fluidGroup,fluidMask:t.fluidMask}}function ft(t){if(t==null)return null;let o=t.gravity;return {density:t.density,viscosity:t.viscosity,gravity:o!=null?b(o):null}}function bt(t){let o=mt(t.material),n=yt(t.filter),e=t.fluidEnabled,r=e?ft(t.fluidProperties):null,a=t.sensorEnabled;if(t.isCircle()){let i=t,s=t.localCOM;return {type:"circle",radius:i.radius,localCOM:b(s),material:o,filter:n,sensorEnabled:a,fluidEnabled:e,fluidProperties:r}}else if(t.isCapsule()){let i=t,s=t.localCOM;return {type:"capsule",width:i.width,height:i.height,localCOM:b(s),material:o,filter:n,sensorEnabled:a,fluidEnabled:e,fluidProperties:r}}else {let s=t.localVerts,l=[],u=s.length;for(let m=0;m<u;m++)l.push(b(s.at(m)));return {type:"polygon",localVerts:l,material:o,filter:n,sensorEnabled:a,fluidEnabled:e,fluidProperties:r}}}var Ft={1:"STATIC",2:"DYNAMIC",3:"KINEMATIC"},Dt={0:"DEFAULT",1:"FIXED",2:"FIXED_GROUP"},ht={0:"DEFAULT",1:"FIXED",2:"FIXED_GROUP"},Mt={0:"DEFAULT",1:"FIXED",2:"SCALED"};function gt(t,o){let n=t.zpp_inner,e=Dt[n.massMode]??"DEFAULT",r=ht[n.inertiaMode]??"DEFAULT",a=Mt[n.gravMassMode]??"DEFAULT",i=[],s=t.shapes,l=s.length;for(let u=0;u<l;u++)i.push(bt(s.at(u)));return {id:o,type:Ft[n.type]??"DYNAMIC",position:b(t.position),rotation:t.rotation,velocity:b(t.velocity),angularVel:t.angularVel,kinematicVel:b(t.kinematicVel),kinAngVel:t.kinAngVel,surfaceVel:b(t.surfaceVel),force:b(t.force),torque:n.type===2?t.torque:0,massMode:e,mass:e==="FIXED"?n.cmass:null,inertiaMode:r,inertia:r==="FIXED"?n.cinertia:null,gravMassMode:a,gravMassScale:n.gravMassScale,allowMovement:t.allowMovement,allowRotation:t.allowRotation,bullet:t.isBullet,shapes:i,userData:ut(n.userData)}}function B(t,o,n,e){let r=t.zpp_inner,a=n!=null?o.get(n.zpp_inner.id)??null:null,i=e!=null?o.get(e.zpp_inner.id)??null:null;return {body1Id:a,body2Id:i,active:r.active,ignore:r.ignore,stiff:r.stiff,frequency:r.frequency,damping:r.damping,maxForce:r.maxForce,maxError:r.maxError,breakUnderForce:r.breakUnderForce,breakUnderError:r.breakUnderError,removeOnBreak:r.removeOnBreak,userData:ut(r.userData)}}function Ct(t,o){switch(t.constructor?.name??""){case "PivotJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"PivotJoint",anchor1:b(e.anchor1),anchor2:b(e.anchor2)}}case "DistanceJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"DistanceJoint",anchor1:b(e.anchor1),anchor2:b(e.anchor2),jointMin:e.jointMin,jointMax:e.jointMax}}case "AngleJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"AngleJoint",jointMin:e.jointMin,jointMax:e.jointMax,ratio:e.ratio}}case "MotorJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"MotorJoint",rate:e.rate,ratio:e.ratio}}case "LineJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"LineJoint",anchor1:b(e.anchor1),anchor2:b(e.anchor2),direction:b(e.direction),jointMin:e.jointMin,jointMax:e.jointMax}}case "PulleyJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"PulleyJoint",anchor1:b(e.anchor1),anchor2:b(e.anchor2),anchor3:b(e.anchor3),anchor4:b(e.anchor4),jointMin:e.jointMin,jointMax:e.jointMax,ratio:e.ratio}}case "WeldJoint":{let e=t;return {...B(t,o,e.body1,e.body2),type:"WeldJoint",anchor1:b(e.anchor1),anchor2:b(e.anchor2),phase:e.phase}}default:return null}}function wt(t){let o=[],n=new Map,e=new Map;function r(d){let f=d.zpp_inner.id;if(e.has(f))return;let p=o.length;n.set(d,p),e.set(f,p),o.push(gt(d,p));}let a=t.bodies,i=a.length;for(let d=0;d<i;d++)r(a.at(d));let s=t.compounds,l=s.length;for(let d=0;d<l;d++){let p=s.at(d).bodies,g=p.length;for(let I=0;I<g;I++)r(p.at(I));}let u=[],m=new Map;function D(d){if(m.has(d))return;let f=Ct(d,e);f!=null&&(m.set(d,u.length),u.push(f));}let M=t.constraints,S=M.length;for(let d=0;d<S;d++)D(M.at(d));for(let d=0;d<l;d++){let p=s.at(d).constraints,g=p.length;for(let I=0;I<g;I++)D(p.at(I));}let A=[];for(let d=0;d<l;d++){let f=s.at(d),p=[],g=f.bodies,I=g.length;for(let J=0;J<I;J++){let st=g.at(J),O=n.get(st);O!=null&&p.push(O);}let C=[],x=f.constraints,w=x.length;for(let J=0;J<w;J++){let st=x.at(J),O=m.get(st);O!=null&&C.push(O);}A.push({bodyIds:p,constraintIndices:C,childIndices:[]});}let c=t.zpp_inner.bphase.is_sweep?"SWEEP_AND_PRUNE":"DYNAMIC_AABB_TREE",F=t.gravity;return {version:1,gravity:b(F),worldLinearDrag:t.worldLinearDrag,worldAngularDrag:t.worldAngularDrag,sortContacts:t.sortContacts,deterministic:t.deterministic,broadphase:c,bodies:o,constraints:u,compounds:A}}function P(t){return chunkOFVSWS4I_cjs.I.get(t.x,t.y)}function v(t){return chunkOFVSWS4I_cjs.I.weak(t.x,t.y)}function vt(t){return new chunkOFVSWS4I_cjs.ca(t.elasticity,t.dynamicFriction,t.staticFriction,t.density,t.rollingFriction)}function At(t){let o=new chunkOFVSWS4I_cjs.ha;return o.collisionGroup=t.collisionGroup,o.collisionMask=t.collisionMask,o.sensorGroup=t.sensorGroup,o.sensorMask=t.sensorMask,o.fluidGroup=t.fluidGroup,o.fluidMask=t.fluidMask,o}function It(t){let o=new chunkOFVSWS4I_cjs.U(t.density,t.viscosity);return t.gravity!=null&&(o.gravity=P(t.gravity)),o}function Jt(t){let o=vt(t.material),n=At(t.filter),e;if(t.type==="circle"){let r=P(t.localCOM);e=new chunkOFVSWS4I_cjs.ga(t.radius,r,o,n);}else if(t.type==="capsule"){let r=P(t.localCOM);e=new chunkOFVSWS4I_cjs.ja(t.width,t.height,r,o,n);}else {let r=t.localVerts.map(a=>P(a));e=new chunkOFVSWS4I_cjs.ia(r,o,n);}return e.sensorEnabled=t.sensorEnabled,e.fluidEnabled=t.fluidEnabled,t.fluidEnabled&&t.fluidProperties!=null&&(e.fluidProperties=It(t.fluidProperties)),e}function St(t){let o=t.type==="STATIC"?chunkOFVSWS4I_cjs.aa.STATIC:t.type==="KINEMATIC"?chunkOFVSWS4I_cjs.aa.KINEMATIC:chunkOFVSWS4I_cjs.aa.DYNAMIC,n=new chunkOFVSWS4I_cjs.$(o,v(t.position));n.rotation=t.rotation,t.type!=="STATIC"&&(n.velocity=P(t.velocity),n.angularVel=t.angularVel),n.kinematicVel=P(t.kinematicVel),n.kinAngVel=t.kinAngVel,n.surfaceVel=P(t.surfaceVel),t.type==="DYNAMIC"&&(n.force=P(t.force),n.torque=t.torque),t.massMode==="FIXED"&&t.mass!=null?n.mass=t.mass:t.massMode==="DEFAULT"&&(n.massMode=chunkOFVSWS4I_cjs.fa.DEFAULT),t.inertiaMode==="FIXED"&&t.inertia!=null?n.inertia=t.inertia:t.inertiaMode==="DEFAULT"&&(n.inertiaMode=chunkOFVSWS4I_cjs.ea.DEFAULT),t.gravMassMode==="SCALED"?(n.gravMassMode=chunkOFVSWS4I_cjs.da.SCALED,n.gravMassScale=t.gravMassScale):t.gravMassMode==="FIXED"&&(n.gravMassMode=chunkOFVSWS4I_cjs.da.FIXED),n.allowMovement=t.allowMovement,n.allowRotation=t.allowRotation,n.isBullet=t.bullet;for(let e of t.shapes)Jt(e).body=n;return t.userData!=null&&Object.assign(n.userData,t.userData),n}function U(t,o){t.active=o.active,t.ignore=o.ignore,t.stiff=o.stiff,t.frequency=o.frequency,t.damping=o.damping,t.maxForce=o.maxForce,t.maxError=o.maxError,t.breakUnderForce=o.breakUnderForce,t.breakUnderError=o.breakUnderError,t.removeOnBreak=o.removeOnBreak,o.userData!=null&&Object.assign(t.userData,o.userData);}function xt(t,o){let n=t.body1Id!=null?o[t.body1Id]??null:null,e=t.body2Id!=null?o[t.body2Id]??null:null;switch(t.type){case "PivotJoint":{let r=new chunkOFVSWS4I_cjs.qa(n,e,v(t.anchor1),v(t.anchor2));return U(r,t),r}case "DistanceJoint":{let r=new chunkOFVSWS4I_cjs.na(n,e,v(t.anchor1),v(t.anchor2),t.jointMin,t.jointMax);return U(r,t),r}case "AngleJoint":{let r=new chunkOFVSWS4I_cjs.ma(n,e,t.jointMin,t.jointMax,t.ratio);return U(r,t),r}case "MotorJoint":{let r=new chunkOFVSWS4I_cjs.pa(n,e,t.rate,t.ratio);return U(r,t),r}case "LineJoint":{let r=new chunkOFVSWS4I_cjs.oa(n,e,v(t.anchor1),v(t.anchor2),v(t.direction),t.jointMin,t.jointMax);return U(r,t),r}case "PulleyJoint":{let r=new chunkOFVSWS4I_cjs.ra(n,e,null,null,v(t.anchor1),v(t.anchor2),v(t.anchor3),v(t.anchor4),t.jointMin,t.jointMax,t.ratio);return U(r,t),r}case "WeldJoint":{let r=new chunkOFVSWS4I_cjs.sa(n,e,v(t.anchor1),v(t.anchor2),t.phase);return U(r,t),r}}}function Et(t){if(t.version!==1)throw new Error(`nape-js serialization: unsupported snapshot version ${t.version} (expected ${1})`);let o=t.broadphase==="SWEEP_AND_PRUNE"?chunkOFVSWS4I_cjs.ka.SWEEP_AND_PRUNE:chunkOFVSWS4I_cjs.ka.DYNAMIC_AABB_TREE,n=new chunkOFVSWS4I_cjs.Y(v(t.gravity),o);n.worldLinearDrag=t.worldLinearDrag,n.worldAngularDrag=t.worldAngularDrag,n.sortContacts=t.sortContacts,n.deterministic=t.deterministic??false;let e=t.bodies.map(St),r=t.constraints.map(s=>xt(s,e)),a=new Set,i=new Set;for(let s of t.compounds){let l=new chunkOFVSWS4I_cjs.ba;for(let u of s.bodyIds)e[u].compound=l,a.add(u);for(let u of s.constraintIndices)r[u].compound=l,i.add(u);l.space=n;}for(let s=0;s<e.length;s++)a.has(s)||(e[s].space=n);for(let s=0;s<r.length;s++)i.has(s)||(r[s].space=n);return n}var rt=class{constructor(o=4096){this.pos=0;this.buf=new ArrayBuffer(o),this.view=new DataView(this.buf);}ensure(o){let n=this.pos+o;if(n<=this.buf.byteLength)return;let e=this.buf.byteLength;for(;e<n;)e*=2;let r=new ArrayBuffer(e);new Uint8Array(r).set(new Uint8Array(this.buf)),this.buf=r,this.view=new DataView(this.buf);}writeUint8(o){this.ensure(1),this.view.setUint8(this.pos,o),this.pos+=1;}writeUint16(o){this.ensure(2),this.view.setUint16(this.pos,o,true),this.pos+=2;}writeUint32(o){this.ensure(4),this.view.setUint32(this.pos,o,true),this.pos+=4;}writeInt32(o){this.ensure(4),this.view.setInt32(this.pos,o,true),this.pos+=4;}writeFloat64(o){this.ensure(8),this.view.setFloat64(this.pos,o,true),this.pos+=8;}writeBool(o){this.writeUint8(o?1:0);}finish(){return new Uint8Array(this.buf,0,this.pos)}};var Pt=1312903237,_=2,Bt=0,Ut=1,kt=2,Tt=3,Nt=4,Vt=5,Ot=6;function _t(t,o){t.writeFloat64(o.elasticity),t.writeFloat64(o.dynamicFriction),t.writeFloat64(o.staticFriction),t.writeFloat64(o.density),t.writeFloat64(o.rollingFriction);}function Lt(t,o){t.writeInt32(o.collisionGroup),t.writeInt32(o.collisionMask),t.writeInt32(o.sensorGroup),t.writeInt32(o.sensorMask),t.writeInt32(o.fluidGroup),t.writeInt32(o.fluidMask);}function Rt(t,o){if(o==null)return;t.writeFloat64(o.density),t.writeFloat64(o.viscosity);let n=o.gravity;t.writeBool(n!=null),n!=null&&(t.writeFloat64(n.x),t.writeFloat64(n.y));}function jt(t,o){if(o.isCircle()){t.writeUint8(0);let a=o;t.writeFloat64(a.radius);let i=o.localCOM;t.writeFloat64(i.x),t.writeFloat64(i.y);}else if(o.isCapsule()){t.writeUint8(2);let a=o;t.writeFloat64(a.width),t.writeFloat64(a.height);let i=o.localCOM;t.writeFloat64(i.x),t.writeFloat64(i.y);}else {t.writeUint8(1);let i=o.localVerts,s=i.length;t.writeUint16(s);for(let l=0;l<s;l++){let u=i.at(l);t.writeFloat64(u.x),t.writeFloat64(u.y);}}_t(t,o.material),Lt(t,o.filter);let n=o.fluidEnabled,e=n&&o.fluidProperties!=null,r=(o.sensorEnabled?1:0)|(n?2:0)|(e?4:0);t.writeUint8(r),e&&Rt(t,o.fluidProperties);}function Gt(t,o){let n=o.zpp_inner;t.writeUint8(n.type),t.writeFloat64(o.position.x),t.writeFloat64(o.position.y),t.writeFloat64(o.rotation),t.writeFloat64(o.velocity.x),t.writeFloat64(o.velocity.y),t.writeFloat64(o.angularVel),t.writeFloat64(o.kinematicVel.x),t.writeFloat64(o.kinematicVel.y),t.writeFloat64(o.kinAngVel),t.writeFloat64(o.surfaceVel.x),t.writeFloat64(o.surfaceVel.y),t.writeFloat64(o.force.x),t.writeFloat64(o.force.y),t.writeFloat64(n.type===2?o.torque:0),t.writeUint8(n.massMode),t.writeFloat64(n.massMode===1?n.cmass:0),t.writeUint8(n.inertiaMode),t.writeFloat64(n.inertiaMode===1?n.cinertia:0),t.writeUint8(n.gravMassMode),t.writeFloat64(n.gravMassScale);let e=(o.allowMovement?1:0)|(o.allowRotation?2:0)|(o.isBullet?4:0);t.writeUint8(e);let r=o.shapes,a=r.length;t.writeUint16(a);for(let i=0;i<a;i++)jt(t,r.at(i));}var pt={PivotJoint:Bt,DistanceJoint:Ut,AngleJoint:kt,MotorJoint:Tt,LineJoint:Nt,PulleyJoint:Vt,WeldJoint:Ot};function k(t,o,n,e,r){let a=e!=null?n.get(e.zpp_inner.id)??-1:-1,i=r!=null?n.get(r.zpp_inner.id)??-1:-1;t.writeInt32(a),t.writeInt32(i);let s=o.zpp_inner,l=(s.active?1:0)|(s.ignore?2:0)|(s.stiff?4:0)|(s.breakUnderForce?8:0)|(s.breakUnderError?16:0)|(s.removeOnBreak?32:0);t.writeUint8(l),t.writeFloat64(s.frequency),t.writeFloat64(s.damping),t.writeFloat64(s.maxForce),t.writeFloat64(s.maxError);}function Wt(t,o,n){let e=o.constructor?.name??"",r=pt[e];if(r===void 0)return false;switch(t.writeUint8(r),e){case "PivotJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.anchor1.x),t.writeFloat64(a.anchor1.y),t.writeFloat64(a.anchor2.x),t.writeFloat64(a.anchor2.y);break}case "DistanceJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.anchor1.x),t.writeFloat64(a.anchor1.y),t.writeFloat64(a.anchor2.x),t.writeFloat64(a.anchor2.y),t.writeFloat64(a.jointMin),t.writeFloat64(a.jointMax);break}case "AngleJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.jointMin),t.writeFloat64(a.jointMax),t.writeFloat64(a.ratio);break}case "MotorJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.rate),t.writeFloat64(a.ratio);break}case "LineJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.anchor1.x),t.writeFloat64(a.anchor1.y),t.writeFloat64(a.anchor2.x),t.writeFloat64(a.anchor2.y),t.writeFloat64(a.direction.x),t.writeFloat64(a.direction.y),t.writeFloat64(a.jointMin),t.writeFloat64(a.jointMax);break}case "PulleyJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.anchor1.x),t.writeFloat64(a.anchor1.y),t.writeFloat64(a.anchor2.x),t.writeFloat64(a.anchor2.y),t.writeFloat64(a.anchor3.x),t.writeFloat64(a.anchor3.y),t.writeFloat64(a.anchor4.x),t.writeFloat64(a.anchor4.y),t.writeFloat64(a.jointMin),t.writeFloat64(a.jointMax),t.writeFloat64(a.ratio);break}case "WeldJoint":{let a=o;k(t,o,n,a.body1,a.body2),t.writeFloat64(a.anchor1.x),t.writeFloat64(a.anchor1.y),t.writeFloat64(a.anchor2.x),t.writeFloat64(a.anchor2.y),t.writeFloat64(a.phase);break}}return true}function Yt(t){let o=new rt,n=[],e=new Map,r=new Map;function a(c){let F=c.zpp_inner.id;if(e.has(F))return;let d=n.length;r.set(c,d),e.set(F,d),n.push(c);}let i=t.bodies,s=i.length;for(let c=0;c<s;c++)a(i.at(c));let l=t.compounds,u=l.length;for(let c=0;c<u;c++){let d=l.at(c).bodies,f=d.length;for(let p=0;p<f;p++)a(d.at(p));}let m=[],D=new Map;function M(c){if(D.has(c))return;let F=c.constructor?.name??"";pt[F]!==void 0&&(D.set(c,m.length),m.push(c));}let S=t.constraints,A=S.length;for(let c=0;c<A;c++)M(S.at(c));for(let c=0;c<u;c++){let d=l.at(c).constraints,f=d.length;for(let p=0;p<f;p++)M(d.at(p));}o.writeUint32(Pt),o.writeUint16(_),o.writeUint32(n.length),o.writeUint32(m.length),o.writeUint32(u);let h=t.gravity;o.writeFloat64(h.x),o.writeFloat64(h.y),o.writeFloat64(t.worldLinearDrag),o.writeFloat64(t.worldAngularDrag),o.writeBool(t.sortContacts),o.writeBool(t.deterministic),o.writeUint8(t.zpp_inner.bphase.is_sweep?0:1);for(let c=0;c<n.length;c++)Gt(o,n[c]);for(let c=0;c<m.length;c++)Wt(o,m[c],e);for(let c=0;c<u;c++){let F=l.at(c),d=F.bodies,f=d.length;o.writeUint16(f);for(let C=0;C<f;C++){let x=d.at(C),w=r.get(x)??0;o.writeUint32(w);}let p=F.constraints,g=p.length,I=0;for(let C=0;C<g;C++){let x=p.at(C);D.has(x)&&I++;}o.writeUint16(I);for(let C=0;C<g;C++){let x=p.at(C),w=D.get(x);w!=null&&o.writeUint32(w);}o.writeUint16(0);}return o.finish()}var it=class{constructor(o){this.pos=0;this.view=new DataView(o.buffer,o.byteOffset,o.byteLength);}readUint8(){let o=this.view.getUint8(this.pos);return this.pos+=1,o}readUint16(){let o=this.view.getUint16(this.pos,true);return this.pos+=2,o}readUint32(){let o=this.view.getUint32(this.pos,true);return this.pos+=4,o}readInt32(){let o=this.view.getInt32(this.pos,true);return this.pos+=4,o}readFloat64(){let o=this.view.getFloat64(this.pos,true);return this.pos+=8,o}readBool(){return this.readUint8()!==0}};var dt=1312903237,Xt=0,qt=1,zt=2,Ht=3,$t=4,Kt=5,Qt=6,Zt={1:chunkOFVSWS4I_cjs.aa.STATIC,2:chunkOFVSWS4I_cjs.aa.DYNAMIC,3:chunkOFVSWS4I_cjs.aa.KINEMATIC};function lt(t){let o=t.readFloat64(),n=t.readFloat64(),e=t.readFloat64(),r=t.readFloat64(),a=t.readFloat64();return new chunkOFVSWS4I_cjs.ca(o,n,e,r,a)}function ct(t){let o=new chunkOFVSWS4I_cjs.ha;return o.collisionGroup=t.readInt32(),o.collisionMask=t.readInt32(),o.sensorGroup=t.readInt32(),o.sensorMask=t.readInt32(),o.fluidGroup=t.readInt32(),o.fluidMask=t.readInt32(),o}function to(t){let o=t.readFloat64(),n=t.readFloat64(),e=new chunkOFVSWS4I_cjs.U(o,n);return t.readBool()&&(e.gravity=chunkOFVSWS4I_cjs.I.get(t.readFloat64(),t.readFloat64())),e}function oo(t){let o=t.readUint8(),n;if(o===0){let a=t.readFloat64(),i=t.readFloat64(),s=t.readFloat64(),l=lt(t),u=ct(t);n=new chunkOFVSWS4I_cjs.ga(a,chunkOFVSWS4I_cjs.I.weak(i,s),l,u);}else if(o===2){let a=t.readFloat64(),i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=lt(t),m=ct(t);n=new chunkOFVSWS4I_cjs.ja(a,i,chunkOFVSWS4I_cjs.I.weak(s,l),u,m);}else {let a=t.readUint16(),i=[];for(let u=0;u<a;u++)i.push(chunkOFVSWS4I_cjs.I.get(t.readFloat64(),t.readFloat64()));let s=lt(t),l=ct(t);n=new chunkOFVSWS4I_cjs.ia(i,s,l);}let e=t.readUint8();return n.sensorEnabled=(e&1)!==0,n.fluidEnabled=(e&2)!==0,(e&4)!==0&&(n.fluidProperties=to(t)),n}function eo(t){let o=t.readUint8(),n=Zt[o]??chunkOFVSWS4I_cjs.aa.DYNAMIC,e=t.readFloat64(),r=t.readFloat64(),a=t.readFloat64(),i=new chunkOFVSWS4I_cjs.$(n,chunkOFVSWS4I_cjs.I.weak(e,r));i.rotation=a;let s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64();o!==1&&(i.velocity=chunkOFVSWS4I_cjs.I.get(s,l),i.angularVel=u),i.kinematicVel=chunkOFVSWS4I_cjs.I.get(t.readFloat64(),t.readFloat64()),i.kinAngVel=t.readFloat64(),i.surfaceVel=chunkOFVSWS4I_cjs.I.get(t.readFloat64(),t.readFloat64());let m=t.readFloat64(),D=t.readFloat64(),M=t.readFloat64();o===2&&(i.force=chunkOFVSWS4I_cjs.I.get(m,D),i.torque=M);let S=t.readUint8(),A=t.readFloat64();S===1&&A!==0?i.mass=A:S===0&&(i.massMode=chunkOFVSWS4I_cjs.fa.DEFAULT);let h=t.readUint8(),c=t.readFloat64();h===1&&c!==0?i.inertia=c:h===0&&(i.inertiaMode=chunkOFVSWS4I_cjs.ea.DEFAULT);let F=t.readUint8(),d=t.readFloat64();F===2?(i.gravMassMode=chunkOFVSWS4I_cjs.da.SCALED,i.gravMassScale=d):F===1&&(i.gravMassMode=chunkOFVSWS4I_cjs.da.FIXED);let f=t.readUint8();i.allowMovement=(f&1)!==0,i.allowRotation=(f&2)!==0,i.isBullet=(f&4)!==0;let p=t.readUint16();for(let g=0;g<p;g++)oo(t).body=i;return i}function no(t){let o=t.readInt32(),n=t.readInt32(),e=t.readUint8(),r=t.readFloat64(),a=t.readFloat64(),i=t.readFloat64(),s=t.readFloat64();return {body1Id:o,body2Id:n,active:(e&1)!==0,ignore:(e&2)!==0,stiff:(e&4)!==0,breakUnderForce:(e&8)!==0,breakUnderError:(e&16)!==0,removeOnBreak:(e&32)!==0,frequency:r,damping:a,maxForce:i,maxError:s}}function T(t,o){t.active=o.active,t.ignore=o.ignore,t.stiff=o.stiff,t.frequency=o.frequency,t.damping=o.damping,t.maxForce=o.maxForce,t.maxError=o.maxError,t.breakUnderForce=o.breakUnderForce,t.breakUnderError=o.breakUnderError,t.removeOnBreak=o.removeOnBreak;}function ao(t,o){let n=t.readUint8(),e=no(t),r=e.body1Id>=0?o[e.body1Id]??null:null,a=e.body2Id>=0?o[e.body2Id]??null:null;switch(n){case Xt:{let i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64(),m=new chunkOFVSWS4I_cjs.qa(r,a,chunkOFVSWS4I_cjs.I.weak(i,s),chunkOFVSWS4I_cjs.I.weak(l,u));return T(m,e),m}case qt:{let i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64(),m=t.readFloat64(),D=t.readFloat64(),M=new chunkOFVSWS4I_cjs.na(r,a,chunkOFVSWS4I_cjs.I.weak(i,s),chunkOFVSWS4I_cjs.I.weak(l,u),m,D);return T(M,e),M}case zt:{let i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=new chunkOFVSWS4I_cjs.ma(r,a,i,s,l);return T(u,e),u}case Ht:{let i=t.readFloat64(),s=t.readFloat64(),l=new chunkOFVSWS4I_cjs.pa(r,a,i,s);return T(l,e),l}case $t:{let i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64(),m=t.readFloat64(),D=t.readFloat64(),M=t.readFloat64(),S=t.readFloat64(),A=new chunkOFVSWS4I_cjs.oa(r,a,chunkOFVSWS4I_cjs.I.weak(i,s),chunkOFVSWS4I_cjs.I.weak(l,u),chunkOFVSWS4I_cjs.I.weak(m,D),M,S);return T(A,e),A}case Kt:{let i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64(),m=t.readFloat64(),D=t.readFloat64(),M=t.readFloat64(),S=t.readFloat64(),A=t.readFloat64(),h=t.readFloat64(),c=t.readFloat64(),F=new chunkOFVSWS4I_cjs.ra(r,a,null,null,chunkOFVSWS4I_cjs.I.weak(i,s),chunkOFVSWS4I_cjs.I.weak(l,u),chunkOFVSWS4I_cjs.I.weak(m,D),chunkOFVSWS4I_cjs.I.weak(M,S),A,h,c);return T(F,e),F}case Qt:{let i=t.readFloat64(),s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64(),m=t.readFloat64(),D=new chunkOFVSWS4I_cjs.sa(r,a,chunkOFVSWS4I_cjs.I.weak(i,s),chunkOFVSWS4I_cjs.I.weak(l,u),m);return T(D,e),D}default:throw new Error(`nape-js binary: unknown constraint type tag ${n}`)}}function ro(t){let o=new it(t),n=o.readUint32();if(n!==dt)throw new Error(`nape-js binary: invalid magic bytes 0x${n.toString(16)} (expected 0x${dt.toString(16)})`);let e=o.readUint16();if(e!==_)throw new Error(`nape-js binary: unsupported version ${e} (expected ${_})`);let r=o.readUint32(),a=o.readUint32(),i=o.readUint32(),s=o.readFloat64(),l=o.readFloat64(),u=o.readFloat64(),m=o.readFloat64(),D=o.readBool(),M=o.readBool(),A=o.readUint8()===0?chunkOFVSWS4I_cjs.ka.SWEEP_AND_PRUNE:chunkOFVSWS4I_cjs.ka.DYNAMIC_AABB_TREE,h=new chunkOFVSWS4I_cjs.Y(chunkOFVSWS4I_cjs.I.weak(s,l),A);h.worldLinearDrag=u,h.worldAngularDrag=m,h.sortContacts=D,h.deterministic=M;let c=new Array(r);for(let p=0;p<r;p++)c[p]=eo(o);let F=new Array(a);for(let p=0;p<a;p++)F[p]=ao(o,c);let d=new Set,f=new Set;for(let p=0;p<i;p++){let g=new chunkOFVSWS4I_cjs.ba,I=o.readUint16();for(let w=0;w<I;w++){let J=o.readUint32();c[J].compound=g,d.add(J);}let C=o.readUint16();for(let w=0;w<C;w++){let J=o.readUint32();F[J].compound=g,f.add(J);}let x=o.readUint16();for(let w=0;w<x;w++)o.readUint32();g.space=h;}for(let p=0;p<r;p++)d.has(p)||(c[p].space=h);for(let p=0;p<a;p++)f.has(p)||(F[p].space=h);return h}exports.BINARY_SNAPSHOT_VERSION=_;exports.SNAPSHOT_VERSION=at;exports.spaceFromBinary=ro;exports.spaceFromJSON=Et;exports.spaceToBinary=Yt;exports.spaceToJSON=wt;//# sourceMappingURL=index.cjs.map
|
|
1
|
+
'use strict';var chunkCA2F5ISB_cjs=require('../chunk-CA2F5ISB.cjs'),chunkHQH77APJ_cjs=require('../chunk-HQH77APJ.cjs');var J=1;function s(t){return {x:t.x,y:t.y}}function Q(t){if(t==null)return null;try{let a=JSON.stringify(t);return a==="{}"?null:JSON.parse(a)}catch{return null}}function it(t){return {elasticity:t.elasticity,dynamicFriction:t.dynamicFriction,staticFriction:t.staticFriction,density:t.density,rollingFriction:t.rollingFriction}}function st(t){return {collisionGroup:t.collisionGroup,collisionMask:t.collisionMask,sensorGroup:t.sensorGroup,sensorMask:t.sensorMask,fluidGroup:t.fluidGroup,fluidMask:t.fluidMask}}function lt(t){if(t==null)return null;let a=t.gravity;return {density:t.density,viscosity:t.viscosity,gravity:a!=null?s(a):null}}function ct(t){let a=it(t.material),n=st(t.filter),e=t.fluidEnabled,o=e?lt(t.fluidProperties):null,l=t.sensorEnabled;if(t.isCircle()){let c=t,r=t.localCOM;return {type:"circle",radius:c.radius,localCOM:s(r),material:a,filter:n,sensorEnabled:l,fluidEnabled:e,fluidProperties:o}}else if(t.isCapsule()){let c=t,r=t.localCOM;return {type:"capsule",width:c.width,height:c.height,localCOM:s(r),material:a,filter:n,sensorEnabled:l,fluidEnabled:e,fluidProperties:o}}else {let r=t.localVerts,m=[],u=r.length;for(let b=0;b<u;b++)m.push(s(r.at(b)));return {type:"polygon",localVerts:m,material:a,filter:n,sensorEnabled:l,fluidEnabled:e,fluidProperties:o}}}var ut={1:"STATIC",2:"DYNAMIC",3:"KINEMATIC"},pt={0:"DEFAULT",1:"FIXED",2:"FIXED_GROUP"},mt={0:"DEFAULT",1:"FIXED",2:"FIXED_GROUP"},Dt={0:"DEFAULT",1:"FIXED",2:"SCALED"};function yt(t,a){let n=t.zpp_inner,e=pt[n.massMode]??"DEFAULT",o=mt[n.inertiaMode]??"DEFAULT",l=Dt[n.gravMassMode]??"DEFAULT",c=[],r=t.shapes,m=r.length;for(let u=0;u<m;u++)c.push(ct(r.at(u)));return {id:a,type:ut[n.type]??"DYNAMIC",position:s(t.position),rotation:t.rotation,velocity:s(t.velocity),angularVel:t.angularVel,kinematicVel:s(t.kinematicVel),kinAngVel:t.kinAngVel,surfaceVel:s(t.surfaceVel),force:s(t.force),torque:n.type===2?t.torque:0,massMode:e,mass:e==="FIXED"?n.cmass:null,inertiaMode:o,inertia:o==="FIXED"?n.cinertia:null,gravMassMode:l,gravMassScale:n.gravMassScale,allowMovement:t.allowMovement,allowRotation:t.allowRotation,bullet:t.isBullet,shapes:c,userData:Q(n.userData)}}function h(t,a,n,e){let o=t.zpp_inner,l=n!=null?a.get(n.zpp_inner.id)??null:null,c=e!=null?a.get(e.zpp_inner.id)??null:null;return {body1Id:l,body2Id:c,active:o.active,ignore:o.ignore,stiff:o.stiff,frequency:o.frequency,damping:o.damping,maxForce:o.maxForce,maxError:o.maxError,breakUnderForce:o.breakUnderForce,breakUnderError:o.breakUnderError,removeOnBreak:o.removeOnBreak,userData:Q(o.userData)}}function ft(t,a){switch(t.constructor?.name??""){case "PivotJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"PivotJoint",anchor1:s(e.anchor1),anchor2:s(e.anchor2)}}case "DistanceJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"DistanceJoint",anchor1:s(e.anchor1),anchor2:s(e.anchor2),jointMin:e.jointMin,jointMax:e.jointMax}}case "AngleJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"AngleJoint",jointMin:e.jointMin,jointMax:e.jointMax,ratio:e.ratio}}case "MotorJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"MotorJoint",rate:e.rate,ratio:e.ratio}}case "LineJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"LineJoint",anchor1:s(e.anchor1),anchor2:s(e.anchor2),direction:s(e.direction),jointMin:e.jointMin,jointMax:e.jointMax}}case "PulleyJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"PulleyJoint",anchor1:s(e.anchor1),anchor2:s(e.anchor2),anchor3:s(e.anchor3),anchor4:s(e.anchor4),jointMin:e.jointMin,jointMax:e.jointMax,ratio:e.ratio}}case "WeldJoint":{let e=t;return {...h(t,a,e.body1,e.body2),type:"WeldJoint",anchor1:s(e.anchor1),anchor2:s(e.anchor2),phase:e.phase}}default:return null}}function dt(t){let a=[],n=new Map,e=new Map;function o(i){let y=i.zpp_inner.id;if(e.has(y))return;let D=a.length;n.set(i,D),e.set(y,D),a.push(yt(i,D));}let l=t.bodies,c=l.length;for(let i=0;i<c;i++)o(l.at(i));let r=t.compounds,m=r.length;for(let i=0;i<m;i++){let D=r.at(i).bodies,C=D.length;for(let f=0;f<C;f++)o(D.at(f));}let u=[],b=new Map;function I(i){if(b.has(i))return;let y=ft(i,e);y!=null&&(b.set(i,u.length),u.push(y));}let x=t.constraints,Z=x.length;for(let i=0;i<Z;i++)I(x.at(i));for(let i=0;i<m;i++){let D=r.at(i).constraints,C=D.length;for(let f=0;f<C;f++)I(D.at(f));}let V=[];for(let i=0;i<m;i++){let y=r.at(i),D=[],C=y.bodies,f=C.length;for(let M=0;M<f;M++){let F=C.at(M),S=n.get(F);S!=null&&D.push(S);}let B=[],w=y.constraints,nt=w.length;for(let M=0;M<nt;M++){let F=w.at(M),S=b.get(F);S!=null&&B.push(S);}V.push({bodyIds:D,constraintIndices:B,childIndices:[]});}let tt=t.zpp_inner.bphase.is_sweep?"SWEEP_AND_PRUNE":"DYNAMIC_AABB_TREE",et=t.gravity;return {version:1,gravity:s(et),worldLinearDrag:t.worldLinearDrag,worldAngularDrag:t.worldAngularDrag,sortContacts:t.sortContacts,deterministic:t.deterministic,broadphase:tt,bodies:a,constraints:u,compounds:V}}function d(t){return chunkHQH77APJ_cjs.I.get(t.x,t.y)}function p(t){return chunkHQH77APJ_cjs.I.weak(t.x,t.y)}function bt(t){return new chunkHQH77APJ_cjs.ca(t.elasticity,t.dynamicFriction,t.staticFriction,t.density,t.rollingFriction)}function Mt(t){let a=new chunkHQH77APJ_cjs.ha;return a.collisionGroup=t.collisionGroup,a.collisionMask=t.collisionMask,a.sensorGroup=t.sensorGroup,a.sensorMask=t.sensorMask,a.fluidGroup=t.fluidGroup,a.fluidMask=t.fluidMask,a}function ht(t){let a=new chunkHQH77APJ_cjs.U(t.density,t.viscosity);return t.gravity!=null&&(a.gravity=d(t.gravity)),a}function gt(t){let a=bt(t.material),n=Mt(t.filter),e;if(t.type==="circle"){let o=d(t.localCOM);e=new chunkHQH77APJ_cjs.ga(t.radius,o,a,n);}else if(t.type==="capsule"){let o=d(t.localCOM);e=new chunkHQH77APJ_cjs.ja(t.width,t.height,o,a,n);}else {let o=t.localVerts.map(l=>d(l));e=new chunkHQH77APJ_cjs.ia(o,a,n);}return e.sensorEnabled=t.sensorEnabled,e.fluidEnabled=t.fluidEnabled,t.fluidEnabled&&t.fluidProperties!=null&&(e.fluidProperties=ht(t.fluidProperties)),e}function Ct(t){let a=t.type==="STATIC"?chunkHQH77APJ_cjs.aa.STATIC:t.type==="KINEMATIC"?chunkHQH77APJ_cjs.aa.KINEMATIC:chunkHQH77APJ_cjs.aa.DYNAMIC,n=new chunkHQH77APJ_cjs.$(a,p(t.position));n.rotation=t.rotation,t.type!=="STATIC"&&(n.velocity=d(t.velocity),n.angularVel=t.angularVel),n.kinematicVel=d(t.kinematicVel),n.kinAngVel=t.kinAngVel,n.surfaceVel=d(t.surfaceVel),t.type==="DYNAMIC"&&(n.force=d(t.force),n.torque=t.torque),t.massMode==="FIXED"&&t.mass!=null?n.mass=t.mass:t.massMode==="DEFAULT"&&(n.massMode=chunkHQH77APJ_cjs.fa.DEFAULT),t.inertiaMode==="FIXED"&&t.inertia!=null?n.inertia=t.inertia:t.inertiaMode==="DEFAULT"&&(n.inertiaMode=chunkHQH77APJ_cjs.ea.DEFAULT),t.gravMassMode==="SCALED"?(n.gravMassMode=chunkHQH77APJ_cjs.da.SCALED,n.gravMassScale=t.gravMassScale):t.gravMassMode==="FIXED"&&(n.gravMassMode=chunkHQH77APJ_cjs.da.FIXED),n.allowMovement=t.allowMovement,n.allowRotation=t.allowRotation,n.isBullet=t.bullet;for(let e of t.shapes)gt(e).body=n;return t.userData!=null&&Object.assign(n.userData,t.userData),n}function g(t,a){t.active=a.active,t.ignore=a.ignore,t.stiff=a.stiff,t.frequency=a.frequency,t.damping=a.damping,t.maxForce=a.maxForce,t.maxError=a.maxError,t.breakUnderForce=a.breakUnderForce,t.breakUnderError=a.breakUnderError,t.removeOnBreak=a.removeOnBreak,a.userData!=null&&Object.assign(t.userData,a.userData);}function St(t,a){let n=t.body1Id!=null?a[t.body1Id]??null:null,e=t.body2Id!=null?a[t.body2Id]??null:null;switch(t.type){case "PivotJoint":{let o=new chunkHQH77APJ_cjs.qa(n,e,p(t.anchor1),p(t.anchor2));return g(o,t),o}case "DistanceJoint":{let o=new chunkHQH77APJ_cjs.na(n,e,p(t.anchor1),p(t.anchor2),t.jointMin,t.jointMax);return g(o,t),o}case "AngleJoint":{let o=new chunkHQH77APJ_cjs.ma(n,e,t.jointMin,t.jointMax,t.ratio);return g(o,t),o}case "MotorJoint":{let o=new chunkHQH77APJ_cjs.pa(n,e,t.rate,t.ratio);return g(o,t),o}case "LineJoint":{let o=new chunkHQH77APJ_cjs.oa(n,e,p(t.anchor1),p(t.anchor2),p(t.direction),t.jointMin,t.jointMax);return g(o,t),o}case "PulleyJoint":{let o=new chunkHQH77APJ_cjs.ra(n,e,null,null,p(t.anchor1),p(t.anchor2),p(t.anchor3),p(t.anchor4),t.jointMin,t.jointMax,t.ratio);return g(o,t),o}case "WeldJoint":{let o=new chunkHQH77APJ_cjs.sa(n,e,p(t.anchor1),p(t.anchor2),t.phase);return g(o,t),o}}}function Et(t){if(t.version!==1)throw new Error(`nape-js serialization: unsupported snapshot version ${t.version} (expected ${1})`);let a=t.broadphase==="SWEEP_AND_PRUNE"?chunkHQH77APJ_cjs.ka.SWEEP_AND_PRUNE:chunkHQH77APJ_cjs.ka.DYNAMIC_AABB_TREE,n=new chunkHQH77APJ_cjs.Y(p(t.gravity),a);n.worldLinearDrag=t.worldLinearDrag,n.worldAngularDrag=t.worldAngularDrag,n.sortContacts=t.sortContacts,n.deterministic=t.deterministic??false;let e=t.bodies.map(Ct),o=t.constraints.map(r=>St(r,e)),l=new Set,c=new Set;for(let r of t.compounds){let m=new chunkHQH77APJ_cjs.ba;for(let u of r.bodyIds)e[u].compound=m,l.add(u);for(let u of r.constraintIndices)o[u].compound=m,c.add(u);m.space=n;}for(let r=0;r<e.length;r++)l.has(r)||(e[r].space=n);for(let r=0;r<o.length;r++)c.has(r)||(o[r].space=n);return n}Object.defineProperty(exports,"BINARY_SNAPSHOT_VERSION",{enumerable:true,get:function(){return chunkCA2F5ISB_cjs.a}});Object.defineProperty(exports,"spaceFromBinary",{enumerable:true,get:function(){return chunkCA2F5ISB_cjs.c}});Object.defineProperty(exports,"spaceToBinary",{enumerable:true,get:function(){return chunkCA2F5ISB_cjs.b}});exports.SNAPSHOT_VERSION=J;exports.spaceFromJSON=Et;exports.spaceToJSON=dt;//# sourceMappingURL=index.cjs.map
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|