@forgeax/engine-physics 0.1.26 → 0.1.28

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/src/index.ts CHANGED
@@ -27,6 +27,37 @@ export {
27
27
  registerPhysicsComponents,
28
28
  rigidBodyTypeFromF32,
29
29
  } from './components';
30
+ export type {
31
+ DerivedPhysicsCandidate,
32
+ DerivedPhysicsCandidateInput,
33
+ DerivedPhysicsCandidateState,
34
+ DerivedPhysicsErrorCode,
35
+ DerivedPhysicsErrorDetail,
36
+ DerivedPhysicsFailure,
37
+ DerivedPhysicsMotion,
38
+ DerivedPhysicsPublication,
39
+ DerivedPhysicsSnapshot,
40
+ DerivedShapeSeamInput,
41
+ DerivedShapeState,
42
+ PhysicsConstraintBodyDependency,
43
+ PhysicsConstraintInput,
44
+ PhysicsContactObservation,
45
+ PhysicsMassProperties,
46
+ PhysicsQuaternion,
47
+ PhysicsVector,
48
+ PhysicsVelocityPolicy,
49
+ VoxelCell,
50
+ VoxelShapeInput,
51
+ } from './derived-physics';
52
+ export {
53
+ cloneDerivedPhysicsInput,
54
+ DERIVED_PHYSICS_LIMITS,
55
+ DerivedPhysicsError,
56
+ estimateDerivedPhysicsInputBytes,
57
+ normalizeVoxelShapeInput,
58
+ preserveCenterOfMassVelocity,
59
+ validateMassProperties,
60
+ } from './derived-physics';
30
61
  export type { PhysicsErrorCode, PhysicsErrorDetail } from './errors';
31
62
 
32
63
  export { PHYSICS_ERROR_HINTS, PhysicsError } from './errors';
@@ -5,6 +5,19 @@
5
5
  // AI users obtain it via `world.getResource<PhysicsWorld>('PhysicsWorld')`.
6
6
 
7
7
  import type { Vec2, Vec3 } from '@forgeax/engine-math';
8
+ import type { Result } from '@forgeax/engine-types';
9
+ import type {
10
+ DerivedPhysicsCandidate,
11
+ DerivedPhysicsCandidateInput,
12
+ DerivedPhysicsError,
13
+ DerivedPhysicsFailure,
14
+ DerivedPhysicsMotion,
15
+ DerivedPhysicsPublication,
16
+ DerivedPhysicsSnapshot,
17
+ DerivedShapeState,
18
+ PhysicsConstraintInput,
19
+ PhysicsContactObservation,
20
+ } from './derived-physics';
8
21
 
9
22
  /**
10
23
  * Raycast hit result — returned by `PhysicsWorld.raycast()`.
@@ -65,7 +78,7 @@ export interface PhysicsWorld {
65
78
  * (unlike `world.set(entity, Transform, { translation: ... })` on
66
79
  * dynamic bodies, which would cause a velocity spike).
67
80
  *
68
- * @param entity - the entity (must have RigidBody + Collider).
81
+ * @param entity - the entity with a registered native body.
69
82
  * @param position - new world-space position.
70
83
  */
71
84
  teleport(entity: number, position: Vec3): void;
