Symptom
Disconnected players remain in the zone as frozen ghosts. Live 2026-07-04 logs: character id 2's player actor (0x00000002) appeared in every later session's zone-in neighbour list (send_zone_in_bundle … ids=[…, "0x00000002:Player"]) while its owner was offline.
Mechanism
handle_session_end (map-server/src/processor.rs:598) removes the registry handle and session maps but:
- never removes the player's
StoredActor from zone.core.actors, and
- broadcasts no
0x00CB RemoveActor to remaining clients.
A correct despawn primitive already exists — apply_despawn_actor (map-server/src/runtime/quest_apply.rs:~1453) broadcasts RemoveActor and cleans the registry; the session-end path just never uses it.
Note the ghost is inert on the wire (zero packets sourced from the ghost actor in later sessions — packet-log census), so this is a stale-state/visual defect, not the opening-quest crash (that was the case-resolution bug, fixed in feature/ubuntu f6897e5). It still accumulates one stale actor per disconnect per zone.
Suggested fix
On session end, remove the player's StoredActor from the zone and broadcast RemoveActor via the existing primitive (mind the deferred-warp/zone-change paths where the actor must survive the handoff).
Symptom
Disconnected players remain in the zone as frozen ghosts. Live 2026-07-04 logs: character id 2's player actor (
0x00000002) appeared in every later session's zone-in neighbour list (send_zone_in_bundle … ids=[…, "0x00000002:Player"]) while its owner was offline.Mechanism
handle_session_end(map-server/src/processor.rs:598) removes the registry handle and session maps but:StoredActorfromzone.core.actors, and0x00CB RemoveActorto remaining clients.A correct despawn primitive already exists —
apply_despawn_actor(map-server/src/runtime/quest_apply.rs:~1453) broadcasts RemoveActor and cleans the registry; the session-end path just never uses it.Note the ghost is inert on the wire (zero packets sourced from the ghost actor in later sessions — packet-log census), so this is a stale-state/visual defect, not the opening-quest crash (that was the case-resolution bug, fixed in
feature/ubuntuf6897e5). It still accumulates one stale actor per disconnect per zone.Suggested fix
On session end, remove the player's StoredActor from the zone and broadcast RemoveActor via the existing primitive (mind the deferred-warp/zone-change paths where the actor must survive the handoff).