You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a player stands (not seated) on a Create Elevator Pulley contraption that has been assembled inside a Sable sub-level (e.g. an airship the elevator shaft is glued into), riding the elevator desyncs the player:
The player is left behind on the previous floor while the cabin moves on without them.
The client console spams <player> moved too quickly! with a phantom vertical delta of ~280 blocks (X/Z ≈ 0).
The ship and cabin flicker / briefly disappear during the movement (the camera lurches into plot space).
Riding the same elevator seated (as a passenger in a glued seat) works perfectly — smooth transition, no flicker, no desync. Rotating contraptions on the sub-level (e.g. bearings/propellers) are also unaffected.
Diagnosis
The elevator contraption itself is captured into the sub-level correctly — it initializes at plot-space coordinates with inSubLevel = true, identical to other contraptions that work. The breakage is specific to the standing-rider carry.
ContraptionCollider.saveClientPlayerFromClipping / savePlayerFromClipping (the client-side anti-clip safety) reposition a standing rider using:
contraptionEntity.getY() is the contraption entity's raw position, which for a sub-level contraption is plot-space (far-away coordinates), not the rendered world-space position. ContraptionColliderMixin transforms the values used inside collideEntities into the sub-level frame, but saveClientPlayerFromClipping / savePlayerFromClipping are not covered, so a standing rider is setPos'd toward plot space — producing the ~280-block phantom Y delta (→ "moved too quickly" → rubber-band / left behind) and the camera lurch (→ render flicker).
This lines up exactly with the observed behavior:
The safety only arms for TranslatingContraption (ElevatorContraption extends PulleyContraption extends TranslatingContraption), so rotating contraptions (bearings) never reach it.
It returns early for passengers (isPassenger()), so a seated rider is unaffected.
Only a standing rider on a translating contraption inside a sub-level triggers it.
Steps to reproduce
Build a Sable airship sub-level and assemble it so it flies.
Glue a Create Elevator Pulley + shaft into the ship (so it becomes part of the sub-level) with at least two floors / elevator contacts.
Assemble the elevator.
Stand on the cabin and send it to another floor.
Expected: ride smoothly to the floor.
Actual: left behind on the old floor; client logs moved too quickly! (~280 Y delta); ship/cabin flicker.
Repeat seated in a glued seat → works correctly.
Suggested fix
Transform the contraption Y used by saveClientPlayerFromClipping / savePlayerFromClipping into the sub-level frame (the same way the collideEntities inputs are already redirected), or skip these anti-clip safeties entirely for contraptions inside a sub-level (the sub-level-transformed collideEntities carry already handles riders correctly).
Workarounds
Ride the elevator seated (the passenger path is unaffected).
Skipping savePlayerFromClipping when getContaining(contraptionEntity) != null (i.e. the contraption is inside a sub-level) restores correct standing-rider behavior in testing, with no observed downside for normal-speed elevators.
Environment
Summary
When a player stands (not seated) on a Create Elevator Pulley contraption that has been assembled inside a Sable sub-level (e.g. an airship the elevator shaft is glued into), riding the elevator desyncs the player:
<player> moved too quickly!with a phantom vertical delta of ~280 blocks (X/Z ≈ 0).Riding the same elevator seated (as a passenger in a glued seat) works perfectly — smooth transition, no flicker, no desync. Rotating contraptions on the sub-level (e.g. bearings/propellers) are also unaffected.
Diagnosis
The elevator contraption itself is captured into the sub-level correctly — it initializes at plot-space coordinates with
inSubLevel = true, identical to other contraptions that work. The breakage is specific to the standing-rider carry.ContraptionCollider.saveClientPlayerFromClipping/savePlayerFromClipping(the client-side anti-clip safety) reposition a standing rider using:contraptionEntity.getY()is the contraption entity's raw position, which for a sub-level contraption is plot-space (far-away coordinates), not the rendered world-space position.ContraptionColliderMixintransforms the values used insidecollideEntitiesinto the sub-level frame, butsaveClientPlayerFromClipping/savePlayerFromClippingare not covered, so a standing rider issetPos'd toward plot space — producing the ~280-block phantom Y delta (→ "moved too quickly" → rubber-band / left behind) and the camera lurch (→ render flicker).This lines up exactly with the observed behavior:
TranslatingContraption(ElevatorContraption extends PulleyContraption extends TranslatingContraption), so rotating contraptions (bearings) never reach it.isPassenger()), so a seated rider is unaffected.Steps to reproduce
moved too quickly!(~280 Y delta); ship/cabin flicker.Suggested fix
Transform the contraption Y used by
saveClientPlayerFromClipping/savePlayerFromClippinginto the sub-level frame (the same way thecollideEntitiesinputs are already redirected), or skip these anti-clip safeties entirely for contraptions inside a sub-level (the sub-level-transformedcollideEntitiescarry already handles riders correctly).Workarounds
savePlayerFromClippingwhengetContaining(contraptionEntity) != null(i.e. the contraption is inside a sub-level) restores correct standing-rider behavior in testing, with no observed downside for normal-speed elevators.Elevator Bug (Without Fix Applied)
elevator-1-bug.mp4
Elevator Bug (With Fix Applied)
elevator-2-fix.mp4