@game_engine/physics-adapter 0.1.0-alpha.1 → 0.1.0-alpha.2
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/README.md +14 -14
- package/dist/index.d.ts +39 -3
- package/dist/index.js +104 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# @game_engine/physics-adapter
|
|
2
|
-
|
|
3
|
-
Engine-neutral physics adapter contracts for Agent Engine.
|
|
4
|
-
|
|
5
|
-
This package defines the boundary between Agent Engine ECS/source data and optional physics backends. It does not include a physics engine and must stay free of backend-specific dependencies.
|
|
6
|
-
|
|
7
|
-
Adapter inputs are plain entities with `Transform`, `Velocity`, `Collider`, `RigidBody`, and `PhysicsMaterial` components. Adapter outputs are deterministic structured snapshots, contacts, grounding hints, and diagnostics.
|
|
8
|
-
|
|
9
|
-
Use `comparePhysicsStepResults` when comparing optional backends. It summarizes body ids, static body positions, contact pairs, and diagnostic codes so tests can compare adapter health without requiring identical solver floating-point output.
|
|
10
|
-
|
|
11
|
-
The current Rapier vs Planck evaluation is documented in
|
|
12
|
-
[`docs/physics-adapter-evaluation.md`](../../docs/physics-adapter-evaluation.md).
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
# @game_engine/physics-adapter
|
|
2
|
+
|
|
3
|
+
Engine-neutral physics adapter contracts for Agent Engine.
|
|
4
|
+
|
|
5
|
+
This package defines the boundary between Agent Engine ECS/source data and optional physics backends. It does not include a physics engine and must stay free of backend-specific dependencies.
|
|
6
|
+
|
|
7
|
+
Adapter inputs are plain entities with `Transform`, `Velocity`, `Collider`, `RigidBody`, and `PhysicsMaterial` components. Adapter outputs are deterministic structured snapshots, contacts, grounding hints, and diagnostics.
|
|
8
|
+
|
|
9
|
+
Use `comparePhysicsStepResults` when comparing optional backends. It summarizes body ids, static body positions, contact pairs, and diagnostic codes so tests can compare adapter health without requiring identical solver floating-point output.
|
|
10
|
+
|
|
11
|
+
The current Rapier vs Planck evaluation is documented in
|
|
12
|
+
[`docs/physics-adapter-evaluation.md`](../../docs/physics-adapter-evaluation.md).
|
|
13
|
+
|
|
14
|
+
Production headless and browser gameplay runtimes construct the Planck implementation of this boundary. `@game_engine/core` keeps deterministic `KinematicPhysics` only for explicit tests, references, and custom registries; Rapier remains an optional comparison backend.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityId, ComponentName, ComponentValue, Vector2, Transform, Velocity, Collider, RigidBody, PhysicsMaterial, World } from '@game_engine/core';
|
|
1
|
+
import { EntityId, ComponentName, ComponentValue, Vector2, Transform, Velocity, PhysicsJoint, Collider, RigidBody, PhysicsMaterial, World } from '@game_engine/core';
|
|
2
2
|
|
|
3
3
|
type PhysicsAdapterSeverity = "warning" | "error";
|
|
4
4
|
type PhysicsBodyType = "static" | "dynamic" | "kinematic";
|
|
@@ -29,6 +29,13 @@ interface PhysicsContactSnapshot {
|
|
|
29
29
|
otherEntityId: EntityId;
|
|
30
30
|
grounded?: boolean;
|
|
31
31
|
}
|
|
32
|
+
type PhysicsCollisionPhase = "start" | "stay" | "end";
|
|
33
|
+
interface PhysicsCollisionEvent {
|
|
34
|
+
phase: PhysicsCollisionPhase;
|
|
35
|
+
entityAId: EntityId;
|
|
36
|
+
entityBId: EntityId;
|
|
37
|
+
sensor: boolean;
|
|
38
|
+
}
|
|
32
39
|
interface PhysicsGroundingSnapshot {
|
|
33
40
|
grounded: boolean;
|
|
34
41
|
groundEntityId?: EntityId;
|
|
@@ -41,17 +48,40 @@ interface PhysicsBodySnapshot {
|
|
|
41
48
|
grounded?: PhysicsGroundingSnapshot;
|
|
42
49
|
contacts: PhysicsContactSnapshot[];
|
|
43
50
|
}
|
|
51
|
+
interface PhysicsJointSnapshot {
|
|
52
|
+
entityId: EntityId;
|
|
53
|
+
type: PhysicsJoint["type"];
|
|
54
|
+
bodyAId: EntityId;
|
|
55
|
+
bodyBId: EntityId;
|
|
56
|
+
}
|
|
57
|
+
interface PhysicsQueryFilter {
|
|
58
|
+
collisionLayers?: number[];
|
|
59
|
+
includeSensors?: boolean;
|
|
60
|
+
}
|
|
61
|
+
interface PhysicsQueryHit {
|
|
62
|
+
entityId: EntityId;
|
|
63
|
+
bodyType: PhysicsBodyType;
|
|
64
|
+
sensor: boolean;
|
|
65
|
+
point?: Vector2;
|
|
66
|
+
normal?: Vector2;
|
|
67
|
+
fraction?: number;
|
|
68
|
+
}
|
|
44
69
|
interface PhysicsStepResult {
|
|
45
70
|
ok: boolean;
|
|
46
71
|
frame: number;
|
|
47
72
|
deltaSeconds: number;
|
|
48
73
|
bodies: PhysicsBodySnapshot[];
|
|
49
74
|
contacts: PhysicsContactSnapshot[];
|
|
75
|
+
collisionEvents: PhysicsCollisionEvent[];
|
|
76
|
+
joints?: PhysicsJointSnapshot[];
|
|
50
77
|
diagnostics: PhysicsAdapterDiagnostics;
|
|
51
78
|
}
|
|
52
79
|
interface PhysicsAdapterWorld {
|
|
53
80
|
step(deltaSeconds: number, options?: PhysicsStepOptions): PhysicsStepResult;
|
|
54
81
|
snapshot(options?: PhysicsStepOptions): PhysicsStepResult;
|
|
82
|
+
queryPoint?(point: Vector2, filter?: PhysicsQueryFilter): PhysicsQueryHit[];
|
|
83
|
+
queryAabb?(lowerBound: Vector2, upperBound: Vector2, filter?: PhysicsQueryFilter): PhysicsQueryHit[];
|
|
84
|
+
raycast?(from: Vector2, to: Vector2, filter?: PhysicsQueryFilter): PhysicsQueryHit[];
|
|
55
85
|
dispose?(): void;
|
|
56
86
|
}
|
|
57
87
|
interface PhysicsAdapter {
|
|
@@ -64,6 +94,7 @@ interface PhysicsComponents {
|
|
|
64
94
|
collider?: Collider;
|
|
65
95
|
rigidBody?: RigidBody;
|
|
66
96
|
physicsMaterial?: PhysicsMaterial;
|
|
97
|
+
physicsJoint?: PhysicsJoint;
|
|
67
98
|
}
|
|
68
99
|
interface PhysicsBackendComparisonInput {
|
|
69
100
|
backend: string;
|
|
@@ -89,14 +120,19 @@ interface PhysicsBackendComparison {
|
|
|
89
120
|
diagnosticsShapeCompatible: boolean;
|
|
90
121
|
}
|
|
91
122
|
declare function createPhysicsAdapterInputFromWorld(world: World): PhysicsAdapterWorldInput;
|
|
123
|
+
declare function applyPhysicsStepResultToWorld(world: World, result: PhysicsStepResult): void;
|
|
92
124
|
declare function clonePhysicsAdapterInput(input: PhysicsAdapterWorldInput): PhysicsAdapterWorldInput;
|
|
93
125
|
declare function readPhysicsComponents(entity: PhysicsAdapterEntity): PhysicsComponents;
|
|
94
126
|
declare function resolvePhysicsBodyType(components: PhysicsComponents): PhysicsBodyType;
|
|
95
127
|
declare function sortPhysicsBodySnapshots(bodies: PhysicsBodySnapshot[]): PhysicsBodySnapshot[];
|
|
96
128
|
declare function sortPhysicsContacts(contacts: PhysicsContactSnapshot[]): PhysicsContactSnapshot[];
|
|
97
|
-
declare function
|
|
129
|
+
declare function sortPhysicsCollisionEvents(events: PhysicsCollisionEvent[]): PhysicsCollisionEvent[];
|
|
130
|
+
declare function sortPhysicsJointSnapshots(joints: PhysicsJointSnapshot[]): PhysicsJointSnapshot[];
|
|
131
|
+
declare function sortPhysicsQueryHits(hits: PhysicsQueryHit[]): PhysicsQueryHit[];
|
|
132
|
+
declare function createPhysicsStepResult(fields: Omit<PhysicsStepResult, "ok" | "bodies" | "contacts" | "collisionEvents" | "diagnostics"> & {
|
|
98
133
|
bodies?: PhysicsBodySnapshot[];
|
|
99
134
|
contacts?: PhysicsContactSnapshot[];
|
|
135
|
+
collisionEvents?: PhysicsCollisionEvent[];
|
|
100
136
|
diagnostics?: PhysicsAdapterDiagnostics;
|
|
101
137
|
}): PhysicsStepResult;
|
|
102
138
|
declare function createPhysicsDiagnostic(diagnostic: PhysicsAdapterDiagnostic): PhysicsAdapterDiagnostic;
|
|
@@ -105,4 +141,4 @@ declare function comparePhysicsStepResults(inputs: PhysicsBackendComparisonInput
|
|
|
105
141
|
declare function roundDeterministic(value: number): number;
|
|
106
142
|
declare function roundVector2(value: Vector2): Vector2;
|
|
107
143
|
|
|
108
|
-
export { type PhysicsAdapter, type PhysicsAdapterCreateOptions, type PhysicsAdapterDiagnostic, type PhysicsAdapterDiagnostics, type PhysicsAdapterEntity, type PhysicsAdapterSeverity, type PhysicsAdapterWorld, type PhysicsAdapterWorldInput, type PhysicsBackendComparison, type PhysicsBackendComparisonInput, type PhysicsBackendResultSummary, type PhysicsBodySnapshot, type PhysicsBodyType, type PhysicsComponents, type PhysicsContactSnapshot, type PhysicsGroundingSnapshot, type PhysicsStaticBodySummary, type PhysicsStepOptions, type PhysicsStepResult, clonePhysicsAdapterInput, comparePhysicsStepResults, createPhysicsAdapterInputFromWorld, createPhysicsDiagnostic, createPhysicsStepResult, readPhysicsComponents, resolvePhysicsBodyType, roundDeterministic, roundVector2, sortPhysicsBodySnapshots, sortPhysicsContacts, summarizePhysicsStepResult };
|
|
144
|
+
export { type PhysicsAdapter, type PhysicsAdapterCreateOptions, type PhysicsAdapterDiagnostic, type PhysicsAdapterDiagnostics, type PhysicsAdapterEntity, type PhysicsAdapterSeverity, type PhysicsAdapterWorld, type PhysicsAdapterWorldInput, type PhysicsBackendComparison, type PhysicsBackendComparisonInput, type PhysicsBackendResultSummary, type PhysicsBodySnapshot, type PhysicsBodyType, type PhysicsCollisionEvent, type PhysicsCollisionPhase, type PhysicsComponents, type PhysicsContactSnapshot, type PhysicsGroundingSnapshot, type PhysicsJointSnapshot, type PhysicsQueryFilter, type PhysicsQueryHit, type PhysicsStaticBodySummary, type PhysicsStepOptions, type PhysicsStepResult, applyPhysicsStepResultToWorld, clonePhysicsAdapterInput, comparePhysicsStepResults, createPhysicsAdapterInputFromWorld, createPhysicsDiagnostic, createPhysicsStepResult, readPhysicsComponents, resolvePhysicsBodyType, roundDeterministic, roundVector2, sortPhysicsBodySnapshots, sortPhysicsCollisionEvents, sortPhysicsContacts, sortPhysicsJointSnapshots, sortPhysicsQueryHits, summarizePhysicsStepResult };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,32 @@ function createPhysicsAdapterInputFromWorld(world) {
|
|
|
4
4
|
entities: world.listEntities().map((entity) => cloneAdapterEntity(entity))
|
|
5
5
|
};
|
|
6
6
|
}
|
|
7
|
+
function applyPhysicsStepResultToWorld(world, result) {
|
|
8
|
+
for (const body of result.bodies) {
|
|
9
|
+
const entity = world.getEntity(body.entityId);
|
|
10
|
+
if (!entity) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
const transform = entity.components.Transform;
|
|
14
|
+
if (transform && body.transform) {
|
|
15
|
+
transform.position = [...body.transform.position];
|
|
16
|
+
transform.rotation = body.transform.rotation;
|
|
17
|
+
}
|
|
18
|
+
const velocity = entity.components.Velocity;
|
|
19
|
+
if (velocity && body.velocity) {
|
|
20
|
+
velocity.linear = [...body.velocity.linear];
|
|
21
|
+
}
|
|
22
|
+
const groundedState = entity.components.GroundedState;
|
|
23
|
+
if (groundedState) {
|
|
24
|
+
groundedState.grounded = body.grounded?.grounded === true;
|
|
25
|
+
if (body.grounded?.groundEntityId) {
|
|
26
|
+
groundedState.groundEntityId = body.grounded.groundEntityId;
|
|
27
|
+
} else {
|
|
28
|
+
delete groundedState.groundEntityId;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
7
33
|
function clonePhysicsAdapterInput(input) {
|
|
8
34
|
return {
|
|
9
35
|
entities: input.entities.map((entity) => cloneAdapterEntity(entity))
|
|
@@ -15,7 +41,8 @@ function readPhysicsComponents(entity) {
|
|
|
15
41
|
velocity: readVelocity(entity.components.Velocity),
|
|
16
42
|
collider: readCollider(entity.components.Collider),
|
|
17
43
|
rigidBody: readRigidBody(entity.components.RigidBody),
|
|
18
|
-
physicsMaterial: readPhysicsMaterial(entity.components.PhysicsMaterial)
|
|
44
|
+
physicsMaterial: readPhysicsMaterial(entity.components.PhysicsMaterial),
|
|
45
|
+
physicsJoint: readPhysicsJoint(entity.components.PhysicsJoint)
|
|
19
46
|
};
|
|
20
47
|
}
|
|
21
48
|
function resolvePhysicsBodyType(components) {
|
|
@@ -33,9 +60,31 @@ function sortPhysicsContacts(contacts) {
|
|
|
33
60
|
return entityOrder !== 0 ? entityOrder : left.otherEntityId.localeCompare(right.otherEntityId);
|
|
34
61
|
});
|
|
35
62
|
}
|
|
63
|
+
function sortPhysicsCollisionEvents(events) {
|
|
64
|
+
const phaseOrder = { start: 0, stay: 1, end: 2 };
|
|
65
|
+
return [...events].sort((left, right) => {
|
|
66
|
+
const entityAOrder = left.entityAId.localeCompare(right.entityAId);
|
|
67
|
+
if (entityAOrder !== 0) {
|
|
68
|
+
return entityAOrder;
|
|
69
|
+
}
|
|
70
|
+
const entityBOrder = left.entityBId.localeCompare(right.entityBId);
|
|
71
|
+
return entityBOrder !== 0 ? entityBOrder : phaseOrder[left.phase] - phaseOrder[right.phase];
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function sortPhysicsJointSnapshots(joints) {
|
|
75
|
+
return [...joints].sort((left, right) => left.entityId.localeCompare(right.entityId));
|
|
76
|
+
}
|
|
77
|
+
function sortPhysicsQueryHits(hits) {
|
|
78
|
+
return [...hits].sort((left, right) => {
|
|
79
|
+
const fractionOrder = (left.fraction ?? 0) - (right.fraction ?? 0);
|
|
80
|
+
return fractionOrder !== 0 ? fractionOrder : left.entityId.localeCompare(right.entityId);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
36
83
|
function createPhysicsStepResult(fields) {
|
|
37
84
|
const bodies = sortPhysicsBodySnapshots(fields.bodies ?? []);
|
|
38
85
|
const contacts = sortPhysicsContacts(fields.contacts ?? []);
|
|
86
|
+
const collisionEvents = sortPhysicsCollisionEvents(fields.collisionEvents ?? []);
|
|
87
|
+
const joints = sortPhysicsJointSnapshots(fields.joints ?? []);
|
|
39
88
|
const diagnostics = sortDiagnostics(fields.diagnostics ?? []);
|
|
40
89
|
return {
|
|
41
90
|
ok: !diagnostics.some((diagnostic) => diagnostic.severity === "error"),
|
|
@@ -43,6 +92,8 @@ function createPhysicsStepResult(fields) {
|
|
|
43
92
|
deltaSeconds: roundDeterministic(fields.deltaSeconds),
|
|
44
93
|
bodies,
|
|
45
94
|
contacts,
|
|
95
|
+
collisionEvents,
|
|
96
|
+
...fields.joints ? { joints } : {},
|
|
46
97
|
diagnostics
|
|
47
98
|
};
|
|
48
99
|
}
|
|
@@ -138,7 +189,9 @@ function readCollider(value) {
|
|
|
138
189
|
shape: "box",
|
|
139
190
|
size,
|
|
140
191
|
static: value.static,
|
|
141
|
-
...typeof value.sensor === "boolean" ? { sensor: value.sensor } : {}
|
|
192
|
+
...typeof value.sensor === "boolean" ? { sensor: value.sensor } : {},
|
|
193
|
+
...typeof value.collisionLayer === "number" ? { collisionLayer: value.collisionLayer } : {},
|
|
194
|
+
...Array.isArray(value.collisionMask) && value.collisionMask.every((layer) => typeof layer === "number") ? { collisionMask: [...value.collisionMask] } : {}
|
|
142
195
|
};
|
|
143
196
|
}
|
|
144
197
|
function readRigidBody(value) {
|
|
@@ -148,7 +201,8 @@ function readRigidBody(value) {
|
|
|
148
201
|
return {
|
|
149
202
|
type: value.type,
|
|
150
203
|
...typeof value.gravityScale === "number" ? { gravityScale: value.gravityScale } : {},
|
|
151
|
-
...typeof value.lockedRotation === "boolean" ? { lockedRotation: value.lockedRotation } : {}
|
|
204
|
+
...typeof value.lockedRotation === "boolean" ? { lockedRotation: value.lockedRotation } : {},
|
|
205
|
+
...typeof value.continuousCollisionDetection === "boolean" ? { continuousCollisionDetection: value.continuousCollisionDetection } : {}
|
|
152
206
|
};
|
|
153
207
|
}
|
|
154
208
|
function readPhysicsMaterial(value) {
|
|
@@ -160,6 +214,49 @@ function readPhysicsMaterial(value) {
|
|
|
160
214
|
restitution: value.restitution
|
|
161
215
|
};
|
|
162
216
|
}
|
|
217
|
+
function readPhysicsJoint(value) {
|
|
218
|
+
if (!isRecord(value) || typeof value.bodyA !== "string" || typeof value.bodyB !== "string") {
|
|
219
|
+
return void 0;
|
|
220
|
+
}
|
|
221
|
+
if (value.type === "distance") {
|
|
222
|
+
const anchorA = readVector2(value.anchorA);
|
|
223
|
+
const anchorB = readVector2(value.anchorB);
|
|
224
|
+
if (!anchorA || !anchorB) {
|
|
225
|
+
return void 0;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
type: "distance",
|
|
229
|
+
bodyA: value.bodyA,
|
|
230
|
+
bodyB: value.bodyB,
|
|
231
|
+
anchorA,
|
|
232
|
+
anchorB,
|
|
233
|
+
...typeof value.length === "number" ? { length: value.length } : {},
|
|
234
|
+
...typeof value.frequencyHz === "number" ? { frequencyHz: value.frequencyHz } : {},
|
|
235
|
+
...typeof value.dampingRatio === "number" ? { dampingRatio: value.dampingRatio } : {},
|
|
236
|
+
...typeof value.collideConnected === "boolean" ? { collideConnected: value.collideConnected } : {}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (value.type === "revolute") {
|
|
240
|
+
const anchor = readVector2(value.anchor);
|
|
241
|
+
if (!anchor) {
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
type: "revolute",
|
|
246
|
+
bodyA: value.bodyA,
|
|
247
|
+
bodyB: value.bodyB,
|
|
248
|
+
anchor,
|
|
249
|
+
...typeof value.enableLimit === "boolean" ? { enableLimit: value.enableLimit } : {},
|
|
250
|
+
...typeof value.lowerAngle === "number" ? { lowerAngle: value.lowerAngle } : {},
|
|
251
|
+
...typeof value.upperAngle === "number" ? { upperAngle: value.upperAngle } : {},
|
|
252
|
+
...typeof value.enableMotor === "boolean" ? { enableMotor: value.enableMotor } : {},
|
|
253
|
+
...typeof value.motorSpeed === "number" ? { motorSpeed: value.motorSpeed } : {},
|
|
254
|
+
...typeof value.maxMotorTorque === "number" ? { maxMotorTorque: value.maxMotorTorque } : {},
|
|
255
|
+
...typeof value.collideConnected === "boolean" ? { collideConnected: value.collideConnected } : {}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
return void 0;
|
|
259
|
+
}
|
|
163
260
|
function readVector2(value) {
|
|
164
261
|
if (!Array.isArray(value) || value.length !== 2 || typeof value[0] !== "number" || typeof value[1] !== "number" || !Number.isFinite(value[0]) || !Number.isFinite(value[1])) {
|
|
165
262
|
return void 0;
|
|
@@ -188,6 +285,7 @@ function staticBodySummariesEqual(left, right) {
|
|
|
188
285
|
});
|
|
189
286
|
}
|
|
190
287
|
export {
|
|
288
|
+
applyPhysicsStepResultToWorld,
|
|
191
289
|
clonePhysicsAdapterInput,
|
|
192
290
|
comparePhysicsStepResults,
|
|
193
291
|
createPhysicsAdapterInputFromWorld,
|
|
@@ -198,7 +296,10 @@ export {
|
|
|
198
296
|
roundDeterministic,
|
|
199
297
|
roundVector2,
|
|
200
298
|
sortPhysicsBodySnapshots,
|
|
299
|
+
sortPhysicsCollisionEvents,
|
|
201
300
|
sortPhysicsContacts,
|
|
301
|
+
sortPhysicsJointSnapshots,
|
|
302
|
+
sortPhysicsQueryHits,
|
|
202
303
|
summarizePhysicsStepResult
|
|
203
304
|
};
|
|
204
305
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n Collider,\n ComponentName,\n ComponentValue,\n EntityId,\n EntityRecord,\n PhysicsMaterial,\n RigidBody,\n Transform,\n Vector2,\n Velocity,\n World\n} from \"@game_engine/core\";\n\nexport type PhysicsAdapterSeverity = \"warning\" | \"error\";\nexport type PhysicsBodyType = \"static\" | \"dynamic\" | \"kinematic\";\n\nexport interface PhysicsAdapterDiagnostic {\n severity: PhysicsAdapterSeverity;\n code: string;\n message: string;\n entityId?: EntityId;\n path?: string;\n suggestion?: string;\n}\n\nexport type PhysicsAdapterDiagnostics = PhysicsAdapterDiagnostic[];\n\nexport interface PhysicsAdapterEntity {\n id: EntityId;\n components: Record<ComponentName, ComponentValue>;\n}\n\nexport interface PhysicsAdapterWorldInput {\n entities: PhysicsAdapterEntity[];\n}\n\nexport interface PhysicsAdapterCreateOptions {\n gravity?: Vector2;\n}\n\nexport interface PhysicsStepOptions {\n frame?: number;\n}\n\nexport interface PhysicsContactSnapshot {\n entityId: EntityId;\n otherEntityId: EntityId;\n grounded?: boolean;\n}\n\nexport interface PhysicsGroundingSnapshot {\n grounded: boolean;\n groundEntityId?: EntityId;\n}\n\nexport interface PhysicsBodySnapshot {\n entityId: EntityId;\n bodyType: PhysicsBodyType;\n transform?: Pick<Transform, \"position\" | \"rotation\">;\n velocity?: Velocity;\n grounded?: PhysicsGroundingSnapshot;\n contacts: PhysicsContactSnapshot[];\n}\n\nexport interface PhysicsStepResult {\n ok: boolean;\n frame: number;\n deltaSeconds: number;\n bodies: PhysicsBodySnapshot[];\n contacts: PhysicsContactSnapshot[];\n diagnostics: PhysicsAdapterDiagnostics;\n}\n\nexport interface PhysicsAdapterWorld {\n step(deltaSeconds: number, options?: PhysicsStepOptions): PhysicsStepResult;\n snapshot(options?: PhysicsStepOptions): PhysicsStepResult;\n dispose?(): void;\n}\n\nexport interface PhysicsAdapter {\n name: string;\n createWorld(\n input: PhysicsAdapterWorldInput,\n options?: PhysicsAdapterCreateOptions\n ): PhysicsAdapterWorld | Promise<PhysicsAdapterWorld>;\n}\n\nexport interface PhysicsComponents {\n transform?: Transform;\n velocity?: Velocity;\n collider?: Collider;\n rigidBody?: RigidBody;\n physicsMaterial?: PhysicsMaterial;\n}\n\nexport interface PhysicsBackendComparisonInput {\n backend: string;\n result: PhysicsStepResult;\n}\n\nexport interface PhysicsStaticBodySummary {\n entityId: EntityId;\n position?: Vector2;\n}\n\nexport interface PhysicsBackendResultSummary {\n backend: string;\n ok: boolean;\n bodyCount: number;\n bodyIds: EntityId[];\n staticBodies: PhysicsStaticBodySummary[];\n diagnosticCodes: string[];\n contactPairs: string[];\n}\n\nexport interface PhysicsBackendComparison {\n summaries: PhysicsBackendResultSummary[];\n sameBodyIds: boolean;\n sameStaticBodyPositions: boolean;\n diagnosticsShapeCompatible: boolean;\n}\n\nexport function createPhysicsAdapterInputFromWorld(world: World): PhysicsAdapterWorldInput {\n return {\n entities: world.listEntities().map((entity) => cloneAdapterEntity(entity))\n };\n}\n\nexport function clonePhysicsAdapterInput(input: PhysicsAdapterWorldInput): PhysicsAdapterWorldInput {\n return {\n entities: input.entities.map((entity) => cloneAdapterEntity(entity))\n };\n}\n\nexport function readPhysicsComponents(entity: PhysicsAdapterEntity): PhysicsComponents {\n return {\n transform: readTransform(entity.components.Transform),\n velocity: readVelocity(entity.components.Velocity),\n collider: readCollider(entity.components.Collider),\n rigidBody: readRigidBody(entity.components.RigidBody),\n physicsMaterial: readPhysicsMaterial(entity.components.PhysicsMaterial)\n };\n}\n\nexport function resolvePhysicsBodyType(components: PhysicsComponents): PhysicsBodyType {\n if (components.rigidBody) {\n return components.rigidBody.type;\n }\n\n return components.collider?.static ? \"static\" : \"dynamic\";\n}\n\nexport function sortPhysicsBodySnapshots(bodies: PhysicsBodySnapshot[]): PhysicsBodySnapshot[] {\n return [...bodies].sort((left, right) => left.entityId.localeCompare(right.entityId));\n}\n\nexport function sortPhysicsContacts(contacts: PhysicsContactSnapshot[]): PhysicsContactSnapshot[] {\n return [...contacts].sort((left, right) => {\n const entityOrder = left.entityId.localeCompare(right.entityId);\n return entityOrder !== 0 ? entityOrder : left.otherEntityId.localeCompare(right.otherEntityId);\n });\n}\n\nexport function createPhysicsStepResult(\n fields: Omit<PhysicsStepResult, \"ok\" | \"bodies\" | \"contacts\" | \"diagnostics\"> & {\n bodies?: PhysicsBodySnapshot[];\n contacts?: PhysicsContactSnapshot[];\n diagnostics?: PhysicsAdapterDiagnostics;\n }\n): PhysicsStepResult {\n const bodies = sortPhysicsBodySnapshots(fields.bodies ?? []);\n const contacts = sortPhysicsContacts(fields.contacts ?? []);\n const diagnostics = sortDiagnostics(fields.diagnostics ?? []);\n\n return {\n ok: !diagnostics.some((diagnostic) => diagnostic.severity === \"error\"),\n frame: fields.frame,\n deltaSeconds: roundDeterministic(fields.deltaSeconds),\n bodies,\n contacts,\n diagnostics\n };\n}\n\nexport function createPhysicsDiagnostic(\n diagnostic: PhysicsAdapterDiagnostic\n): PhysicsAdapterDiagnostic {\n return { ...diagnostic };\n}\n\nexport function summarizePhysicsStepResult(\n backend: string,\n result: PhysicsStepResult\n): PhysicsBackendResultSummary {\n return {\n backend,\n ok: result.ok,\n bodyCount: result.bodies.length,\n bodyIds: result.bodies.map((body) => body.entityId).sort(),\n staticBodies: result.bodies\n .filter((body) => body.bodyType === \"static\")\n .map((body) => ({\n entityId: body.entityId,\n ...(body.transform?.position ? { position: roundVector2(body.transform.position) } : {})\n }))\n .sort((left, right) => left.entityId.localeCompare(right.entityId)),\n diagnosticCodes: result.diagnostics.map((diagnostic) => diagnostic.code).sort(),\n contactPairs: result.contacts\n .map((contact) => `${contact.entityId}->${contact.otherEntityId}`)\n .sort()\n };\n}\n\nexport function comparePhysicsStepResults(\n inputs: PhysicsBackendComparisonInput[]\n): PhysicsBackendComparison {\n const summaries = inputs\n .map((input) => summarizePhysicsStepResult(input.backend, input.result))\n .sort((left, right) => left.backend.localeCompare(right.backend));\n const [baseline] = summaries;\n\n return {\n summaries,\n sameBodyIds: baseline ? summaries.every((summary) => arraysEqual(summary.bodyIds, baseline.bodyIds)) : true,\n sameStaticBodyPositions: baseline\n ? summaries.every((summary) => staticBodySummariesEqual(summary.staticBodies, baseline.staticBodies))\n : true,\n diagnosticsShapeCompatible: baseline\n ? summaries.every((summary) => arraysEqual(summary.diagnosticCodes, baseline.diagnosticCodes))\n : true\n };\n}\n\nexport function roundDeterministic(value: number): number {\n const rounded = Number(value.toFixed(12));\n const nearestInteger = Math.round(rounded);\n return Math.abs(rounded - nearestInteger) < 1e-9 ? nearestInteger : rounded;\n}\n\nexport function roundVector2(value: Vector2): Vector2 {\n return [roundDeterministic(value[0]), roundDeterministic(value[1])];\n}\n\nfunction cloneAdapterEntity(entity: EntityRecord | PhysicsAdapterEntity): PhysicsAdapterEntity {\n return {\n id: entity.id,\n components: cloneComponents(entity.components)\n };\n}\n\nfunction cloneComponents(components: Record<ComponentName, ComponentValue>): Record<ComponentName, ComponentValue> {\n return Object.fromEntries(Object.entries(components).map(([name, value]) => [name, cloneValue(value)]));\n}\n\nfunction cloneValue(value: ComponentValue): ComponentValue {\n if (value === undefined) {\n return undefined;\n }\n\n return JSON.parse(JSON.stringify(value));\n}\n\nfunction sortDiagnostics(diagnostics: PhysicsAdapterDiagnostics): PhysicsAdapterDiagnostics {\n return [...diagnostics].sort((left, right) => {\n const entityOrder = (left.entityId ?? \"\").localeCompare(right.entityId ?? \"\");\n if (entityOrder !== 0) {\n return entityOrder;\n }\n\n const pathOrder = (left.path ?? \"\").localeCompare(right.path ?? \"\");\n return pathOrder !== 0 ? pathOrder : left.code.localeCompare(right.code);\n });\n}\n\nfunction readTransform(value: ComponentValue): Transform | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n\n const position = readVector2(value.position);\n const scale = readVector2(value.scale);\n const rotation = typeof value.rotation === \"number\" && Number.isFinite(value.rotation) ? value.rotation : undefined;\n\n return position && scale && rotation !== undefined\n ? {\n position,\n rotation,\n scale\n }\n : undefined;\n}\n\nfunction readVelocity(value: ComponentValue): Velocity | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n\n const linear = readVector2(value.linear);\n return linear ? { linear } : undefined;\n}\n\nfunction readCollider(value: ComponentValue): Collider | undefined {\n if (!isRecord(value) || value.shape !== \"box\" || typeof value.static !== \"boolean\") {\n return undefined;\n }\n\n const size = readVector2(value.size);\n if (!size) {\n return undefined;\n }\n\n return {\n shape: \"box\",\n size,\n static: value.static,\n ...(typeof value.sensor === \"boolean\" ? { sensor: value.sensor } : {})\n };\n}\n\nfunction readRigidBody(value: ComponentValue): RigidBody | undefined {\n if (!isRecord(value) || ![\"static\", \"dynamic\", \"kinematic\"].includes(String(value.type))) {\n return undefined;\n }\n\n return {\n type: value.type as RigidBody[\"type\"],\n ...(typeof value.gravityScale === \"number\" ? { gravityScale: value.gravityScale } : {}),\n ...(typeof value.lockedRotation === \"boolean\" ? { lockedRotation: value.lockedRotation } : {})\n };\n}\n\nfunction readPhysicsMaterial(value: ComponentValue): PhysicsMaterial | undefined {\n if (!isRecord(value) || typeof value.friction !== \"number\" || typeof value.restitution !== \"number\") {\n return undefined;\n }\n\n return {\n friction: value.friction,\n restitution: value.restitution\n };\n}\n\nfunction readVector2(value: unknown): Vector2 | undefined {\n if (\n !Array.isArray(value) ||\n value.length !== 2 ||\n typeof value[0] !== \"number\" ||\n typeof value[1] !== \"number\" ||\n !Number.isFinite(value[0]) ||\n !Number.isFinite(value[1])\n ) {\n return undefined;\n }\n\n return [value[0], value[1]];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction arraysEqual(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((value, index) => value === right[index]);\n}\n\nfunction staticBodySummariesEqual(\n left: readonly PhysicsStaticBodySummary[],\n right: readonly PhysicsStaticBodySummary[]\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n\n return left.every((leftSummary, index) => {\n const rightSummary = right[index];\n if (!rightSummary || leftSummary.entityId !== rightSummary.entityId) {\n return false;\n }\n\n if (!leftSummary.position || !rightSummary.position) {\n return leftSummary.position === rightSummary.position;\n }\n\n return leftSummary.position[0] === rightSummary.position[0] && leftSummary.position[1] === rightSummary.position[1];\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\r\n Collider,\r\n ComponentName,\r\n ComponentValue,\r\n EntityId,\r\n EntityRecord,\r\n GroundedState,\r\n PhysicsJoint,\r\n PhysicsMaterial,\r\n RigidBody,\r\n Transform,\r\n Vector2,\r\n Velocity,\r\n World\r\n} from \"@game_engine/core\";\r\n\r\nexport type PhysicsAdapterSeverity = \"warning\" | \"error\";\r\nexport type PhysicsBodyType = \"static\" | \"dynamic\" | \"kinematic\";\r\n\r\nexport interface PhysicsAdapterDiagnostic {\r\n severity: PhysicsAdapterSeverity;\r\n code: string;\r\n message: string;\r\n entityId?: EntityId;\r\n path?: string;\r\n suggestion?: string;\r\n}\r\n\r\nexport type PhysicsAdapterDiagnostics = PhysicsAdapterDiagnostic[];\r\n\r\nexport interface PhysicsAdapterEntity {\r\n id: EntityId;\r\n components: Record<ComponentName, ComponentValue>;\r\n}\r\n\r\nexport interface PhysicsAdapterWorldInput {\r\n entities: PhysicsAdapterEntity[];\r\n}\r\n\r\nexport interface PhysicsAdapterCreateOptions {\r\n gravity?: Vector2;\r\n}\r\n\r\nexport interface PhysicsStepOptions {\r\n frame?: number;\r\n}\r\n\r\nexport interface PhysicsContactSnapshot {\r\n entityId: EntityId;\r\n otherEntityId: EntityId;\r\n grounded?: boolean;\r\n}\r\n\r\nexport type PhysicsCollisionPhase = \"start\" | \"stay\" | \"end\";\r\n\r\nexport interface PhysicsCollisionEvent {\r\n phase: PhysicsCollisionPhase;\r\n entityAId: EntityId;\r\n entityBId: EntityId;\r\n sensor: boolean;\r\n}\r\n\r\nexport interface PhysicsGroundingSnapshot {\r\n grounded: boolean;\r\n groundEntityId?: EntityId;\r\n}\r\n\r\nexport interface PhysicsBodySnapshot {\r\n entityId: EntityId;\r\n bodyType: PhysicsBodyType;\r\n transform?: Pick<Transform, \"position\" | \"rotation\">;\r\n velocity?: Velocity;\r\n grounded?: PhysicsGroundingSnapshot;\r\n contacts: PhysicsContactSnapshot[];\r\n}\r\n\r\nexport interface PhysicsJointSnapshot {\r\n entityId: EntityId;\r\n type: PhysicsJoint[\"type\"];\r\n bodyAId: EntityId;\r\n bodyBId: EntityId;\r\n}\r\n\r\nexport interface PhysicsQueryFilter {\r\n collisionLayers?: number[];\r\n includeSensors?: boolean;\r\n}\r\n\r\nexport interface PhysicsQueryHit {\r\n entityId: EntityId;\r\n bodyType: PhysicsBodyType;\r\n sensor: boolean;\r\n point?: Vector2;\r\n normal?: Vector2;\r\n fraction?: number;\r\n}\r\n\r\nexport interface PhysicsStepResult {\r\n ok: boolean;\r\n frame: number;\r\n deltaSeconds: number;\r\n bodies: PhysicsBodySnapshot[];\r\n contacts: PhysicsContactSnapshot[];\r\n collisionEvents: PhysicsCollisionEvent[];\r\n joints?: PhysicsJointSnapshot[];\r\n diagnostics: PhysicsAdapterDiagnostics;\r\n}\r\n\r\nexport interface PhysicsAdapterWorld {\r\n step(deltaSeconds: number, options?: PhysicsStepOptions): PhysicsStepResult;\r\n snapshot(options?: PhysicsStepOptions): PhysicsStepResult;\r\n queryPoint?(point: Vector2, filter?: PhysicsQueryFilter): PhysicsQueryHit[];\r\n queryAabb?(lowerBound: Vector2, upperBound: Vector2, filter?: PhysicsQueryFilter): PhysicsQueryHit[];\r\n raycast?(from: Vector2, to: Vector2, filter?: PhysicsQueryFilter): PhysicsQueryHit[];\r\n dispose?(): void;\r\n}\r\n\r\nexport interface PhysicsAdapter {\r\n name: string;\r\n createWorld(\r\n input: PhysicsAdapterWorldInput,\r\n options?: PhysicsAdapterCreateOptions\r\n ): PhysicsAdapterWorld | Promise<PhysicsAdapterWorld>;\r\n}\r\n\r\nexport interface PhysicsComponents {\r\n transform?: Transform;\r\n velocity?: Velocity;\r\n collider?: Collider;\r\n rigidBody?: RigidBody;\r\n physicsMaterial?: PhysicsMaterial;\r\n physicsJoint?: PhysicsJoint;\r\n}\r\n\r\nexport interface PhysicsBackendComparisonInput {\r\n backend: string;\r\n result: PhysicsStepResult;\r\n}\r\n\r\nexport interface PhysicsStaticBodySummary {\r\n entityId: EntityId;\r\n position?: Vector2;\r\n}\r\n\r\nexport interface PhysicsBackendResultSummary {\r\n backend: string;\r\n ok: boolean;\r\n bodyCount: number;\r\n bodyIds: EntityId[];\r\n staticBodies: PhysicsStaticBodySummary[];\r\n diagnosticCodes: string[];\r\n contactPairs: string[];\r\n}\r\n\r\nexport interface PhysicsBackendComparison {\r\n summaries: PhysicsBackendResultSummary[];\r\n sameBodyIds: boolean;\r\n sameStaticBodyPositions: boolean;\r\n diagnosticsShapeCompatible: boolean;\r\n}\r\n\r\nexport function createPhysicsAdapterInputFromWorld(world: World): PhysicsAdapterWorldInput {\r\n return {\r\n entities: world.listEntities().map((entity) => cloneAdapterEntity(entity))\r\n };\r\n}\r\n\r\nexport function applyPhysicsStepResultToWorld(world: World, result: PhysicsStepResult): void {\r\n for (const body of result.bodies) {\r\n const entity = world.getEntity(body.entityId);\r\n if (!entity) {\r\n continue;\r\n }\r\n\r\n const transform = entity.components.Transform as Transform | undefined;\r\n if (transform && body.transform) {\r\n transform.position = [...body.transform.position];\r\n transform.rotation = body.transform.rotation;\r\n }\r\n\r\n const velocity = entity.components.Velocity as Velocity | undefined;\r\n if (velocity && body.velocity) {\r\n velocity.linear = [...body.velocity.linear];\r\n }\r\n\r\n const groundedState = entity.components.GroundedState as GroundedState | undefined;\r\n if (groundedState) {\r\n groundedState.grounded = body.grounded?.grounded === true;\r\n if (body.grounded?.groundEntityId) {\r\n groundedState.groundEntityId = body.grounded.groundEntityId;\r\n } else {\r\n delete groundedState.groundEntityId;\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport function clonePhysicsAdapterInput(input: PhysicsAdapterWorldInput): PhysicsAdapterWorldInput {\r\n return {\r\n entities: input.entities.map((entity) => cloneAdapterEntity(entity))\r\n };\r\n}\r\n\r\nexport function readPhysicsComponents(entity: PhysicsAdapterEntity): PhysicsComponents {\r\n return {\r\n transform: readTransform(entity.components.Transform),\r\n velocity: readVelocity(entity.components.Velocity),\r\n collider: readCollider(entity.components.Collider),\r\n rigidBody: readRigidBody(entity.components.RigidBody),\r\n physicsMaterial: readPhysicsMaterial(entity.components.PhysicsMaterial),\r\n physicsJoint: readPhysicsJoint(entity.components.PhysicsJoint)\r\n };\r\n}\r\n\r\nexport function resolvePhysicsBodyType(components: PhysicsComponents): PhysicsBodyType {\r\n if (components.rigidBody) {\r\n return components.rigidBody.type;\r\n }\r\n\r\n return components.collider?.static ? \"static\" : \"dynamic\";\r\n}\r\n\r\nexport function sortPhysicsBodySnapshots(bodies: PhysicsBodySnapshot[]): PhysicsBodySnapshot[] {\r\n return [...bodies].sort((left, right) => left.entityId.localeCompare(right.entityId));\r\n}\r\n\r\nexport function sortPhysicsContacts(contacts: PhysicsContactSnapshot[]): PhysicsContactSnapshot[] {\r\n return [...contacts].sort((left, right) => {\r\n const entityOrder = left.entityId.localeCompare(right.entityId);\r\n return entityOrder !== 0 ? entityOrder : left.otherEntityId.localeCompare(right.otherEntityId);\r\n });\r\n}\r\n\r\nexport function sortPhysicsCollisionEvents(events: PhysicsCollisionEvent[]): PhysicsCollisionEvent[] {\r\n const phaseOrder: Record<PhysicsCollisionPhase, number> = { start: 0, stay: 1, end: 2 };\r\n return [...events].sort((left, right) => {\r\n const entityAOrder = left.entityAId.localeCompare(right.entityAId);\r\n if (entityAOrder !== 0) {\r\n return entityAOrder;\r\n }\r\n\r\n const entityBOrder = left.entityBId.localeCompare(right.entityBId);\r\n return entityBOrder !== 0 ? entityBOrder : phaseOrder[left.phase] - phaseOrder[right.phase];\r\n });\r\n}\r\n\r\nexport function sortPhysicsJointSnapshots(joints: PhysicsJointSnapshot[]): PhysicsJointSnapshot[] {\r\n return [...joints].sort((left, right) => left.entityId.localeCompare(right.entityId));\r\n}\r\n\r\nexport function sortPhysicsQueryHits(hits: PhysicsQueryHit[]): PhysicsQueryHit[] {\r\n return [...hits].sort((left, right) => {\r\n const fractionOrder = (left.fraction ?? 0) - (right.fraction ?? 0);\r\n return fractionOrder !== 0 ? fractionOrder : left.entityId.localeCompare(right.entityId);\r\n });\r\n}\r\n\r\nexport function createPhysicsStepResult(\r\n fields: Omit<PhysicsStepResult, \"ok\" | \"bodies\" | \"contacts\" | \"collisionEvents\" | \"diagnostics\"> & {\r\n bodies?: PhysicsBodySnapshot[];\r\n contacts?: PhysicsContactSnapshot[];\r\n collisionEvents?: PhysicsCollisionEvent[];\r\n diagnostics?: PhysicsAdapterDiagnostics;\r\n }\r\n): PhysicsStepResult {\r\n const bodies = sortPhysicsBodySnapshots(fields.bodies ?? []);\r\n const contacts = sortPhysicsContacts(fields.contacts ?? []);\r\n const collisionEvents = sortPhysicsCollisionEvents(fields.collisionEvents ?? []);\r\n const joints = sortPhysicsJointSnapshots(fields.joints ?? []);\r\n const diagnostics = sortDiagnostics(fields.diagnostics ?? []);\r\n\r\n return {\r\n ok: !diagnostics.some((diagnostic) => diagnostic.severity === \"error\"),\r\n frame: fields.frame,\r\n deltaSeconds: roundDeterministic(fields.deltaSeconds),\r\n bodies,\r\n contacts,\r\n collisionEvents,\r\n ...(fields.joints ? { joints } : {}),\r\n diagnostics\r\n };\r\n}\r\n\r\nexport function createPhysicsDiagnostic(\r\n diagnostic: PhysicsAdapterDiagnostic\r\n): PhysicsAdapterDiagnostic {\r\n return { ...diagnostic };\r\n}\r\n\r\nexport function summarizePhysicsStepResult(\r\n backend: string,\r\n result: PhysicsStepResult\r\n): PhysicsBackendResultSummary {\r\n return {\r\n backend,\r\n ok: result.ok,\r\n bodyCount: result.bodies.length,\r\n bodyIds: result.bodies.map((body) => body.entityId).sort(),\r\n staticBodies: result.bodies\r\n .filter((body) => body.bodyType === \"static\")\r\n .map((body) => ({\r\n entityId: body.entityId,\r\n ...(body.transform?.position ? { position: roundVector2(body.transform.position) } : {})\r\n }))\r\n .sort((left, right) => left.entityId.localeCompare(right.entityId)),\r\n diagnosticCodes: result.diagnostics.map((diagnostic) => diagnostic.code).sort(),\r\n contactPairs: result.contacts\r\n .map((contact) => `${contact.entityId}->${contact.otherEntityId}`)\r\n .sort()\r\n };\r\n}\r\n\r\nexport function comparePhysicsStepResults(\r\n inputs: PhysicsBackendComparisonInput[]\r\n): PhysicsBackendComparison {\r\n const summaries = inputs\r\n .map((input) => summarizePhysicsStepResult(input.backend, input.result))\r\n .sort((left, right) => left.backend.localeCompare(right.backend));\r\n const [baseline] = summaries;\r\n\r\n return {\r\n summaries,\r\n sameBodyIds: baseline ? summaries.every((summary) => arraysEqual(summary.bodyIds, baseline.bodyIds)) : true,\r\n sameStaticBodyPositions: baseline\r\n ? summaries.every((summary) => staticBodySummariesEqual(summary.staticBodies, baseline.staticBodies))\r\n : true,\r\n diagnosticsShapeCompatible: baseline\r\n ? summaries.every((summary) => arraysEqual(summary.diagnosticCodes, baseline.diagnosticCodes))\r\n : true\r\n };\r\n}\r\n\r\nexport function roundDeterministic(value: number): number {\r\n const rounded = Number(value.toFixed(12));\r\n const nearestInteger = Math.round(rounded);\r\n return Math.abs(rounded - nearestInteger) < 1e-9 ? nearestInteger : rounded;\r\n}\r\n\r\nexport function roundVector2(value: Vector2): Vector2 {\r\n return [roundDeterministic(value[0]), roundDeterministic(value[1])];\r\n}\r\n\r\nfunction cloneAdapterEntity(entity: EntityRecord | PhysicsAdapterEntity): PhysicsAdapterEntity {\r\n return {\r\n id: entity.id,\r\n components: cloneComponents(entity.components)\r\n };\r\n}\r\n\r\nfunction cloneComponents(components: Record<ComponentName, ComponentValue>): Record<ComponentName, ComponentValue> {\r\n return Object.fromEntries(Object.entries(components).map(([name, value]) => [name, cloneValue(value)]));\r\n}\r\n\r\nfunction cloneValue(value: ComponentValue): ComponentValue {\r\n if (value === undefined) {\r\n return undefined;\r\n }\r\n\r\n return JSON.parse(JSON.stringify(value));\r\n}\r\n\r\nfunction sortDiagnostics(diagnostics: PhysicsAdapterDiagnostics): PhysicsAdapterDiagnostics {\r\n return [...diagnostics].sort((left, right) => {\r\n const entityOrder = (left.entityId ?? \"\").localeCompare(right.entityId ?? \"\");\r\n if (entityOrder !== 0) {\r\n return entityOrder;\r\n }\r\n\r\n const pathOrder = (left.path ?? \"\").localeCompare(right.path ?? \"\");\r\n return pathOrder !== 0 ? pathOrder : left.code.localeCompare(right.code);\r\n });\r\n}\r\n\r\nfunction readTransform(value: ComponentValue): Transform | undefined {\r\n if (!isRecord(value)) {\r\n return undefined;\r\n }\r\n\r\n const position = readVector2(value.position);\r\n const scale = readVector2(value.scale);\r\n const rotation = typeof value.rotation === \"number\" && Number.isFinite(value.rotation) ? value.rotation : undefined;\r\n\r\n return position && scale && rotation !== undefined\r\n ? {\r\n position,\r\n rotation,\r\n scale\r\n }\r\n : undefined;\r\n}\r\n\r\nfunction readVelocity(value: ComponentValue): Velocity | undefined {\r\n if (!isRecord(value)) {\r\n return undefined;\r\n }\r\n\r\n const linear = readVector2(value.linear);\r\n return linear ? { linear } : undefined;\r\n}\r\n\r\nfunction readCollider(value: ComponentValue): Collider | undefined {\r\n if (!isRecord(value) || value.shape !== \"box\" || typeof value.static !== \"boolean\") {\r\n return undefined;\r\n }\r\n\r\n const size = readVector2(value.size);\r\n if (!size) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n shape: \"box\",\r\n size,\r\n static: value.static,\r\n ...(typeof value.sensor === \"boolean\" ? { sensor: value.sensor } : {}),\r\n ...(typeof value.collisionLayer === \"number\" ? { collisionLayer: value.collisionLayer } : {}),\r\n ...(Array.isArray(value.collisionMask) && value.collisionMask.every((layer) => typeof layer === \"number\")\r\n ? { collisionMask: [...value.collisionMask] as number[] }\r\n : {})\r\n };\r\n}\r\n\r\nfunction readRigidBody(value: ComponentValue): RigidBody | undefined {\r\n if (!isRecord(value) || ![\"static\", \"dynamic\", \"kinematic\"].includes(String(value.type))) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n type: value.type as RigidBody[\"type\"],\r\n ...(typeof value.gravityScale === \"number\" ? { gravityScale: value.gravityScale } : {}),\r\n ...(typeof value.lockedRotation === \"boolean\" ? { lockedRotation: value.lockedRotation } : {}),\r\n ...(typeof value.continuousCollisionDetection === \"boolean\"\r\n ? { continuousCollisionDetection: value.continuousCollisionDetection }\r\n : {})\r\n };\r\n}\r\n\r\nfunction readPhysicsMaterial(value: ComponentValue): PhysicsMaterial | undefined {\r\n if (!isRecord(value) || typeof value.friction !== \"number\" || typeof value.restitution !== \"number\") {\r\n return undefined;\r\n }\r\n\r\n return {\r\n friction: value.friction,\r\n restitution: value.restitution\r\n };\r\n}\r\n\r\nfunction readPhysicsJoint(value: ComponentValue): PhysicsJoint | undefined {\r\n if (!isRecord(value) || typeof value.bodyA !== \"string\" || typeof value.bodyB !== \"string\") {\r\n return undefined;\r\n }\r\n\r\n if (value.type === \"distance\") {\r\n const anchorA = readVector2(value.anchorA);\r\n const anchorB = readVector2(value.anchorB);\r\n if (!anchorA || !anchorB) {\r\n return undefined;\r\n }\r\n return {\r\n type: \"distance\",\r\n bodyA: value.bodyA,\r\n bodyB: value.bodyB,\r\n anchorA,\r\n anchorB,\r\n ...(typeof value.length === \"number\" ? { length: value.length } : {}),\r\n ...(typeof value.frequencyHz === \"number\" ? { frequencyHz: value.frequencyHz } : {}),\r\n ...(typeof value.dampingRatio === \"number\" ? { dampingRatio: value.dampingRatio } : {}),\r\n ...(typeof value.collideConnected === \"boolean\" ? { collideConnected: value.collideConnected } : {})\r\n };\r\n }\r\n\r\n if (value.type === \"revolute\") {\r\n const anchor = readVector2(value.anchor);\r\n if (!anchor) {\r\n return undefined;\r\n }\r\n return {\r\n type: \"revolute\",\r\n bodyA: value.bodyA,\r\n bodyB: value.bodyB,\r\n anchor,\r\n ...(typeof value.enableLimit === \"boolean\" ? { enableLimit: value.enableLimit } : {}),\r\n ...(typeof value.lowerAngle === \"number\" ? { lowerAngle: value.lowerAngle } : {}),\r\n ...(typeof value.upperAngle === \"number\" ? { upperAngle: value.upperAngle } : {}),\r\n ...(typeof value.enableMotor === \"boolean\" ? { enableMotor: value.enableMotor } : {}),\r\n ...(typeof value.motorSpeed === \"number\" ? { motorSpeed: value.motorSpeed } : {}),\r\n ...(typeof value.maxMotorTorque === \"number\" ? { maxMotorTorque: value.maxMotorTorque } : {}),\r\n ...(typeof value.collideConnected === \"boolean\" ? { collideConnected: value.collideConnected } : {})\r\n };\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nfunction readVector2(value: unknown): Vector2 | undefined {\r\n if (\r\n !Array.isArray(value) ||\r\n value.length !== 2 ||\r\n typeof value[0] !== \"number\" ||\r\n typeof value[1] !== \"number\" ||\r\n !Number.isFinite(value[0]) ||\r\n !Number.isFinite(value[1])\r\n ) {\r\n return undefined;\r\n }\r\n\r\n return [value[0], value[1]];\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction arraysEqual(left: readonly string[], right: readonly string[]): boolean {\r\n return left.length === right.length && left.every((value, index) => value === right[index]);\r\n}\r\n\r\nfunction staticBodySummariesEqual(\r\n left: readonly PhysicsStaticBodySummary[],\r\n right: readonly PhysicsStaticBodySummary[]\r\n): boolean {\r\n if (left.length !== right.length) {\r\n return false;\r\n }\r\n\r\n return left.every((leftSummary, index) => {\r\n const rightSummary = right[index];\r\n if (!rightSummary || leftSummary.entityId !== rightSummary.entityId) {\r\n return false;\r\n }\r\n\r\n if (!leftSummary.position || !rightSummary.position) {\r\n return leftSummary.position === rightSummary.position;\r\n }\r\n\r\n return leftSummary.position[0] === rightSummary.position[0] && leftSummary.position[1] === rightSummary.position[1];\r\n });\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@game_engine/physics-adapter",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
4
|
"description": "Backend-neutral physics adapter contracts for Agent Engine experiments.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22.11.0 <23 || >=24.11.0 <25"
|
|
26
|
+
},
|
|
24
27
|
"type": "module",
|
|
25
28
|
"main": "./dist/index.js",
|
|
26
29
|
"types": "./dist/index.d.ts",
|
|
@@ -31,7 +34,7 @@
|
|
|
31
34
|
}
|
|
32
35
|
},
|
|
33
36
|
"dependencies": {
|
|
34
|
-
"@game_engine/core": "0.1.0-alpha.
|
|
37
|
+
"@game_engine/core": "0.1.0-alpha.2"
|
|
35
38
|
},
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"tsup": "^8.3.5",
|