Quick Summary
- π’ Status: implemented β commit
131b439 on local branch chore/disable-claude-code-ci (not yet pushed; PR not yet opened).
- New module
arcane-infra::rapier_cluster::RapierClusterSim implements ClusterSimulation and wraps a user's sim, inserting Rapier's PhysicsPipeline::step between user on_tick and ClusterServer::tick.
- Networking, replication,
ws_server, neighbor merge, and persist are unchanged β same run_cluster_loop code path.
- Behind feature flag
rapier-cluster (off by default). Vanilla cargo build pulls zero rapier3d into the dep tree.
- 18 unit tests cover lifecycle, multi-entity, dynamics, user-sim composition, determinism, despawn-respawn round-trip.
Why This Matters
Foundation for the heterogeneous-node vision in #33 β lets a cluster run cheap-but-real physics for entities no player is actively watching, while engine-parity nodes (Unreal/Chaos, Unity/PhysX) handle player-visible entities. Delivers the "second backend (Rapier stub)" item in #8 well past stub: a working drop-in.
Scope
- In:
RapierClusterSim wrapper + RapierConfig + arcane-rapier-cluster binary + tests + module docs.
- Out (separate issues): contact events, per-entity collider shapes, impulse/force commands, raycasts, joints, kinematic neighbor proxies, world-bounds policy, naming-rename sweep (
#32).
Action Items
Architecture
RapierClusterSim IS-A ClusterSimulation that HAS-A user ClusterSimulation. Each tick:
- User's
on_tick runs first β game logic, action handling, velocity intent writes.
- Wrapper acquires its
Mutex<RapierState> lock.
- Despawns bodies for entities in
pending_removals and entities that vanished from the entity map.
sync_inputs: spawns first-sight entities at entity.position, sets linvel from entity.velocity for existing bodies. Skips ids in pending_removals to avoid re-spawning bodies the user just asked to drop.
step_with_accumulator: fixed 1/60 s Rapier substeps until accumulator drains.
sync_outputs: writes body.translation β entity.position and body.linvel β entity.velocity for replication.
Contract (documented in module docs)
entity.velocity is intent-in.
entity.position is output-only after first-sight spawn. User writes are silently overwritten.
- Despawn driven by
pending_removals and entity-map disappearance.
- Every entity gets a uniform
0.5-radius sphere collider; per-entity shapes deferred.
Industry term
The pattern is pluggable physics backend (Bevy RapierPhysicsPlugin swappable for XpbdPlugin; Unreal PhysicsScene). The composition shape β wrapper sim wraps user sim β is the Strategy pattern at the design-pattern level.
Files changed
| File |
Change |
crates/arcane-infra/Cargo.toml |
rapier3d = "0.32" (optional = true); feature rapier-cluster = ["cluster-ws", "dep:rapier3d"]; bin entry |
crates/arcane-infra/src/lib.rs |
pub mod rapier_cluster (gated); re-exports RapierClusterSim + RapierConfig |
crates/arcane-infra/src/rapier_cluster.rs |
new β wrapper + private RapierState + 18 tests |
crates/arcane-infra/src/bin/arcane_rapier_cluster.rs |
new β binary mirror of arcane_cluster.rs |
Verification matrix
| Build |
Tests |
Rapier in dep tree |
Vanilla cargo test -p arcane-infra |
65 pass |
0 |
--features rapier-cluster |
83 pass (18 new) |
rapier3d v0.32.0 |
cargo build --bin arcane-cluster (vanilla) |
builds |
n/a |
cargo build --bin arcane-rapier-cluster --features rapier-cluster |
builds |
n/a |
cargo clippy both modes |
silent |
n/a |
| Module-level doctest |
compiles |
n/a |
Reference
- Parent EPIC:
#8 β Cluster physics backends β Unreal (Chaos) first, multi-engine path
- Strategic context:
#33 β Engine-specific node types β heterogeneous physics tiers
- Architecture doc:
docs/architecture/physics-backends-and-unreal.md β Β§7 "Multi-backend path" + Phase D
- Commit:
131b439 (local, not yet pushed)
- Follow-up:
#118 β Rapier cluster physics: contact events + per-entity collider shapes
Quick Summary
131b439on local branchchore/disable-claude-code-ci(not yet pushed; PR not yet opened).arcane-infra::rapier_cluster::RapierClusterSimimplementsClusterSimulationand wraps a user's sim, inserting Rapier'sPhysicsPipeline::stepbetween useron_tickandClusterServer::tick.ws_server, neighbor merge, and persist are unchanged β samerun_cluster_loopcode path.rapier-cluster(off by default). Vanillacargo buildpulls zerorapier3dinto the dep tree.Why This Matters
Foundation for the heterogeneous-node vision in
#33β lets a cluster run cheap-but-real physics for entities no player is actively watching, while engine-parity nodes (Unreal/Chaos, Unity/PhysX) handle player-visible entities. Delivers the "second backend (Rapier stub)" item in#8well past stub: a working drop-in.Scope
RapierClusterSimwrapper +RapierConfig+arcane-rapier-clusterbinary + tests + module docs.#32).Action Items
RapierClusterSimandRapierConfiginarcane-infra::rapier_clusterrapier-cluster+arcane-rapier-clusterbinaryrapier3dArchitecture
RapierClusterSimIS-AClusterSimulationthat HAS-A userClusterSimulation. Each tick:on_tickruns first β game logic, action handling, velocity intent writes.Mutex<RapierState>lock.pending_removalsand entities that vanished from the entity map.sync_inputs: spawns first-sight entities atentity.position, setslinvelfromentity.velocityfor existing bodies. Skips ids inpending_removalsto avoid re-spawning bodies the user just asked to drop.step_with_accumulator: fixed1/60 sRapier substeps until accumulator drains.sync_outputs: writesbody.translationβentity.positionandbody.linvelβentity.velocityfor replication.Contract (documented in module docs)
entity.velocityis intent-in.entity.positionis output-only after first-sight spawn. User writes are silently overwritten.pending_removalsand entity-map disappearance.0.5-radius sphere collider; per-entity shapes deferred.Industry term
The pattern is pluggable physics backend (Bevy
RapierPhysicsPluginswappable forXpbdPlugin; UnrealPhysicsScene). The composition shape β wrapper sim wraps user sim β is the Strategy pattern at the design-pattern level.Files changed
crates/arcane-infra/Cargo.tomlrapier3d = "0.32"(optional = true); featurerapier-cluster = ["cluster-ws", "dep:rapier3d"]; bin entrycrates/arcane-infra/src/lib.rspub mod rapier_cluster(gated); re-exportsRapierClusterSim+RapierConfigcrates/arcane-infra/src/rapier_cluster.rsRapierState+ 18 testscrates/arcane-infra/src/bin/arcane_rapier_cluster.rsarcane_cluster.rsVerification matrix
cargo test -p arcane-infra--features rapier-clusterrapier3d v0.32.0cargo build --bin arcane-cluster(vanilla)cargo build --bin arcane-rapier-cluster --features rapier-clustercargo clippyboth modesReference
#8β Cluster physics backends β Unreal (Chaos) first, multi-engine path#33β Engine-specific node types β heterogeneous physics tiersdocs/architecture/physics-backends-and-unreal.mdβ Β§7 "Multi-backend path" + Phase D131b439(local, not yet pushed)#118β Rapier cluster physics: contact events + per-entity collider shapes