Skip to content

ssarg fix the ae2 conflict and the raper3d getpose non-unwinding panic - #1396

Open
mynameisgrass wants to merge 3 commits into
ryanhcode:mainfrom
mynameisgrass:main
Open

ssarg fix the ae2 conflict and the raper3d getpose non-unwinding panic#1396
mynameisgrass wants to merge 3 commits into
ryanhcode:mainfrom
mynameisgrass:main

Conversation

@mynameisgrass

Copy link
Copy Markdown

No description provided.

Copilot AI review requested due to automatic review settings July 26, 2026 03:11
@CLAassistant

CLAassistant commented Jul 26, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ mynameisgrass
❌ ElBamboo
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the Rapier JNI bridge and related pipeline code to avoid crashes/panics when physics objects are missing or native calls fail, and adds additional diagnostics while adjusting build metadata.

Changes:

  • Rust: make rigid-body lookups fallible (Option) and guard multiple JNI entrypoints against missing IDs.
  • Rust: make joint and box removal paths tolerate missing rigid body mappings.
  • Java: add [SableDebug] logging and exception logging around key native calls; update project version/credits.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
sable_rapier/src/main/rust/rapier/src/lib.rs Switch rigid body accessors to Option and guard several JNI functions from panicking on missing IDs.
sable_rapier/src/main/rust/rapier/src/joints.rs Add helper to resolve rigid bodies (including ground) and return sentinel on missing mapping instead of panicking.
sable_rapier/src/main/rust/rapier/src/boxes.rs Make removeBox tolerant of missing rigid-body mapping.
sable_rapier/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/RapierPhysicsPipeline.java Add debug/error logging and try/catch around native calls; adjust wake-up path to use Rapier3D.getID.
gradle.properties Update version suffix and credits list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +524 to +536
if let Some(rb) = get_rigid_body(&sim_data, &sable_data, id as LevelColliderID) {
let arr: [jdouble; 7] = [
rb.translation().x as jdouble,
rb.translation().y as jdouble,
rb.translation().z as jdouble,
rb.rotation().x as jdouble,
rb.rotation().y as jdouble,
rb.rotation().z as jdouble,
rb.rotation().w as jdouble,
];

let _ = env.set_double_array_region(&store, 0, &arr);
}
Comment on lines +1359 to +1363
if let Some(rb) = get_rigid_body(&sim_data, &sable_data, id as LevelColliderID) {
let vel = rb.linvel();

let vel = rb.linvel();

_env.set_double_array_region(
&store,
0,
&[vel.x as jdouble, vel.y as jdouble, vel.z as jdouble],
)
.unwrap();
_env.set_double_array_region(
&store,
Comment on lines +1387 to +1391
if let Some(rb) = get_rigid_body(&sim_data, &sable_data, id as LevelColliderID) {
let vel = rb.angvel();

_env.set_double_array_region(
&store,
0,
&[vel.x as jdouble, vel.y as jdouble, vel.z as jdouble],
)
.unwrap();
_env.set_double_array_region(
&store,
Comment on lines 118 to 122
@Override
public void init(@Nullable final Vector3dc gravity, final double universalDrag) {
try {
Sable.LOGGER.info("[SableDebug] Initializing Rapier physics pipeline with gravity=({}, {}, {}), drag={}", gravity.x(), gravity.y(), gravity.z(), universalDrag);
this.scene = new RapierPhysicsScene(Rapier3D.initialize(gravity.x(), gravity.y(), gravity.z(), universalDrag));
PR ryanhcode#1396 (ssarg / mynameisgrass) fixed the non-unwinding panic on the
rigid_bodies registry (the reported getPose crash), but a second
registry, level_colliders, was left fully unguarded. On a production
NeoForge 1.21.1 server this reproduced the exact same failure mode
(SIGABRT from a Rust panic across an extern "system" JNI boundary)
one call further down the same code path, in setCenterOfMass:

  thread '<unnamed>' panicked at rapier/src/lib.rs:557:14:
  called `Option::unwrap()` on a `None` value
  thread caused non-unwinding panic. aborting.

This commit audits every JNI entry point that indexes level_colliders
(or a rigid_bodies handle later resolved through it) by an id supplied
from Java, and replaces unwrap()/expect()/direct indexing with
Option-based guards that no-op (or fall back to an unswapped/zero
default where the lookup only affects an optimization) when the body
has already been removed - mirroring the pattern ryanhcode#1396 applied to
rigid_bodies.

Sites fixed, none of which were touched by ryanhcode#1396:
- lib.rs: setCenterOfMass, setLocalBounds, addChunk
- contraptions.rs: get_kinematic_collider_info (now returns Option)
  and its two callers; createKinematicContraption's mount lookup;
  removeKinematicContraption against a double-remove
- rope.rs: tick() start/end attachment anchor updates, for a rope
  still attached to a sub-level that has since unloaded
- dispatcher.rs: the collision-pair swap heuristic, and both
  world_vs_world contact-manifold paths
- hooks.rs: fake-velocity lookups in both solver-contact hooks

Where a guarded lookup only feeds a performance heuristic (the
dispatcher swap order) or a purely cosmetic velocity nudge, the
fallback is the pre-existing default behavior rather than skipping
the tick, since skipping there is not required for correctness.

Verified against the production crash: applying ryanhcode#1396 alone traded
the original getPose panic for this setCenterOfMass panic on the same
server within the same physics tick chain (onStatsChanged calls
setCenterOfMass then setLocalBounds back to back). With this commit
on top, both crashes are gone under the same reproduction (repeated
sub-level load/unload near a player).

This patch was written and applied by Claude (Anthropic) at the
repository owner's direction - i.e. it is vibecoded: the owner
described the crash and asked for a fix, Claude read ryanhcode#1396, found the
gap, wrote the guards, cross-compiled sable_rapier for
x86_64-unknown-linux-gnu.2.17 to match upstream's release target, and
verified the fix in place on the affected server before this commit
was prepared. It has not been reviewed by a Rust engineer beyond that
runtime verification - please review the unwrap/expect removals
accordingly, in particular whether any of the now-silent no-op paths
should instead log or clean up related state (e.g. dangling rope
attachments after a level_colliders entry disappears from under it).
…ose-panic

Guard remaining level_colliders lookups against missing keys (extends ryanhcode#1396)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants