@newkrok/nape-js 3.32.0 → 3.34.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-CA2F5ISB.cjs +2 -0
- package/dist/chunk-GPGT7DYQ.js +2 -0
- package/dist/index.cjs +1 -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 +132 -2
- package/llms.txt +65 -53
- package/package.json +14 -4
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {aa,ka,Y,ba,I,$,fa,ea,da,sa,ra,oa,pa,ma,na,qa,ga,ja,ia,ca,ha,U as U$1}from'../chunk-263GQ5UK.js';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 I.get(t.x,t.y)}function v(t){return I.weak(t.x,t.y)}function vt(t){return new ca(t.elasticity,t.dynamicFriction,t.staticFriction,t.density,t.rollingFriction)}function At(t){let o=new 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 U$1(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 ga(t.radius,r,o,n);}else if(t.type==="capsule"){let r=P(t.localCOM);e=new ja(t.width,t.height,r,o,n);}else {let r=t.localVerts.map(a=>P(a));e=new 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"?aa.STATIC:t.type==="KINEMATIC"?aa.KINEMATIC:aa.DYNAMIC,n=new $(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=fa.DEFAULT),t.inertiaMode==="FIXED"&&t.inertia!=null?n.inertia=t.inertia:t.inertiaMode==="DEFAULT"&&(n.inertiaMode=ea.DEFAULT),t.gravMassMode==="SCALED"?(n.gravMassMode=da.SCALED,n.gravMassScale=t.gravMassScale):t.gravMassMode==="FIXED"&&(n.gravMassMode=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 qa(n,e,v(t.anchor1),v(t.anchor2));return U(r,t),r}case "DistanceJoint":{let r=new na(n,e,v(t.anchor1),v(t.anchor2),t.jointMin,t.jointMax);return U(r,t),r}case "AngleJoint":{let r=new ma(n,e,t.jointMin,t.jointMax,t.ratio);return U(r,t),r}case "MotorJoint":{let r=new pa(n,e,t.rate,t.ratio);return U(r,t),r}case "LineJoint":{let r=new 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 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 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"?ka.SWEEP_AND_PRUNE:ka.DYNAMIC_AABB_TREE,n=new 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 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:aa.STATIC,2:aa.DYNAMIC,3:aa.KINEMATIC};function lt(t){let o=t.readFloat64(),n=t.readFloat64(),e=t.readFloat64(),r=t.readFloat64(),a=t.readFloat64();return new ca(o,n,e,r,a)}function ct(t){let o=new 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 U$1(o,n);return t.readBool()&&(e.gravity=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 ga(a,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 ja(a,i,I.weak(s,l),u,m);}else {let a=t.readUint16(),i=[];for(let u=0;u<a;u++)i.push(I.get(t.readFloat64(),t.readFloat64()));let s=lt(t),l=ct(t);n=new 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]??aa.DYNAMIC,e=t.readFloat64(),r=t.readFloat64(),a=t.readFloat64(),i=new $(n,I.weak(e,r));i.rotation=a;let s=t.readFloat64(),l=t.readFloat64(),u=t.readFloat64();o!==1&&(i.velocity=I.get(s,l),i.angularVel=u),i.kinematicVel=I.get(t.readFloat64(),t.readFloat64()),i.kinAngVel=t.readFloat64(),i.surfaceVel=I.get(t.readFloat64(),t.readFloat64());let m=t.readFloat64(),D=t.readFloat64(),M=t.readFloat64();o===2&&(i.force=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=fa.DEFAULT);let h=t.readUint8(),c=t.readFloat64();h===1&&c!==0?i.inertia=c:h===0&&(i.inertiaMode=ea.DEFAULT);let F=t.readUint8(),d=t.readFloat64();F===2?(i.gravMassMode=da.SCALED,i.gravMassScale=d):F===1&&(i.gravMassMode=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 qa(r,a,I.weak(i,s),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 na(r,a,I.weak(i,s),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 ma(r,a,i,s,l);return T(u,e),u}case Ht:{let i=t.readFloat64(),s=t.readFloat64(),l=new 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 oa(r,a,I.weak(i,s),I.weak(l,u),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 ra(r,a,null,null,I.weak(i,s),I.weak(l,u),I.weak(m,D),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 sa(r,a,I.weak(i,s),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?ka.SWEEP_AND_PRUNE:ka.DYNAMIC_AABB_TREE,h=new Y(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 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}export{_ as BINARY_SNAPSHOT_VERSION,at as SNAPSHOT_VERSION,ro as spaceFromBinary,Et as spaceFromJSON,Yt as spaceToBinary,wt as spaceToJSON};//# sourceMappingURL=index.js.map
|
|
1
|
+
export{a as BINARY_SNAPSHOT_VERSION,c as spaceFromBinary,b as spaceToBinary}from'../chunk-GPGT7DYQ.js';import {ka,Y,ba,I,aa,$,fa,ea,da,sa,ra,oa,pa,ma,na,qa,ga,ja,ia,ca,ha,U}from'../chunk-263GQ5UK.js';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 I.get(t.x,t.y)}function p(t){return I.weak(t.x,t.y)}function bt(t){return new ca(t.elasticity,t.dynamicFriction,t.staticFriction,t.density,t.rollingFriction)}function Mt(t){let a=new 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 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 ga(t.radius,o,a,n);}else if(t.type==="capsule"){let o=d(t.localCOM);e=new ja(t.width,t.height,o,a,n);}else {let o=t.localVerts.map(l=>d(l));e=new 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"?aa.STATIC:t.type==="KINEMATIC"?aa.KINEMATIC:aa.DYNAMIC,n=new $(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=fa.DEFAULT),t.inertiaMode==="FIXED"&&t.inertia!=null?n.inertia=t.inertia:t.inertiaMode==="DEFAULT"&&(n.inertiaMode=ea.DEFAULT),t.gravMassMode==="SCALED"?(n.gravMassMode=da.SCALED,n.gravMassScale=t.gravMassScale):t.gravMassMode==="FIXED"&&(n.gravMassMode=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 qa(n,e,p(t.anchor1),p(t.anchor2));return g(o,t),o}case "DistanceJoint":{let o=new na(n,e,p(t.anchor1),p(t.anchor2),t.jointMin,t.jointMax);return g(o,t),o}case "AngleJoint":{let o=new ma(n,e,t.jointMin,t.jointMax,t.ratio);return g(o,t),o}case "MotorJoint":{let o=new pa(n,e,t.rate,t.ratio);return g(o,t),o}case "LineJoint":{let o=new 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 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 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"?ka.SWEEP_AND_PRUNE:ka.DYNAMIC_AABB_TREE,n=new 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 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}export{J as SNAPSHOT_VERSION,Et as spaceFromJSON,dt as spaceToJSON};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/llms-full.txt
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
- **npm**: `npm install @newkrok/nape-js`
|
|
6
6
|
- **GitHub**: https://github.com/NewKrok/nape-js
|
|
7
|
-
- **API docs**: https://
|
|
8
|
-
- **Demos**: https://
|
|
7
|
+
- **API docs**: https://napejs.org/api/index.html
|
|
8
|
+
- **Demos**: https://napejs.org/examples
|
|
9
9
|
- **License**: MIT
|
|
10
10
|
- **Version**: 3.30.0
|
|
11
11
|
- **Cookbook**: https://github.com/NewKrok/nape-js/blob/master/docs/guides/cookbook.md
|
|
@@ -2073,3 +2073,133 @@ function render() {
|
|
|
2073
2073
|
}
|
|
2074
2074
|
render();
|
|
2075
2075
|
```
|
|
2076
|
+
|
|
2077
|
+
---
|
|
2078
|
+
|
|
2079
|
+
## Replay Sub-Package (`@newkrok/nape-js/replay`)
|
|
2080
|
+
|
|
2081
|
+
Record a deterministic simulation as `(initial snapshot, per-frame input log)`
|
|
2082
|
+
and replay it deterministically — same machine, another machine, days later.
|
|
2083
|
+
Built on `/serialization` plus `space.deterministic = true`. Tree-shakeable.
|
|
2084
|
+
|
|
2085
|
+
```typescript
|
|
2086
|
+
import "@newkrok/nape-js"; // engine bootstrap
|
|
2087
|
+
import { Recorder, Player, encodeReplay, decodeReplay } from "@newkrok/nape-js/replay";
|
|
2088
|
+
```
|
|
2089
|
+
|
|
2090
|
+
### Recorder
|
|
2091
|
+
|
|
2092
|
+
```typescript
|
|
2093
|
+
new Recorder<T>(space: Space, options?: { keyframeEvery?: number })
|
|
2094
|
+
```
|
|
2095
|
+
|
|
2096
|
+
Captures the initial snapshot at construction and stores user-supplied input
|
|
2097
|
+
payloads via `recordFrame`. With `keyframeEvery > 0` (default `60`), also
|
|
2098
|
+
captures intermediate snapshots for fast scrub.
|
|
2099
|
+
|
|
2100
|
+
**Methods:**
|
|
2101
|
+
- `recordFrame(input?: T | null): void` — Log a payload at the current frame
|
|
2102
|
+
and advance. Pass `null` (or omit) for input-less frames; only non-null
|
|
2103
|
+
payloads are stored. Payloads are deep-cloned via JSON (primitives
|
|
2104
|
+
fast-pathed). Throws after `finish()`.
|
|
2105
|
+
- `finish(): Replay<T>` — Seal the recording and return an immutable result.
|
|
2106
|
+
|
|
2107
|
+
**Properties:**
|
|
2108
|
+
- `frame: number` — Frames recorded so far.
|
|
2109
|
+
- `finished: boolean` — True after `finish()`.
|
|
2110
|
+
|
|
2111
|
+
### Player
|
|
2112
|
+
|
|
2113
|
+
```typescript
|
|
2114
|
+
new Player<T>(replay: Replay<T>, applyInput?: ((input: T, space: Space, frame: number) => void) | null, options?: { dt?: number; velocityIterations?: number; positionIterations?: number })
|
|
2115
|
+
```
|
|
2116
|
+
|
|
2117
|
+
Plays a recorded `Replay`. Owns its own `Space` deserialised from the initial
|
|
2118
|
+
snapshot.
|
|
2119
|
+
|
|
2120
|
+
**Lifecycle:**
|
|
2121
|
+
- `restore(): Space` — Restore initial snapshot. Idempotent (rewinds to frame 0).
|
|
2122
|
+
- `step(): void` — Apply the next recorded input via `applyInput`, then step
|
|
2123
|
+
physics by `dt`. Throws past end or before `restore()`.
|
|
2124
|
+
- `stepTo(frame: number): void` — Random-access seek. Forward jumps walk the
|
|
2125
|
+
log; backward jumps restore the latest keyframe ≤ target then step forward.
|
|
2126
|
+
|
|
2127
|
+
**Properties:**
|
|
2128
|
+
- `space: Space` — Active space (throws before `restore()`).
|
|
2129
|
+
- `frame: number` — Current frame index (0 = pre-step).
|
|
2130
|
+
- `frameCount: number` — Total frames in the replay.
|
|
2131
|
+
- `finished: boolean` — `frame >= frameCount`.
|
|
2132
|
+
- `applyInput` — Mutable; swap callback mid-playback.
|
|
2133
|
+
|
|
2134
|
+
### encodeReplay / decodeReplay
|
|
2135
|
+
|
|
2136
|
+
```typescript
|
|
2137
|
+
function encodeReplay<T>(replay: Replay<T>): Uint8Array
|
|
2138
|
+
function decodeReplay<T = unknown>(bytes: Uint8Array): Replay<T>
|
|
2139
|
+
```
|
|
2140
|
+
|
|
2141
|
+
Compact binary format: magic `RPLY`, versioned, length-prefixed snapshots,
|
|
2142
|
+
UTF-8 JSON for input payloads. Round-trip preserves frame count, inputs, and
|
|
2143
|
+
keyframes byte-for-byte. Throws on bad magic or unsupported version.
|
|
2144
|
+
|
|
2145
|
+
### validateDeterministicConfig
|
|
2146
|
+
|
|
2147
|
+
```typescript
|
|
2148
|
+
function validateDeterministicConfig(space: Space): { ok: boolean; warnings: string[] }
|
|
2149
|
+
```
|
|
2150
|
+
|
|
2151
|
+
Sanity-checks `space.deterministic = true` and friends. Pure inspection.
|
|
2152
|
+
|
|
2153
|
+
### Replay type
|
|
2154
|
+
|
|
2155
|
+
```typescript
|
|
2156
|
+
interface Replay<T> {
|
|
2157
|
+
readonly version: number;
|
|
2158
|
+
readonly initialSnapshot: Uint8Array;
|
|
2159
|
+
readonly inputs: ReadonlyArray<{ frame: number; payload: T }>;
|
|
2160
|
+
readonly keyframes: ReadonlyArray<{ frame: number; snapshot: Uint8Array }>;
|
|
2161
|
+
readonly frameCount: number;
|
|
2162
|
+
}
|
|
2163
|
+
```
|
|
2164
|
+
|
|
2165
|
+
### Determinism contract
|
|
2166
|
+
|
|
2167
|
+
Replay matches recording bit-close on the **same platform** when:
|
|
2168
|
+
|
|
2169
|
+
1. `space.deterministic = true` is set on the recording space (and survives in
|
|
2170
|
+
the snapshot).
|
|
2171
|
+
2. Both sides use a fixed `dt` and matching velocity/position iteration counts.
|
|
2172
|
+
3. The user's `applyInput` is a pure function of `(input, space, frame)` — no
|
|
2173
|
+
`Math.random()`, no wall-clock reads, no closure mutations.
|
|
2174
|
+
|
|
2175
|
+
Cross-platform bit-exact replay is not currently supported (floating-point
|
|
2176
|
+
rounding differs across CPUs). `body.userData` is NOT preserved through binary
|
|
2177
|
+
snapshots — encode it into your input payload if needed.
|
|
2178
|
+
|
|
2179
|
+
### Usage example
|
|
2180
|
+
|
|
2181
|
+
```typescript
|
|
2182
|
+
import "@newkrok/nape-js";
|
|
2183
|
+
import { Recorder, Player, encodeReplay, decodeReplay } from "@newkrok/nape-js/replay";
|
|
2184
|
+
|
|
2185
|
+
type Input = { fire?: boolean };
|
|
2186
|
+
|
|
2187
|
+
// Record
|
|
2188
|
+
space.deterministic = true;
|
|
2189
|
+
const recorder = new Recorder<Input>(space, { keyframeEvery: 60 });
|
|
2190
|
+
for (let f = 0; f < 600; f++) {
|
|
2191
|
+
const input = readInput();
|
|
2192
|
+
recorder.recordFrame(input);
|
|
2193
|
+
if (input?.fire) ball.applyImpulse(new Vec2(0, -200));
|
|
2194
|
+
space.step(1 / 60);
|
|
2195
|
+
}
|
|
2196
|
+
const blob = encodeReplay(recorder.finish());
|
|
2197
|
+
|
|
2198
|
+
// Replay
|
|
2199
|
+
const replay = decodeReplay<Input>(blob);
|
|
2200
|
+
const player = new Player(replay, (input, sp) => {
|
|
2201
|
+
if (input.fire) sp.bodies.at(1).applyImpulse(new Vec2(0, -200));
|
|
2202
|
+
});
|
|
2203
|
+
player.restore();
|
|
2204
|
+
while (!player.finished) player.step();
|
|
2205
|
+
```
|
package/llms.txt
CHANGED
|
@@ -6,10 +6,11 @@ Install: `npm install @newkrok/nape-js`
|
|
|
6
6
|
|
|
7
7
|
- [GitHub Repository](https://github.com/NewKrok/nape-js): Source code, issues, contributing guide
|
|
8
8
|
- [npm Package](https://www.npmjs.com/package/@newkrok/nape-js): Published package with TypeScript declarations
|
|
9
|
-
- [API Reference](https://
|
|
10
|
-
- [Interactive Demos](https://
|
|
9
|
+
- [API Reference](https://napejs.org/api/index.html): Full TypeDoc-generated API docs
|
|
10
|
+
- [Interactive Demos](https://napejs.org/examples): Live physics demos with source code
|
|
11
11
|
- [Full LLM Documentation](https://raw.githubusercontent.com/NewKrok/nape-js/master/packages/nape-js/llms-full.txt): Complete API reference in a single file
|
|
12
|
-
- [Cookbook](https://github.com/NewKrok/nape-js/blob/master/docs/guides/cookbook.md): Task-oriented recipes (platformer, ragdoll, fluid, serialization, etc.)
|
|
12
|
+
- [Cookbook](https://github.com/NewKrok/nape-js/blob/master/docs/guides/cookbook.md): Task-oriented recipes (platformer, ragdoll, fluid, serialization, replay, etc.)
|
|
13
|
+
- [Replay Guide](https://github.com/NewKrok/nape-js/blob/master/docs/guides/replay-guide.md): Recorder + Player + binary encode/decode + determinism contract
|
|
13
14
|
- [Troubleshooting](https://github.com/NewKrok/nape-js/blob/master/docs/guides/troubleshooting.md): Common problems and solutions
|
|
14
15
|
- [Anti-Patterns](https://github.com/NewKrok/nape-js/blob/master/docs/guides/anti-patterns.md): Common mistakes to avoid
|
|
15
16
|
- [PixiJS Integration](https://www.npmjs.com/package/@newkrok/nape-pixi) (`@newkrok/nape-pixi`): Sibling package — body/sprite sync, fixed-step render interpolation, debug draw, and off-thread physics bridge. PIXI v8.
|
|
@@ -36,92 +37,92 @@ function update() {
|
|
|
36
37
|
|
|
37
38
|
## Core Classes
|
|
38
39
|
|
|
39
|
-
- [Space](https://
|
|
40
|
-
- [Body](https://
|
|
41
|
-
- [Vec2](https://
|
|
42
|
-
- [AABB](https://
|
|
40
|
+
- [Space](https://napejs.org/api/classes/Space.html): Physics world — create with gravity, add bodies, call `step(dt)` to simulate. `space.deterministic = true` for same-platform reproducibility (multiplayer rollback/prediction)
|
|
41
|
+
- [Body](https://napejs.org/api/classes/Body.html): Rigid body with position, velocity, rotation, mass, shapes list
|
|
42
|
+
- [Vec2](https://napejs.org/api/classes/Vec2.html): 2D vector with pooling (`Vec2.get()`, `Vec2.weak()`) and arithmetic methods
|
|
43
|
+
- [AABB](https://napejs.org/api/classes/AABB.html): Axis-aligned bounding box for spatial queries
|
|
43
44
|
|
|
44
45
|
## Shapes
|
|
45
46
|
|
|
46
|
-
- [Circle](https://
|
|
47
|
-
- [Polygon](https://
|
|
48
|
-
- [Shape](https://
|
|
49
|
-
- [Edge](https://
|
|
47
|
+
- [Circle](https://napejs.org/api/classes/Circle.html): Circular collision shape with radius
|
|
48
|
+
- [Polygon](https://napejs.org/api/classes/Polygon.html): Convex polygon with factories: `Polygon.box()`, `Polygon.rect()`, `Polygon.regular()`
|
|
49
|
+
- [Shape](https://napejs.org/api/classes/Shape.html): Base class — material, filter, sensor support, cbTypes
|
|
50
|
+
- [Edge](https://napejs.org/api/classes/Edge.html): Read-only polygon edge with normal and projection data
|
|
50
51
|
|
|
51
52
|
## Physics Properties
|
|
52
53
|
|
|
53
|
-
- [Material](https://
|
|
54
|
-
- [FluidProperties](https://
|
|
55
|
-
- [InteractionFilter](https://
|
|
56
|
-
- [InteractionGroup](https://
|
|
54
|
+
- [Material](https://napejs.org/api/classes/Material.html): Elasticity, friction, density — presets: `wood()`, `steel()`, `ice()`, `rubber()`, `glass()`, `sand()`
|
|
55
|
+
- [FluidProperties](https://napejs.org/api/classes/FluidProperties.html): Density, viscosity for fluid interaction shapes
|
|
56
|
+
- [InteractionFilter](https://napejs.org/api/classes/InteractionFilter.html): Bit-mask collision/sensor/fluid filtering
|
|
57
|
+
- [InteractionGroup](https://napejs.org/api/classes/InteractionGroup.html): Group-based interaction management
|
|
57
58
|
|
|
58
59
|
## Constraints (Joints)
|
|
59
60
|
|
|
60
|
-
- [PivotJoint](https://
|
|
61
|
-
- [DistanceJoint](https://
|
|
62
|
-
- [WeldJoint](https://
|
|
63
|
-
- [AngleJoint](https://
|
|
64
|
-
- [MotorJoint](https://
|
|
65
|
-
- [LineJoint](https://
|
|
66
|
-
- [PulleyJoint](https://
|
|
67
|
-
- [Constraint](https://
|
|
61
|
+
- [PivotJoint](https://napejs.org/api/classes/PivotJoint.html): Pin two bodies at a shared anchor point
|
|
62
|
+
- [DistanceJoint](https://napejs.org/api/classes/DistanceJoint.html): Constrain distance between two anchors to [min, max]
|
|
63
|
+
- [WeldJoint](https://napejs.org/api/classes/WeldJoint.html): Fix relative position and rotation angle
|
|
64
|
+
- [AngleJoint](https://napejs.org/api/classes/AngleJoint.html): Constrain relative angle to [min, max] with optional ratio
|
|
65
|
+
- [MotorJoint](https://napejs.org/api/classes/MotorJoint.html): Drive relative angular velocity to a target rate
|
|
66
|
+
- [LineJoint](https://napejs.org/api/classes/LineJoint.html): Constrain anchor to slide along a line direction
|
|
67
|
+
- [PulleyJoint](https://napejs.org/api/classes/PulleyJoint.html): Constrain weighted sum of two distances (pulley/rope)
|
|
68
|
+
- [Constraint](https://napejs.org/api/classes/Constraint.html): Base class — stiff/soft, frequency, damping, breaking, maxForce
|
|
68
69
|
|
|
69
70
|
## Callbacks & Events
|
|
70
71
|
|
|
71
|
-
- [InteractionListener](https://
|
|
72
|
-
- [BodyListener](https://
|
|
73
|
-
- [ConstraintListener](https://
|
|
74
|
-
- [PreListener](https://
|
|
75
|
-
- [CbType](https://
|
|
76
|
-
- [CbEvent](https://
|
|
72
|
+
- [InteractionListener](https://napejs.org/api/classes/InteractionListener.html): Listen for BEGIN/ONGOING/END collision, sensor, or fluid events
|
|
73
|
+
- [BodyListener](https://napejs.org/api/classes/BodyListener.html): Listen for WAKE/SLEEP body state changes
|
|
74
|
+
- [ConstraintListener](https://napejs.org/api/classes/ConstraintListener.html): Listen for BREAK constraint events
|
|
75
|
+
- [PreListener](https://napejs.org/api/classes/PreListener.html): Pre-collision handler — filter or modify collisions before solving
|
|
76
|
+
- [CbType](https://napejs.org/api/classes/CbType.html): Tag bodies/shapes/constraints for selective callback filtering
|
|
77
|
+
- [CbEvent](https://napejs.org/api/classes/CbEvent.html): Event types — BEGIN, ONGOING, END, WAKE, SLEEP, BREAK, PRE
|
|
77
78
|
|
|
78
79
|
## Collision & Dynamics
|
|
79
80
|
|
|
80
|
-
- [Arbiter](https://
|
|
81
|
-
- [CollisionArbiter](https://
|
|
82
|
-
- [FluidArbiter](https://
|
|
83
|
-
- [Contact](https://
|
|
81
|
+
- [Arbiter](https://napejs.org/api/classes/Arbiter.html): Interaction data between two shapes (base class)
|
|
82
|
+
- [CollisionArbiter](https://napejs.org/api/classes/CollisionArbiter.html): Collision contacts, normal, impulses, kinetic energy
|
|
83
|
+
- [FluidArbiter](https://napejs.org/api/classes/FluidArbiter.html): Fluid overlap, buoyancy/drag impulses
|
|
84
|
+
- [Contact](https://napejs.org/api/classes/Contact.html): Single contact point — position, penetration, friction
|
|
84
85
|
|
|
85
86
|
## Geometry Utilities
|
|
86
87
|
|
|
87
|
-
- [Ray](https://
|
|
88
|
-
- [Mat23](https://
|
|
89
|
-
- [Geom](https://
|
|
90
|
-
- [MarchingSquares](https://
|
|
88
|
+
- [Ray](https://napejs.org/api/classes/Ray.html): Ray for raycasting queries with origin, direction, maxDistance
|
|
89
|
+
- [Mat23](https://napejs.org/api/classes/Mat23.html): 2x3 affine transform matrix — rotation, translation, scale
|
|
90
|
+
- [Geom](https://napejs.org/api/classes/Geom.html): Static utilities — distance queries, ray tests, polygon operations
|
|
91
|
+
- [MarchingSquares](https://napejs.org/api/classes/MarchingSquares.html): Contour extraction from scalar fields
|
|
91
92
|
|
|
92
93
|
## Destruction / Fracture
|
|
93
94
|
|
|
94
|
-
- [fractureBody](https://
|
|
95
|
-
- [computeVoronoi](https://
|
|
96
|
-
- [generateFractureSites](https://
|
|
95
|
+
- [fractureBody](https://napejs.org/api/functions/fractureBody.html): Shatter a polygon body into Voronoi fragments — `fractureBody(body, impactPoint, { fragmentCount?, explosionImpulse?, random? })`
|
|
96
|
+
- [computeVoronoi](https://napejs.org/api/functions/computeVoronoi.html): Raw Voronoi diagram computation from point set
|
|
97
|
+
- [generateFractureSites](https://napejs.org/api/functions/generateFractureSites.html): Generate random fracture site points within a polygon
|
|
97
98
|
|
|
98
99
|
## Helpers
|
|
99
100
|
|
|
100
101
|
Higher-level building blocks layered on top of the engine — opt-in modules.
|
|
101
102
|
|
|
102
|
-
- [CharacterController](https://
|
|
103
|
-
- [RadialGravityField](https://
|
|
104
|
-
- [ParticleEmitter](https://
|
|
103
|
+
- [CharacterController](https://napejs.org/api/classes/CharacterController.html): Velocity-based 2D platformer controller with ground/slope/wall raycasts, coyote-time, one-way platforms, moving-platform inheritance, and an overridable `down` direction (radial-gravity worlds)
|
|
104
|
+
- [RadialGravityField](https://napejs.org/api/classes/RadialGravityField.html) / [RadialGravityFieldGroup](https://napejs.org/api/classes/RadialGravityFieldGroup.html): Point-source gravity field with `inverse-square` / `inverse` / `constant` / custom falloff, `maxRadius` / `softening` / `minRadius`, body filter, mass scaling — replaces hand-rolled `body.force = ...` loops for orbital, planet, and multi-body scenarios
|
|
105
|
+
- [ParticleEmitter](https://napejs.org/api/classes/ParticleEmitter.html) / [ParticleEmitterGroup](https://napejs.org/api/classes/ParticleEmitterGroup.html): Physics-aware particle emitter — pooled `Body` swarm with continuous (`rate`) / periodic (`burstCount` + `burstInterval`) / manual (`emit(n)`) spawning, configurable spawn (`point` / `rect` / `circle` / `arc` / custom) and velocity (`fixed` / `cone` / `radial` / custom) patterns, deterministic RNG, world-space `bounds`, `selfCollision` toggle, lifecycle hooks (`onSpawn` / `onUpdate` / `onDeath` / `onCollide` with `requestKill`)
|
|
105
106
|
- `buildTilemapBody` / `meshTilemap` / `tiledLayerToGrid` / `ldtkLayerToGrid`: Greedy-meshed collision body from a 2D tile grid (5–50× fewer shapes vs one-polygon-per-cell), with built-in parsers for Tiled JSON tile layers and LDtk IntGrid layers
|
|
106
|
-
- [TriggerZone](https://
|
|
107
|
-
- [createConcaveBody](https://
|
|
107
|
+
- [TriggerZone](https://napejs.org/api/classes/TriggerZone.html): Sensor zone with `onEnter` / `onExit` callbacks — wraps the BEGIN/END `InteractionListener` plumbing
|
|
108
|
+
- [createConcaveBody](https://napejs.org/api/functions/createConcaveBody.html): Decomposes a concave outline into convex polygons and packs them into a single body
|
|
108
109
|
|
|
109
110
|
## Enums
|
|
110
111
|
|
|
111
|
-
- [BodyType](https://
|
|
112
|
-
- [ShapeType](https://
|
|
113
|
-
- [Broadphase](https://
|
|
114
|
-
- [InteractionType](https://
|
|
115
|
-
- [ArbiterType](https://
|
|
112
|
+
- [BodyType](https://napejs.org/api/classes/BodyType.html): STATIC, DYNAMIC, KINEMATIC
|
|
113
|
+
- [ShapeType](https://napejs.org/api/classes/ShapeType.html): CIRCLE, POLYGON
|
|
114
|
+
- [Broadphase](https://napejs.org/api/classes/Broadphase.html): DYNAMIC_AABB_TREE (default), SWEEP_AND_PRUNE, SPATIAL_HASH
|
|
115
|
+
- [InteractionType](https://napejs.org/api/classes/InteractionType.html): COLLISION, SENSOR, FLUID, ANY
|
|
116
|
+
- [ArbiterType](https://napejs.org/api/classes/ArbiterType.html): COLLISION, SENSOR, FLUID
|
|
116
117
|
|
|
117
118
|
## Grouping & Hierarchy
|
|
118
119
|
|
|
119
|
-
- [Compound](https://
|
|
120
|
-
- [Interactor](https://
|
|
120
|
+
- [Compound](https://napejs.org/api/classes/Compound.html): Hierarchical grouping of bodies, constraints, and sub-compounds
|
|
121
|
+
- [Interactor](https://napejs.org/api/classes/Interactor.html): Base class for Body, Shape, Compound — type casting, cbTypes
|
|
121
122
|
|
|
122
123
|
## Collections
|
|
123
124
|
|
|
124
|
-
- [NapeList](https://
|
|
125
|
+
- [NapeList](https://napejs.org/api/classes/NapeList.html): Generic iterable list with `for...of` support, add/remove/push/pop
|
|
125
126
|
|
|
126
127
|
## Web Worker (`@newkrok/nape-js/worker`)
|
|
127
128
|
|
|
@@ -129,3 +130,14 @@ Higher-level building blocks layered on top of the engine — opt-in modules.
|
|
|
129
130
|
- `buildWorkerScript(napeUrl)`: Generate self-contained worker script for inline Blob or hosted file
|
|
130
131
|
- `BodyTransform`: `{ x, y, rotation }` per-body transform read from shared buffer
|
|
131
132
|
- `FLOATS_PER_BODY`, `HEADER_FLOATS`: Buffer layout constants
|
|
133
|
+
|
|
134
|
+
## Replay (`@newkrok/nape-js/replay`)
|
|
135
|
+
|
|
136
|
+
Record a deterministic simulation and play it back. Built on `/serialization` + `space.deterministic = true`. Tree-shakeable; only loads when imported.
|
|
137
|
+
|
|
138
|
+
- [Recorder](https://napejs.org/api/classes/Recorder.html)`<T>`: Captures the initial snapshot at construction, then `recordFrame(input)` logs an input payload per frame. Optional `keyframeEvery` (default 60) records intermediate snapshots for fast scrub. `finish()` returns an immutable `Replay<T>`.
|
|
139
|
+
- [Player](https://napejs.org/api/classes/Player.html)`<T>`: Owns its own deserialised `Space`. `restore()` rewinds to frame 0; `step()` applies the next recorded input (via the user's `applyInput` callback) and steps physics; `stepTo(frame)` does random-access scrub (uses keyframes for backward jumps).
|
|
140
|
+
- [encodeReplay](https://napejs.org/api/functions/encodeReplay.html) / [decodeReplay](https://napejs.org/api/functions/decodeReplay.html): Compact binary format (magic `RPLY`, versioned, length-prefixed snapshots, UTF-8 JSON payloads). Round-trips byte-for-byte.
|
|
141
|
+
- [validateDeterministicConfig](https://napejs.org/api/functions/validateDeterministicConfig.html): Sanity-checks `space.deterministic = true` etc.; returns `{ ok, warnings }`.
|
|
142
|
+
|
|
143
|
+
**Determinism contract** — replay matches recording when (a) `space.deterministic = true`, (b) fixed `dt` and matching iteration counts on both sides, (c) the user's `applyInput` is a pure function of `(input, space, frame)`. Same-platform soft determinism only (floating-point rounding differs across CPUs).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newkrok/nape-js",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.34.0",
|
|
4
4
|
"description": "High-performance 2D physics engine for TypeScript & JavaScript — rigid bodies, constraints, fluid simulation, raycasting, and deterministic multiplayer. Tree-shakeable, zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -49,6 +49,16 @@
|
|
|
49
49
|
"default": "./dist/serialization/index.cjs"
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
|
+
"./replay": {
|
|
53
|
+
"import": {
|
|
54
|
+
"types": "./dist/replay/index.d.ts",
|
|
55
|
+
"default": "./dist/replay/index.js"
|
|
56
|
+
},
|
|
57
|
+
"require": {
|
|
58
|
+
"types": "./dist/replay/index.d.cts",
|
|
59
|
+
"default": "./dist/replay/index.cjs"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
52
62
|
"./worker": {
|
|
53
63
|
"import": {
|
|
54
64
|
"types": "./dist/worker/index.d.ts",
|
|
@@ -70,8 +80,8 @@
|
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
82
|
},
|
|
73
|
-
"llms": "https://
|
|
74
|
-
"llmsFull": "https://
|
|
83
|
+
"llms": "https://napejs.org/llms.txt",
|
|
84
|
+
"llmsFull": "https://napejs.org/llms-full.txt",
|
|
75
85
|
"files": [
|
|
76
86
|
"dist",
|
|
77
87
|
"!dist/**/*.map",
|
|
@@ -119,5 +129,5 @@
|
|
|
119
129
|
"bugs": {
|
|
120
130
|
"url": "https://github.com/NewKrok/nape-js/issues"
|
|
121
131
|
},
|
|
122
|
-
"homepage": "https://
|
|
132
|
+
"homepage": "https://napejs.org/"
|
|
123
133
|
}
|