@series-inc/rundot-syncplay 6.0.0-rc.43 → 6.0.0-rc.45

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.
@@ -0,0 +1,9 @@
1
+ # Syncplay rc.42
2
+
3
+ This release adds multiplayer physical assemblies and a 3D physics runtime bridge:
4
+ - `createSyncplayPhysicalAssemblySlice`, `stepSyncplayPhysicalAssembly`, and `projectSyncplayPhysicalAssembly` under `@series-inc/rundot-syncplay/modules/physical-assembly`.
5
+ - Authoritative Ultrahand glue, detach, and rotate operations with deterministic events.
6
+ - Recall trajectory recording and kinematic rewinds via `createSyncplayBodyPoseTrack3D`.
7
+ - Orientation hold controller (`createOrientationHold3D`) and kinematic path drive (`createKinematicPathDrive3D`) in 3D physics.
8
+ - Authoritative Rapier physics bridge (`createPhysicalAssemblyBridge3D`) linking assembly events to 3D world state.
9
+ - Disconnect recovery to release holds and active recalls on slot departure.
@@ -0,0 +1,32 @@
1
+ # Syncplay rc.43
2
+
3
+ This release introduces deterministic dynamic seating and player-keyed secret authority:
4
+
5
+ ## Dynamic Seat Control
6
+ - Rooms can configure dynamic slot policies via `deterministic.seatPolicy`:
7
+ - `recycleVacatedSeats`: boolean (default `false`). When `true`, vacated seats can be claimed by new joining players.
8
+ - `allowHumanClaimBot`: boolean (default `false`). When `true`, new human players can take over bot-controlled slots (transition S3). Returning original owners with retained claims can always reclaim their own seat regardless of this setting.
9
+ - `onHumanLeave`: `'empty' | 'bot'` (default `'empty'`). Dictates slot controller when a human player disconnects or departs.
10
+ - `initialBotSlots`: array of slot numbers controlled by bots at match start.
11
+ - Full state machine supporting transitions S1 through S6:
12
+ - `S1_empty_to_bot`
13
+ - `S2_empty_to_human`
14
+ - `S3_bot_to_human`
15
+ - `S4_bot_to_empty`
16
+ - `S5_human_to_bot`
17
+ - `S6_human_to_empty`
18
+ - Authority-issued controller leases: each human and bot controller receives an immutable, room-scoped lease (`claimId`, `botLeaseId`, and `controlEpoch`). Outgoing leases are revoked prior to successor admission.
19
+
20
+ ## Player-Keyed Secret Authority
21
+ - Private holdings (cards, items, secret roles, and choice commitments) are strictly bound to authenticated `playerId` and `claimId`, rather than bare slot indices.
22
+ - Unconsumed holdings are permanently revoked upon final departure from recyclable seats.
23
+ - Successor players occupying recycled slots never inherit prior secrets or assigned hidden roles.
24
+ - Role arrays are sized dynamically by simulation capacity `X`, removing the previous 16-player secret limit while preserving byte and snapshot budgets.
25
+
26
+ ## Durable Recovery & Fencing
27
+ - Critical seat transitions and claim modifications use monotonic revision fencing in `StateStore.saveCritical`.
28
+ - Stored snapshots round-trip version 4 records containing explicit `seatCheckpoint` states.
29
+ - Storage read errors fail closed to prevent accidental overwrites or fresh worker starts over existing persistent rooms.
30
+
31
+ ## Match Log v2
32
+ - Match logs now support version 2 formatting with explicit `claimAttributions` mapping each confirmed input frame to the active controller claim.
@@ -0,0 +1,19 @@
1
+ # Syncplay rc.44
2
+
3
+ This candidate release introduces authoring and tooling gap closures across physics and presentation:
4
+
5
+ ## Physics Debug Overlay 3D
6
+ - Introduced `createPhysicsDebugOverlay3D` in `@series-inc/rundot-syncplay/physics/3d` and `@series-inc/rundot-syncplay`.
7
+ - Supports read-only extraction of wireframe geometry, contact records, joint state, and sensors from `PhysicsWorld3D` without mutating physics state or invalidating simulation digests.
8
+ - Provides strict type definitions: `PhysicsDebugOverlay3D`, `PhysicsDebugOverlayOptions3D`, `PhysicsDebugWireframeShape3D`, `PhysicsDebugContactRecord3D`, and `PhysicsDebugJointRecord3D`.
9
+ - Supports R3F wireframe rendering adapters and budgeting controls (`maxShapes`, `maxVertices`, `maxContacts`, `maxJoints`, `maxSensors`).
10
+
11
+ ## Collider Preparation
12
+ - Introduced pure deterministic geometry cooking and validation in `collider-preparation.ts`.
13
+ - Validates coplanar faces, non-manifold edges, slivers, and degenerate polygons before registration with the native physics solver.
14
+
15
+ ## Navmesh Geometry Cooking
16
+ - Added headless geometry cooking tools for dynamic navmesh generation in `navmesh.ts`.
17
+
18
+ ## Presentation Inverse Kinematics
19
+ - Added two-bone presentation inverse kinematics solver in `presentation-ik.ts` with joint constraints and pole targets.
@@ -0,0 +1,18 @@
1
+ # Syncplay rc.45
2
+
3
+ This release contains verified performance optimizations for snapshot decoding, physics checkpoint state commitments, and session wire encoding:
4
+
5
+ ## Snapshot Base64 Decoding
6
+ - Replaced temporary quartet array allocations with four numeric scalar registers in `base64ToBytes`.
7
+ - Preserves identical decoding error messages, validation order, and padding checks.
8
+ - Reduces temporary heap allocations by 94 percent during snapshot Base64 decoding.
9
+
10
+ ## 3D Physics Checkpoint Digest Caching
11
+ - Memoizes `#digest` and `#strongDigest` on `CapturedPhysicsGame3D` during the unreleased checkpoint lifetime.
12
+ - Public `physics.strongDigest()` method returns a defensive copy (`.slice()`) to protect cached buffers from external modification.
13
+ - Internal `stateCommitment` reads protected digest buffers directly without duplicate calculation or unnecessary allocation.
14
+
15
+ ## Session Wire Single-Pass Canonical Encoding
16
+ - Canonicalizes outbound session message payloads once before checksum computation and envelope serialization.
17
+ - Serializes top-level envelope properties in canonical alphabetical order.
18
+ - Forwards pre-decoded session messages to `handleSessionText` during session swap and secret validation paths to prevent duplicate decode work.
@@ -23,7 +23,7 @@ export const physicsProfileWasmMetadata = Object.freeze({
23
23
  "sourceHash": "095061366ce3734601d06d48fa61d88a8538e1ba01e9c47663a7303ddb18fee7",
24
24
  "wasmSha256": "4b2ac3ff7d0f7a15eb31f5742a90f16f458a906d5d41bdc5fbde03e5589f94bf",
25
25
  "artifact": "profile",
26
- "packageVersion": "6.0.0-rc.43",
26
+ "packageVersion": "6.0.0-rc.45",
27
27
  "compilerFlags": [
28
28
  "-std=c++20",
29
29
  "-O3",
@@ -23,7 +23,7 @@ export const physicsWasmMetadata = Object.freeze({
23
23
  "sourceHash": "38d5f2cde9e8d448f029fd2921a743e4a40e19dc84c03abf7bed829003e2469d",
24
24
  "wasmSha256": "5f6a3d861cf3eb79a2f8060d6c4b5512673a943044a52a9d20b39f0f2fef985f",
25
25
  "artifact": "production",
26
- "packageVersion": "6.0.0-rc.43",
26
+ "packageVersion": "6.0.0-rc.45",
27
27
  "compilerFlags": [
28
28
  "-std=c++20",
29
29
  "-O3",
@@ -50,7 +50,7 @@ export const physics2dWasmMetadata = Object.freeze({
50
50
  "sourceHash": "faa090a03a6fddaf79c704fb1d76f810955ff35597449c8cec9541a75905a37e",
51
51
  "wasmSha256": "49cb90541deed40f5fff1015bb578e13ec9a793d51931c1227e3e5a11bbfa3f7",
52
52
  "artifact": "production",
53
- "packageVersion": "6.0.0-rc.43",
53
+ "packageVersion": "6.0.0-rc.45",
54
54
  "compilerFlags": [
55
55
  "-std=c++20",
56
56
  "-O3",
package/dist/browser.d.ts CHANGED
@@ -19,7 +19,7 @@ export { createDeterministicMath } from './math.js';
19
19
  export { rewindDeterministicTargets, runDeterministicMovementCrowdSimulation, runDeterministicMovementSimulation, stepDeterministicFpsAim, stepDeterministicKcc2D, stepDeterministicTopDownMover, validateDeterministicLagCompensatedHit } from './movement.js';
20
20
  export { stepDeterministicCarry3D, stepDeterministicKcc3D } from './movement3d.js';
21
21
  export { applyDeterministicReciprocalAvoidance, cookDeterministicNavigationGraph, cookTilemapNavigationGraph, createDeterministicFlowField, findDeterministicPath, smoothDeterministicPath, stepDeterministicNavigationAgents } from './navigation.js';
22
- export { cookDeterministicNavmesh, cookImportedDeterministicNavmesh, findDeterministicNavmeshPath, findDeterministicNavmeshPointPath, locateDeterministicNavmeshPolygon, runDeterministicNavmeshStress, smoothDeterministicNavmeshPath, stepDeterministicNavmeshAgents, stepDeterministicNavmeshOffMeshTraversal } from './navmesh.js';
22
+ export { cookDeterministicNavmesh, cookDeterministicNavmeshFromGeometry, cookImportedDeterministicNavmesh, findDeterministicNavmeshPath, findDeterministicNavmeshPointPath, locateDeterministicNavmeshPolygon, runDeterministicNavmeshStress, smoothDeterministicNavmeshPath, stepDeterministicNavmeshAgents, stepDeterministicNavmeshOffMeshTraversal } from './navmesh.js';
23
23
  export { createNetworkedSyncplayClient, prepareNetworkedSyncplayTransport } from './networked-client.js';
24
24
  export { createSyncplayRunner } from './runner.js';
25
25
  export { fbm2D, hash2, hashUint32, valueNoise1D, valueNoise2D } from './noise.js';
@@ -84,3 +84,6 @@ export type { MultiplayerApi, JoinTicketRequest } from '@series-inc/rundot-game-
84
84
  export { openSyncplayBrowserRoom, resolveSyncplayBrowserIntent, shareSyncplayRoom, } from './browserSession.js';
85
85
  export type { OpenSyncplayBrowserRoomOptions, OpenSyncplayBrowserRoomResult, ResolveSyncplayBrowserIntentOptions, SyncplayBrowserApi, SyncplayBrowserIntent, } from './browserSession.js';
86
86
  export { SyncplayRuntimeLeaseRequiredError } from './runtime-cleanup.js';
87
+ export type { DeterministicNavmeshGeometrySource, DeterministicNavmeshGeometryOptions } from './navmesh.js';
88
+ export { solveTwoBoneIk3D, solveFootPlanting3D, } from './presentation-ik.js';
89
+ export type { TwoBoneIkInput3D, TwoBoneIkOutput3D, FootPlantingInput3D, FootPlantingOutput3D, Vec3PresentationIK, QuatPresentationIK, } from './presentation-ik.js';
package/dist/browser.js CHANGED
@@ -20,7 +20,7 @@ export { createDeterministicMath } from './math.js';
20
20
  export { rewindDeterministicTargets, runDeterministicMovementCrowdSimulation, runDeterministicMovementSimulation, stepDeterministicFpsAim, stepDeterministicKcc2D, stepDeterministicTopDownMover, validateDeterministicLagCompensatedHit } from './movement.js';
21
21
  export { stepDeterministicCarry3D, stepDeterministicKcc3D } from './movement3d.js';
22
22
  export { applyDeterministicReciprocalAvoidance, cookDeterministicNavigationGraph, cookTilemapNavigationGraph, createDeterministicFlowField, findDeterministicPath, smoothDeterministicPath, stepDeterministicNavigationAgents } from './navigation.js';
23
- export { cookDeterministicNavmesh, cookImportedDeterministicNavmesh, findDeterministicNavmeshPath, findDeterministicNavmeshPointPath, locateDeterministicNavmeshPolygon, runDeterministicNavmeshStress, smoothDeterministicNavmeshPath, stepDeterministicNavmeshAgents, stepDeterministicNavmeshOffMeshTraversal } from './navmesh.js';
23
+ export { cookDeterministicNavmesh, cookDeterministicNavmeshFromGeometry, cookImportedDeterministicNavmesh, findDeterministicNavmeshPath, findDeterministicNavmeshPointPath, locateDeterministicNavmeshPolygon, runDeterministicNavmeshStress, smoothDeterministicNavmeshPath, stepDeterministicNavmeshAgents, stepDeterministicNavmeshOffMeshTraversal } from './navmesh.js';
24
24
  export { createNetworkedSyncplayClient, prepareNetworkedSyncplayTransport } from './networked-client.js';
25
25
  export { createSyncplayRunner } from './runner.js';
26
26
  export { fbm2D, hash2, hashUint32, valueNoise1D, valueNoise2D } from './noise.js';
@@ -49,3 +49,4 @@ export { WsMultiplayerApi } from '@series-inc/rundot-game-sdk/mp-client';
49
49
  // (RundotGameAPI comes from the SDK — syncplay may depend on the SDK).
50
50
  export { openSyncplayBrowserRoom, resolveSyncplayBrowserIntent, shareSyncplayRoom, } from './browserSession.js';
51
51
  export { SyncplayRuntimeLeaseRequiredError } from './runtime-cleanup.js';
52
+ export { solveTwoBoneIk3D, solveFootPlanting3D, } from './presentation-ik.js';
@@ -0,0 +1,31 @@
1
+ import { type ColliderSourceMesh } from './collider-cooking.js';
2
+ export interface Point3D {
3
+ readonly x: number;
4
+ readonly y: number;
5
+ readonly z: number;
6
+ }
7
+ export interface ColliderPreparationOptions {
8
+ readonly minArea?: number;
9
+ readonly minEdge?: number;
10
+ readonly resolution?: number;
11
+ readonly quantum?: number;
12
+ }
13
+ export interface ColliderPreparedPart {
14
+ readonly normal: Point3D;
15
+ readonly boundaries: readonly (readonly Point3D[])[];
16
+ readonly area: number;
17
+ readonly isHole?: boolean;
18
+ }
19
+ export interface ColliderPreparationRemovedStats {
20
+ readonly degenerate: number;
21
+ readonly interior: number;
22
+ readonly coplanar: number;
23
+ readonly contained: number;
24
+ }
25
+ export interface ColliderPreparationResult {
26
+ readonly triangles: readonly (readonly [Point3D, Point3D, Point3D])[];
27
+ readonly parts: readonly ColliderPreparedPart[];
28
+ readonly digest: string;
29
+ readonly removed: ColliderPreparationRemovedStats;
30
+ }
31
+ export declare function prepareColliderMesh(source: ColliderSourceMesh, options?: ColliderPreparationOptions): ColliderPreparationResult;