Skip to content

Prevent NPE for weightless contraptions#965

Open
lap2ka wants to merge 2 commits into
ryanhcode:mainfrom
lap2ka:fix478
Open

Prevent NPE for weightless contraptions#965
lap2ka wants to merge 2 commits into
ryanhcode:mainfrom
lap2ka:fix478

Conversation

@lap2ka
Copy link
Copy Markdown
Contributor

@lap2ka lap2ka commented May 19, 2026

Fix #457, fix #478, fix #851, fix #882, fix #906, fix #909
lotta duplicates here

Copilot AI review requested due to automatic review settings May 19, 2026 23:32
Copy link
Copy Markdown

Copilot AI left a comment

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 targets a recurring server crash in the Create compatibility layer where MassTracker.getCenterOfMass() can be null for certain “weightless” / non-solid contraptions, leading to a NullPointerException during contraption initialization.

Changes:

  • Adds a null-check before translating floating block cluster origins using the contraption center of mass.
  • Adds a null-check before adding the contraption to the physics pipeline.
Comments suppressed due to low confidence (1)

neoforge/src/main/java/dev/ryanhcode/sable/neoforge/mixin/compatibility/create/contraptions/AbstractContraptionEntityMixin.java:175

  • This null-guard prevents the immediate NPE, but leaves sable$massTracker in a state where getCenterOfMass() is null. Several call sites assume a non-null center of mass (e.g., KinematicContraption.sable$getLocalPose() and this mixin's sable$getPosition()), so if this contraption is added to a plot or the physics pipeline later it can still crash. Consider treating a null centerOfMass as an invalid MassTracker and explicitly skipping/removing the contraption from any physics/plot collections (or providing a safe fallback center of mass) to keep invariants consistent.
        assert this.sable$localBounds != null;
        this.sable$massTracker = MassTracker.build(this.sable$blockGetter(), this.sable$localBounds);
        final Vector3dc centerOfMass = this.sable$massTracker.getCenterOfMass();
        if (centerOfMass != null) {
            final Vector3d temp = centerOfMass.negate(new Vector3d()).add(0.5, 0.5, 0.5);
            for (final FloatingBlockCluster cluster : this.sable$floatingClusterContainer.clusters) {
                cluster.getBlockData().translateOrigin(temp);
            }
        }

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

Comment on lines 99 to 106
if (!this.sable$added && this.level() instanceof final ServerLevel serverLevel) {
this.sable$buildProperties();
this.sable$addToPlot();
this.sable$addToPipeline(serverLevel);
if (this.sable$massTracker.getCenterOfMass() != null) {
this.sable$addToPipeline(serverLevel);
}
this.sable$added = true;
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

shi the AI overlord is right

@lap2ka
Copy link
Copy Markdown
Contributor Author

lap2ka commented May 19, 2026

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment