player: say what holds WASD when a settle releases

Coming out of a worldport unable to walk was a story, because nothing in the log said whether
the hold was the settle, a lost mover or a pending reseat. `movement_suppressors` named six
states and was only ever printed by the logout smoke test; `settling` was missing from it
although the settle hold is a mover hold (`mover.rs`), and a cross-map worldport is exactly
where it fires.

One line per settle, on the frame it ends, naming the hold or `none` — so the next transfer
reports its own cause. Instrument only; no gate reads either list.
This commit is contained in:
chairmanpow
2026-10-02 18:23:09 +01:00
parent c2d83dc22e
commit bf52a0abb1
2 changed files with 13 additions and 1 deletions
+3 -1
View File
@@ -538,7 +538,8 @@ impl Player {
}
/// The states on this resource that stop WASD, comma-joined, or `"none"`: an instrument for the
/// log after a session boundary, not a gate. A stun lives on the descriptor and does not show.
/// log after a session boundary, not a gate. A stun lives on the descriptor and does not
/// show. `settling` is in the list because the settle hold is a mover hold, not a camera one.
pub(crate) fn movement_suppressors(&self) -> String {
let named = [
(!self.active, "inactive"),
@@ -548,6 +549,7 @@ impl Player {
(self.server_riding, "server-ride"),
(self.foreign_mover.is_some(), "possession"),
(self.reseat, "reseat-pending"),
(self.settling, "settling"),
];
let list: Vec<&str> = named
.into_iter()
@@ -137,6 +137,7 @@ pub(super) fn release_post_snap_hold(
// the deadline is pushed while the resident world is still the map we left and while the
// stream advances, so only a stream with no progress for the whole budget times out.
let now = time.elapsed_secs();
let was_settling = player.settling;
if p.presentable() && !player.world_stale && focus_matches {
player.end_settle(true, now);
} else if player.world_stale || progressed {
@@ -144,6 +145,15 @@ pub(super) fn release_post_snap_hold(
} else if now >= player.settle_deadline {
player.end_settle(false, now);
}
// Once per settle, and only on the frame it ends: what still holds WASD, or `none`. Without
// this a character that comes out of a worldport unable to walk is a story, because nothing
// else in the log says whether the hold is the settle, a lost mover, or a pending reseat.
if was_settling && !player.settling {
info!(
"worldport: settle released — WASD held by: {}",
player.movement_suppressors()
);
}
// The worldport ack, the reference's post-load `0xDC`, goes at either end of the hold: the
// server keeps an unacked transfer out of world until logout.
if !player.settling && player.owes_worldport_ack {