@lagless/physics-shared 0.0.43 → 0.0.46

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/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export * from './lib/collision-layers.js';
4
4
  export * from './lib/collision-events-base.js';
5
5
  export * from './lib/physics-simulation-base.js';
6
6
  export * from './lib/physics-sync-interfaces.js';
7
+ export * from './lib/wire-collider-entity-map-rebuild.js';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,2CAA2C,CAAC"}
package/dist/index.js CHANGED
@@ -4,5 +4,6 @@ export * from './lib/collision-layers.js';
4
4
  export * from './lib/collision-events-base.js';
5
5
  export * from './lib/physics-simulation-base.js';
6
6
  export * from './lib/physics-sync-interfaces.js';
7
+ export * from './lib/wire-collider-entity-map-rebuild.js';
7
8
 
8
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './lib/body-type.js';\nexport * from './lib/collider-entity-map.js';\nexport * from './lib/collision-layers.js';\nexport * from './lib/collision-events-base.js';\nexport * from './lib/physics-simulation-base.js';\nexport * from './lib/physics-sync-interfaces.js';\n"],"names":[],"rangeMappings":";;;;;","mappings":"AAAA,cAAc,qBAAqB;AACnC,cAAc,+BAA+B;AAC7C,cAAc,4BAA4B;AAC1C,cAAc,iCAAiC;AAC/C,cAAc,mCAAmC;AACjD,cAAc,mCAAmC"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './lib/body-type.js';\nexport * from './lib/collider-entity-map.js';\nexport * from './lib/collision-layers.js';\nexport * from './lib/collision-events-base.js';\nexport * from './lib/physics-simulation-base.js';\nexport * from './lib/physics-sync-interfaces.js';\nexport * from './lib/wire-collider-entity-map-rebuild.js';\n"],"names":[],"rangeMappings":";;;;;;","mappings":"AAAA,cAAc,qBAAqB;AACnC,cAAc,+BAA+B;AAC7C,cAAc,4BAA4B;AAC1C,cAAc,iCAAiC;AAC/C,cAAc,mCAAmC;AACjD,cAAc,mCAAmC;AACjD,cAAc,4CAA4C"}
@@ -8,7 +8,13 @@ export declare class PhysicsSimulationBase extends ECSSimulation {
8
8
  private readonly _physicsWorldManager;
9
9
  private _rapierSnapshotHistory;
10
10
  private readonly _initialRapierSnapshot;
11
+ private _colliderEntityMapRebuildFn;
11
12
  constructor(config: ECSConfig, deps: ECSDeps, inputProvider: AbstractInputProvider, _physicsWorldManager: IPhysicsWorldManagerBase);
13
+ /**
14
+ * Register a callback that rebuilds the ColliderEntityMap from ECS state.
15
+ * Called automatically after rollback and state transfer to keep the map in sync.
16
+ */
17
+ setColliderEntityMapRebuild(fn: () => void): void;
12
18
  protected saveSnapshot(tick: number): void;
13
19
  protected rollback(tick: number): void;
14
20
  applyExternalState(state: ArrayBuffer, tick: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"physics-simulation-base.d.ts","sourceRoot":"","sources":["../../src/lib/physics-simulation-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAKzF,oFAAoF;AACpF,MAAM,WAAW,wBAAwB;IACvC,YAAY,IAAI,UAAU,CAAC;IAC3B,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;CACzC;AAED,qBAAa,qBAAsB,SAAQ,aAAa;IAQpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAPvC,OAAO,CAAC,sBAAsB,CAA8B;IAC5D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;gBAGlD,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,OAAO,EACb,aAAa,EAAE,qBAAqB,EACnB,oBAAoB,EAAE,wBAAwB;cAO9C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;cAKhC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkB/B,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ1E;;OAEG;IACI,yBAAyB,CAAC,cAAc,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAOhF;;OAEG;IACI,qBAAqB,IAAI,UAAU;IAI1C;;;OAGG;IACa,sBAAsB,IAAI,WAAW;IAcrD;;;OAGG;IACa,sBAAsB,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAoB9E"}
1
+ {"version":3,"file":"physics-simulation-base.d.ts","sourceRoot":"","sources":["../../src/lib/physics-simulation-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAKzF,oFAAoF;AACpF,MAAM,WAAW,wBAAwB;IACvC,YAAY,IAAI,UAAU,CAAC;IAC3B,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;CACzC;AAED,qBAAa,qBAAsB,SAAQ,aAAa;IASpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IARvC,OAAO,CAAC,sBAAsB,CAA8B;IAC5D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IACpD,OAAO,CAAC,2BAA2B,CAA6B;gBAG9D,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,OAAO,EACb,aAAa,EAAE,qBAAqB,EACnB,oBAAoB,EAAE,wBAAwB;IAOjE;;;OAGG;IACI,2BAA2B,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;cAIrC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;cAKhC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAmB/B,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ1E;;OAEG;IACI,yBAAyB,CAAC,cAAc,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQhF;;OAEG;IACI,qBAAqB,IAAI,UAAU;IAI1C;;;OAGG;IACa,sBAAsB,IAAI,WAAW;IAcrD;;;OAGG;IACa,sBAAsB,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAqB9E"}
@@ -2,6 +2,12 @@ import { ECSSimulation } from '@lagless/core';
2
2
  import { SnapshotHistory, createLogger } from '@lagless/misc';
3
3
  const log = createLogger('PhysicsSimulationBase');
4
4
  export class PhysicsSimulationBase extends ECSSimulation {
5
+ /**
6
+ * Register a callback that rebuilds the ColliderEntityMap from ECS state.
7
+ * Called automatically after rollback and state transfer to keep the map in sync.
8
+ */ setColliderEntityMapRebuild(fn) {
9
+ this._colliderEntityMapRebuildFn = fn;
10
+ }
5
11
  saveSnapshot(tick) {
6
12
  super.saveSnapshot(tick);
7
13
  this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());
@@ -20,6 +26,7 @@ export class PhysicsSimulationBase extends ECSSimulation {
20
26
  }
21
27
  this._physicsWorldManager.restoreSnapshot(rapierSnapshot);
22
28
  this._rapierSnapshotHistory.rollback(this.mem.tickManager.tick);
29
+ this._colliderEntityMapRebuildFn == null ? void 0 : this._colliderEntityMapRebuildFn.call(this);
23
30
  }
24
31
  applyExternalState(state, tick) {
25
32
  // Reset rapier snapshot history BEFORE super call — super.applyExternalState()
@@ -35,6 +42,7 @@ export class PhysicsSimulationBase extends ECSSimulation {
35
42
  this._physicsWorldManager.restoreSnapshot(rapierSnapshot);
36
43
  this._rapierSnapshotHistory = new SnapshotHistory(this._ECSConfig.snapshotHistorySize);
37
44
  this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());
45
+ this._colliderEntityMapRebuildFn == null ? void 0 : this._colliderEntityMapRebuildFn.call(this);
38
46
  }
39
47
  /**
40
48
  * Export current Rapier world snapshot for state transfer.
@@ -71,11 +79,13 @@ export class PhysicsSimulationBase extends ECSSimulation {
71
79
  // Save rapier snapshot at this tick (overwrite the empty one saved by applyExternalState)
72
80
  this._rapierSnapshotHistory = new SnapshotHistory(this._ECSConfig.snapshotHistorySize);
73
81
  this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());
82
+ this._colliderEntityMapRebuildFn == null ? void 0 : this._colliderEntityMapRebuildFn.call(this);
74
83
  this.notifyStateTransferHandlers(tick);
75
84
  }
76
85
  constructor(config, deps, inputProvider, _physicsWorldManager){
77
86
  super(config, deps, inputProvider);
78
87
  this._physicsWorldManager = _physicsWorldManager;
88
+ this._colliderEntityMapRebuildFn = null;
79
89
  this._rapierSnapshotHistory = new SnapshotHistory(config.snapshotHistorySize);
80
90
  this._initialRapierSnapshot = this._physicsWorldManager.takeSnapshot();
81
91
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/physics-simulation-base.ts"],"sourcesContent":["import { ECSConfig, ECSSimulation, AbstractInputProvider, ECSDeps } from '@lagless/core';\nimport { SnapshotHistory, createLogger } from '@lagless/misc';\n\nconst log = createLogger('PhysicsSimulationBase');\n\n/** Minimal interface for a physics world manager that supports snapshot/restore. */\nexport interface IPhysicsWorldManagerBase {\n takeSnapshot(): Uint8Array;\n restoreSnapshot(data: Uint8Array): void;\n}\n\nexport class PhysicsSimulationBase extends ECSSimulation {\n private _rapierSnapshotHistory: SnapshotHistory<Uint8Array>;\n private readonly _initialRapierSnapshot: Uint8Array;\n\n constructor(\n config: ECSConfig,\n deps: ECSDeps,\n inputProvider: AbstractInputProvider,\n private readonly _physicsWorldManager: IPhysicsWorldManagerBase,\n ) {\n super(config, deps, inputProvider);\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(config.snapshotHistorySize);\n this._initialRapierSnapshot = this._physicsWorldManager.takeSnapshot();\n }\n\n protected override saveSnapshot(tick: number): void {\n super.saveSnapshot(tick);\n this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());\n }\n\n protected override rollback(tick: number): void {\n // Rollback ECS state first (calls super which restores ArrayBuffer)\n super.rollback(tick);\n\n // Rollback Rapier world\n let rapierSnapshot: Uint8Array;\n try {\n rapierSnapshot = this._rapierSnapshotHistory.getNearest(tick);\n log.warn(`Rapier rollback to tick ${tick} succeeded`);\n } catch {\n rapierSnapshot = this._initialRapierSnapshot;\n log.warn(`Rapier rollback to tick ${tick} failed, using initial snapshot`);\n }\n\n this._physicsWorldManager.restoreSnapshot(rapierSnapshot);\n this._rapierSnapshotHistory.rollback(this.mem.tickManager.tick);\n }\n\n public override applyExternalState(state: ArrayBuffer, tick: number): void {\n // Reset rapier snapshot history BEFORE super call — super.applyExternalState()\n // calls this.saveSnapshot(tick), which writes to _rapierSnapshotHistory.\n // If we reset after, the old _lastTick causes \"Ticks must be non-decreasing\".\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(this._ECSConfig.snapshotHistorySize);\n super.applyExternalState(state, tick);\n }\n\n /**\n * Apply an external Rapier snapshot (e.g. from late-join state transfer).\n */\n public applyExternalPhysicsState(rapierSnapshot: Uint8Array, tick: number): void {\n log.info(`Applying external physics state at tick ${tick} (${rapierSnapshot.byteLength} bytes)`);\n this._physicsWorldManager.restoreSnapshot(rapierSnapshot);\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(this._ECSConfig.snapshotHistorySize);\n this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());\n }\n\n /**\n * Export current Rapier world snapshot for state transfer.\n */\n public exportPhysicsSnapshot(): Uint8Array {\n return this._physicsWorldManager.takeSnapshot();\n }\n\n /**\n * Export combined ECS + Rapier state for network transfer.\n * Format: [ecsLength:u32LE][ecsBytes][rapierBytes]\n */\n public override exportStateForTransfer(): ArrayBuffer {\n const ecsSnapshot = this.mem.exportSnapshot();\n const rapierSnapshot = this._physicsWorldManager.takeSnapshot();\n\n const blob = new ArrayBuffer(4 + ecsSnapshot.byteLength + rapierSnapshot.byteLength);\n const view = new DataView(blob);\n view.setUint32(0, ecsSnapshot.byteLength, true);\n new Uint8Array(blob, 4, ecsSnapshot.byteLength).set(new Uint8Array(ecsSnapshot));\n new Uint8Array(blob, 4 + ecsSnapshot.byteLength).set(rapierSnapshot);\n\n log.info(`exportStateForTransfer: ecs=${ecsSnapshot.byteLength} rapier=${rapierSnapshot.byteLength} total=${blob.byteLength}`);\n return blob;\n }\n\n /**\n * Apply combined ECS + Rapier state from network transfer.\n * Splits the blob, applies ECS state, restores Rapier world, saves snapshot.\n */\n public override applyStateFromTransfer(blob: ArrayBuffer, tick: number): void {\n const view = new DataView(blob);\n const ecsLength = view.getUint32(0, true);\n const ecsState = blob.slice(4, 4 + ecsLength);\n const rapierBytes = new Uint8Array(blob, 4 + ecsLength);\n\n log.info(`applyStateFromTransfer: tick=${tick} ecs=${ecsLength} rapier=${rapierBytes.byteLength}`);\n\n // Apply ECS state (calls applyExternalState → saveSnapshot)\n this.applyExternalState(ecsState, tick);\n\n // Restore Rapier world from transferred snapshot\n this._physicsWorldManager.restoreSnapshot(rapierBytes);\n\n // Save rapier snapshot at this tick (overwrite the empty one saved by applyExternalState)\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(this._ECSConfig.snapshotHistorySize);\n this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());\n\n this.notifyStateTransferHandlers(tick);\n }\n}\n"],"names":["ECSSimulation","SnapshotHistory","createLogger","log","PhysicsSimulationBase","saveSnapshot","tick","_rapierSnapshotHistory","set","_physicsWorldManager","takeSnapshot","rollback","rapierSnapshot","getNearest","warn","_initialRapierSnapshot","restoreSnapshot","mem","tickManager","applyExternalState","state","_ECSConfig","snapshotHistorySize","applyExternalPhysicsState","info","byteLength","exportPhysicsSnapshot","exportStateForTransfer","ecsSnapshot","exportSnapshot","blob","ArrayBuffer","view","DataView","setUint32","Uint8Array","applyStateFromTransfer","ecsLength","getUint32","ecsState","slice","rapierBytes","notifyStateTransferHandlers","constructor","config","deps","inputProvider"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["../../src/lib/physics-simulation-base.ts"],"sourcesContent":["import { ECSConfig, ECSSimulation, AbstractInputProvider, ECSDeps } from '@lagless/core';\nimport { SnapshotHistory, createLogger } from '@lagless/misc';\n\nconst log = createLogger('PhysicsSimulationBase');\n\n/** Minimal interface for a physics world manager that supports snapshot/restore. */\nexport interface IPhysicsWorldManagerBase {\n takeSnapshot(): Uint8Array;\n restoreSnapshot(data: Uint8Array): void;\n}\n\nexport class PhysicsSimulationBase extends ECSSimulation {\n private _rapierSnapshotHistory: SnapshotHistory<Uint8Array>;\n private readonly _initialRapierSnapshot: Uint8Array;\n private _colliderEntityMapRebuildFn: (() => void) | null = null;\n\n constructor(\n config: ECSConfig,\n deps: ECSDeps,\n inputProvider: AbstractInputProvider,\n private readonly _physicsWorldManager: IPhysicsWorldManagerBase,\n ) {\n super(config, deps, inputProvider);\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(config.snapshotHistorySize);\n this._initialRapierSnapshot = this._physicsWorldManager.takeSnapshot();\n }\n\n /**\n * Register a callback that rebuilds the ColliderEntityMap from ECS state.\n * Called automatically after rollback and state transfer to keep the map in sync.\n */\n public setColliderEntityMapRebuild(fn: () => void): void {\n this._colliderEntityMapRebuildFn = fn;\n }\n\n protected override saveSnapshot(tick: number): void {\n super.saveSnapshot(tick);\n this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());\n }\n\n protected override rollback(tick: number): void {\n // Rollback ECS state first (calls super which restores ArrayBuffer)\n super.rollback(tick);\n\n // Rollback Rapier world\n let rapierSnapshot: Uint8Array;\n try {\n rapierSnapshot = this._rapierSnapshotHistory.getNearest(tick);\n log.warn(`Rapier rollback to tick ${tick} succeeded`);\n } catch {\n rapierSnapshot = this._initialRapierSnapshot;\n log.warn(`Rapier rollback to tick ${tick} failed, using initial snapshot`);\n }\n\n this._physicsWorldManager.restoreSnapshot(rapierSnapshot);\n this._rapierSnapshotHistory.rollback(this.mem.tickManager.tick);\n this._colliderEntityMapRebuildFn?.();\n }\n\n public override applyExternalState(state: ArrayBuffer, tick: number): void {\n // Reset rapier snapshot history BEFORE super call — super.applyExternalState()\n // calls this.saveSnapshot(tick), which writes to _rapierSnapshotHistory.\n // If we reset after, the old _lastTick causes \"Ticks must be non-decreasing\".\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(this._ECSConfig.snapshotHistorySize);\n super.applyExternalState(state, tick);\n }\n\n /**\n * Apply an external Rapier snapshot (e.g. from late-join state transfer).\n */\n public applyExternalPhysicsState(rapierSnapshot: Uint8Array, tick: number): void {\n log.info(`Applying external physics state at tick ${tick} (${rapierSnapshot.byteLength} bytes)`);\n this._physicsWorldManager.restoreSnapshot(rapierSnapshot);\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(this._ECSConfig.snapshotHistorySize);\n this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());\n this._colliderEntityMapRebuildFn?.();\n }\n\n /**\n * Export current Rapier world snapshot for state transfer.\n */\n public exportPhysicsSnapshot(): Uint8Array {\n return this._physicsWorldManager.takeSnapshot();\n }\n\n /**\n * Export combined ECS + Rapier state for network transfer.\n * Format: [ecsLength:u32LE][ecsBytes][rapierBytes]\n */\n public override exportStateForTransfer(): ArrayBuffer {\n const ecsSnapshot = this.mem.exportSnapshot();\n const rapierSnapshot = this._physicsWorldManager.takeSnapshot();\n\n const blob = new ArrayBuffer(4 + ecsSnapshot.byteLength + rapierSnapshot.byteLength);\n const view = new DataView(blob);\n view.setUint32(0, ecsSnapshot.byteLength, true);\n new Uint8Array(blob, 4, ecsSnapshot.byteLength).set(new Uint8Array(ecsSnapshot));\n new Uint8Array(blob, 4 + ecsSnapshot.byteLength).set(rapierSnapshot);\n\n log.info(`exportStateForTransfer: ecs=${ecsSnapshot.byteLength} rapier=${rapierSnapshot.byteLength} total=${blob.byteLength}`);\n return blob;\n }\n\n /**\n * Apply combined ECS + Rapier state from network transfer.\n * Splits the blob, applies ECS state, restores Rapier world, saves snapshot.\n */\n public override applyStateFromTransfer(blob: ArrayBuffer, tick: number): void {\n const view = new DataView(blob);\n const ecsLength = view.getUint32(0, true);\n const ecsState = blob.slice(4, 4 + ecsLength);\n const rapierBytes = new Uint8Array(blob, 4 + ecsLength);\n\n log.info(`applyStateFromTransfer: tick=${tick} ecs=${ecsLength} rapier=${rapierBytes.byteLength}`);\n\n // Apply ECS state (calls applyExternalState → saveSnapshot)\n this.applyExternalState(ecsState, tick);\n\n // Restore Rapier world from transferred snapshot\n this._physicsWorldManager.restoreSnapshot(rapierBytes);\n\n // Save rapier snapshot at this tick (overwrite the empty one saved by applyExternalState)\n this._rapierSnapshotHistory = new SnapshotHistory<Uint8Array>(this._ECSConfig.snapshotHistorySize);\n this._rapierSnapshotHistory.set(tick, this._physicsWorldManager.takeSnapshot());\n\n this._colliderEntityMapRebuildFn?.();\n this.notifyStateTransferHandlers(tick);\n }\n}\n"],"names":["ECSSimulation","SnapshotHistory","createLogger","log","PhysicsSimulationBase","setColliderEntityMapRebuild","fn","_colliderEntityMapRebuildFn","saveSnapshot","tick","_rapierSnapshotHistory","set","_physicsWorldManager","takeSnapshot","rollback","rapierSnapshot","getNearest","warn","_initialRapierSnapshot","restoreSnapshot","mem","tickManager","applyExternalState","state","_ECSConfig","snapshotHistorySize","applyExternalPhysicsState","info","byteLength","exportPhysicsSnapshot","exportStateForTransfer","ecsSnapshot","exportSnapshot","blob","ArrayBuffer","view","DataView","setUint32","Uint8Array","applyStateFromTransfer","ecsLength","getUint32","ecsState","slice","rapierBytes","notifyStateTransferHandlers","constructor","config","deps","inputProvider"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { ECSDeps } from '@lagless/core';
2
+ import { PhysicsSimulationBase } from './physics-simulation-base.js';
3
+ import { ColliderEntityMap } from './collider-entity-map.js';
4
+ /**
5
+ * Auto-wire ColliderEntityMap rebuild from ECS state after rollback / state transfer.
6
+ * Finds PhysicsRefs component by its unique schema shape (colliderHandle + bodyHandle as Float64Array)
7
+ * and wires up a rebuild callback on the simulation.
8
+ */
9
+ export declare function wireColliderEntityMapRebuild(deps: ECSDeps, simulation: PhysicsSimulationBase, colliderEntityMap: ColliderEntityMap): void;
10
+ //# sourceMappingURL=wire-collider-entity-map-rebuild.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-collider-entity-map-rebuild.d.ts","sourceRoot":"","sources":["../../src/lib/wire-collider-entity-map-rebuild.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAI7D;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,qBAAqB,EACjC,iBAAiB,EAAE,iBAAiB,GACnC,IAAI,CAoCN"}
@@ -0,0 +1,37 @@
1
+ import { createLogger } from '@lagless/misc';
2
+ const log = createLogger('wireColliderEntityMapRebuild');
3
+ /**
4
+ * Auto-wire ColliderEntityMap rebuild from ECS state after rollback / state transfer.
5
+ * Finds PhysicsRefs component by its unique schema shape (colliderHandle + bodyHandle as Float64Array)
6
+ * and wires up a rebuild callback on the simulation.
7
+ */ export function wireColliderEntityMapRebuild(deps, simulation, colliderEntityMap) {
8
+ // Find PhysicsRefs component by its unique schema shape
9
+ const physicsRefsCtor = deps.components.find((c)=>{
10
+ const schema = c.schema;
11
+ return (schema == null ? void 0 : schema.colliderHandle) === Float64Array && (schema == null ? void 0 : schema.bodyHandle) === Float64Array;
12
+ });
13
+ if (!physicsRefsCtor) {
14
+ log.warn('PhysicsRefs component not found in ECSDeps — ColliderEntityMap rebuild will not be wired. ' + 'This is expected if the simulation does not use physics.');
15
+ return;
16
+ }
17
+ // Find filter that includes PhysicsRefs
18
+ const physicsRefsFilterCtor = deps.filters.find((f)=>{
19
+ const include = f.include;
20
+ return include == null ? void 0 : include.includes(physicsRefsCtor);
21
+ });
22
+ if (!physicsRefsFilterCtor) {
23
+ log.warn('PhysicsRefsFilter not found in ECSDeps — ColliderEntityMap rebuild will not be wired.');
24
+ return;
25
+ }
26
+ const refsInstance = simulation.mem.componentsManager.get(physicsRefsCtor);
27
+ const filterInstance = simulation.mem.filtersManager.get(physicsRefsFilterCtor);
28
+ const colliderHandles = refsInstance.unsafe.colliderHandle;
29
+ simulation.setColliderEntityMapRebuild(()=>{
30
+ colliderEntityMap.clear();
31
+ for (const entity of filterInstance){
32
+ colliderEntityMap.set(colliderHandles[entity], entity);
33
+ }
34
+ });
35
+ }
36
+
37
+ //# sourceMappingURL=wire-collider-entity-map-rebuild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/wire-collider-entity-map-rebuild.ts"],"sourcesContent":["import { ECSDeps } from '@lagless/core';\nimport { createLogger } from '@lagless/misc';\nimport { PhysicsSimulationBase } from './physics-simulation-base.js';\nimport { ColliderEntityMap } from './collider-entity-map.js';\n\nconst log = createLogger('wireColliderEntityMapRebuild');\n\n/**\n * Auto-wire ColliderEntityMap rebuild from ECS state after rollback / state transfer.\n * Finds PhysicsRefs component by its unique schema shape (colliderHandle + bodyHandle as Float64Array)\n * and wires up a rebuild callback on the simulation.\n */\nexport function wireColliderEntityMapRebuild(\n deps: ECSDeps,\n simulation: PhysicsSimulationBase,\n colliderEntityMap: ColliderEntityMap,\n): void {\n // Find PhysicsRefs component by its unique schema shape\n const physicsRefsCtor = deps.components.find(\n (c) => {\n const schema = (c as unknown as { schema?: Record<string, unknown> }).schema;\n return schema?.colliderHandle === Float64Array && schema?.bodyHandle === Float64Array;\n },\n );\n if (!physicsRefsCtor) {\n log.warn('PhysicsRefs component not found in ECSDeps — ColliderEntityMap rebuild will not be wired. ' +\n 'This is expected if the simulation does not use physics.');\n return;\n }\n\n // Find filter that includes PhysicsRefs\n const physicsRefsFilterCtor = deps.filters.find(\n (f) => {\n const include = (f as unknown as { include?: unknown[] }).include;\n return include?.includes(physicsRefsCtor);\n },\n );\n if (!physicsRefsFilterCtor) {\n log.warn('PhysicsRefsFilter not found in ECSDeps — ColliderEntityMap rebuild will not be wired.');\n return;\n }\n\n const refsInstance = simulation.mem.componentsManager.get(physicsRefsCtor);\n const filterInstance = simulation.mem.filtersManager.get(physicsRefsFilterCtor);\n const colliderHandles = (refsInstance as unknown as { unsafe: { colliderHandle: Float64Array } }).unsafe.colliderHandle;\n\n simulation.setColliderEntityMapRebuild(() => {\n colliderEntityMap.clear();\n for (const entity of filterInstance) {\n colliderEntityMap.set(colliderHandles[entity], entity);\n }\n });\n}\n"],"names":["createLogger","log","wireColliderEntityMapRebuild","deps","simulation","colliderEntityMap","physicsRefsCtor","components","find","c","schema","colliderHandle","Float64Array","bodyHandle","warn","physicsRefsFilterCtor","filters","f","include","includes","refsInstance","mem","componentsManager","get","filterInstance","filtersManager","colliderHandles","unsafe","setColliderEntityMapRebuild","clear","entity","set"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AACA,SAASA,YAAY,QAAQ,gBAAgB;AAI7C,MAAMC,MAAMD,aAAa;AAEzB;;;;CAIC,GACD,OAAO,SAASE,6BACdC,IAAa,EACbC,UAAiC,EACjCC,iBAAoC;IAEpC,wDAAwD;IACxD,MAAMC,kBAAkBH,KAAKI,UAAU,CAACC,IAAI,CAC1C,CAACC;QACC,MAAMC,SAAS,AAACD,EAAsDC,MAAM;QAC5E,OAAOA,CAAAA,0BAAAA,OAAQC,cAAc,MAAKC,gBAAgBF,CAAAA,0BAAAA,OAAQG,UAAU,MAAKD;IAC3E;IAEF,IAAI,CAACN,iBAAiB;QACpBL,IAAIa,IAAI,CAAC,+FACP;QACF;IACF;IAEA,wCAAwC;IACxC,MAAMC,wBAAwBZ,KAAKa,OAAO,CAACR,IAAI,CAC7C,CAACS;QACC,MAAMC,UAAU,AAACD,EAAyCC,OAAO;QACjE,OAAOA,2BAAAA,QAASC,QAAQ,CAACb;IAC3B;IAEF,IAAI,CAACS,uBAAuB;QAC1Bd,IAAIa,IAAI,CAAC;QACT;IACF;IAEA,MAAMM,eAAehB,WAAWiB,GAAG,CAACC,iBAAiB,CAACC,GAAG,CAACjB;IAC1D,MAAMkB,iBAAiBpB,WAAWiB,GAAG,CAACI,cAAc,CAACF,GAAG,CAACR;IACzD,MAAMW,kBAAkB,AAACN,aAAyEO,MAAM,CAAChB,cAAc;IAEvHP,WAAWwB,2BAA2B,CAAC;QACrCvB,kBAAkBwB,KAAK;QACvB,KAAK,MAAMC,UAAUN,eAAgB;YACnCnB,kBAAkB0B,GAAG,CAACL,eAAe,CAACI,OAAO,EAAEA;QACjD;IACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lagless/physics-shared",
3
- "version": "0.0.43",
3
+ "version": "0.0.46",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -39,8 +39,8 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@swc/helpers": "~0.5.11",
42
- "@lagless/core": "0.0.43",
43
- "@lagless/misc": "0.0.43"
42
+ "@lagless/core": "0.0.46",
43
+ "@lagless/misc": "0.0.46"
44
44
  },
45
45
  "devDependencies": {
46
46
  "unplugin-swc": "^1.5.7"