@@ -105,7 +118,7 @@ export interface PhysicsWorld {
105
118
  *
106
119
  * Returns `true` after `ensureBody` has created a Rapier body for the entity
107
120
  * (which happens asynchronously via WASM fire-and-forget load + tick pipeline).
108
- * Always returns `false` for entities that have no `RigidBody` + `Collider`.
121
+ * A RigidBody-only 3D entity is a native body even before derived shapes arrive.
109
122
  *
110
123
  * AI-user contract: before calling `moveAndSlide` inside a per-frame driver,
111
124
  * guard with `if (!pw.hasBody(entity)) return;` to avoid `body-not-found`
@@ -113,6 +126,70 @@ export interface PhysicsWorld {
113
126
  * `physicsSyncBackend` tick that builds the body.
114
127
  */
115
128
  hasBody(entity: number): boolean;
129
+
130
+ /**
131
+ * Prepare a replacement set of local derived shapes without making it
132
+ * queryable. The Rapier 3D implementation backs these shapes with one
133
+ * native world and one ECS body; 2D backends may omit this optional seam.
134
+ */
135
+ prepareDerivedShapeCandidate?: (
136
+ input: DerivedPhysicsCandidateInput,
137
+ ) => Result<DerivedPhysicsCandidate, DerivedPhysicsError>;
138
+ /**
139
+ * Queue a prepared candidate. The optional synchronous geometry commit runs
140
+ * after fallible native preparation, before step/publication. It must either
141
+ * commit its complete ECS binding or return failure without changing it.
142
+ * Returned failure restores old physics; a thrown callback has uncertain ECS
143
+ * writes and requires rebuild. Reentrant physics access is refused.
144
+ */
145
+ admitDerivedShapeCandidate?: (
146
+ candidate: DerivedPhysicsCandidate,
147
+ commitGeometry?: () => Result<void, Error>,
148
+ ) => Result<DerivedPhysicsCandidate, DerivedPhysicsError>;
149
+ /** Borrowed ordering proof, present only inside the paired geometry commit. */
150
+ getDerivedAdmission?: (
151
+ entity?: number,
152
+ ) =>
153
+ | { readonly entity: number; readonly revision: number; readonly fixedStep: number }
154
+ | undefined;
155
+ /** Cancel a candidate that has not been published. */
156
+ cancelDerivedShapeCandidate?: (
157
+ candidate: DerivedPhysicsCandidate,
158
+ ) => Result<void, DerivedPhysicsError>;
159
+ /** Invalidate pending candidates without touching the last committed state. */
160
+ invalidateDerivedShapeCandidates?: (reason?: string) => void;
161
+ /** Read the most recent fixed-step publication for one body. */
162
+ getDerivedPublication?: (entity: number) => DerivedPhysicsPublication | undefined;
163
+ /** Read the structured failure from the latest rejected admission, if any. */
164
+ getDerivedFailure?: (entity: number) => DerivedPhysicsFailure | undefined;
165
+ /** Read the committed body type without exposing a native Rapier body. */
166
+ getDerivedBodyType?: (entity: number) => 'static' | 'dynamic' | 'kinematic' | undefined;
167
+ /** Read whether a native admission failure requires a full World rebuild. */
168
+ getDerivedRecoveryState?: () => 'ready' | 'rebuild-required';
169
+ /** Read detached mass evidence without exposing a native body handle. */
170
+ getDerivedBodyMass?: (entity: number) => number | undefined;
171
+ /** Read the committed world-space COM and velocities for one derived body. */
172
+ getDerivedMotion?: (entity: number) => DerivedPhysicsMotion | undefined;
173
+ /** Read the currently committed local shape identities for one body. */
174
+ getDerivedShapes?: (entity: number) => readonly DerivedShapeState[];
175
+ /** Read detached contact observations from the latest fixed-step drain. */
176
+ getContactObservations?: () => readonly PhysicsContactObservation[];
177
+ /** Complete the fixed-step publication after ECS writeback/contact sync. */
178
+ finalizeDerivedFixedStep?: () => void;
179
+ /** Capture portable, committed input for explicit rebuild/recovery. */
180
+ captureDerivedPhysicsState?: () => DerivedPhysicsSnapshot;
181
+ /** Restore a previously captured input through normal candidate admission. */
182
+ restoreDerivedPhysicsState?: (
183
+ snapshot: DerivedPhysicsSnapshot,
184
+ ) => Result<readonly DerivedPhysicsCandidate[], DerivedPhysicsError>;
185
+ /** Create/update/remove constraints in the same solver as ordinary bodies. */
186
+ createDerivedConstraint?: (
187
+ input: PhysicsConstraintInput,
188
+ ) => Result<{ readonly id: string; readonly revision: number }, DerivedPhysicsError>;
189
+ updateDerivedConstraint?: (
190
+ input: PhysicsConstraintInput,
191
+ ) => Result<{ readonly id: string; readonly revision: number }, DerivedPhysicsError>;
192
+ removeDerivedConstraint?: (id: string) => Result<void, DerivedPhysicsError>;
116
193
  }
117
194
 
118
195
  /** 2D raycast hit result. */
@@ -3,9 +3,9 @@
3
3
  // physicsPlugin lives in @forgeax/engine-physics (the interface package, C-9)
4
4
  // and accepts an interface->backend dependency inversion: its async apply
5
5
  // dynamic-imports the rapier 2D / 3D backend on demand. The backends are
6
- // declared as devDependencies in this package's package.json (a regular
6
+ // optional peerDependencies in this package's package.json (a regular
7
7
  // dependency would form a physics <-> rapier cycle since the backends depend on
8
- // the interface package); the consuming app declares the real runtime dep.
8
+ // the interface package); the consuming app declares the selected runtime dep.
9
9
  //
10
10
  // charter awareness:
11
11
  // P3 explicit failure: WASM load failure rejects plugin activation and the