Avatar position sync between Slipstream viewers over the helper (sender-authoritative, 2 m bound) #1417

Open
opened 2026-11-04 01:04:25 +00:00 by sky_line · 0 comments
Owner

Goal

Fix avatar position desync between viewers by having each Slipstream user share their own precise position with nearby Slipstream viewers over the Slipstream helper (the LSL bridge, slbridge.{h,cpp} and app_settings/slbridge/slipstream_helper.lsl). Other viewers then draw that avatar where its own viewer shows it, instead of where their interpolation of the sim's updates puts it.

Today every viewer reconstructs other avatars from the sim's object updates (terse updates with velocity, extrapolated between them). Where those reconstructions differ from what the owner sees, two people see each other in different places:

  • avatars stopping, turning or jumping;
  • movement under lag;
  • sitting and vehicle offsets;
  • hover height.

Rules (owner's)

  • The sender is authoritative for their own position. Nobody sends positions for anyone else, and a receiver never accepts a position for avatar A from anything but A's own helper. Identity comes from the sim (llGetOwnerKey() of the speaking attachment), never from the message body, as the helper already does for poses.
  • 2 m bound. A shared position may never differ by more than 2 m from that avatar's in-world position:
    • Receivers check it against the position they get from the sim for that avatar. More than 2 m away means the shared position is rejected for that update, and the avatar falls back to normal sim-driven placement. Receivers must enforce this themselves, because a modified helper or viewer can send anything.
    • The sender's helper also clamps against llGetPos() before speaking, as a first line.
  • Visual only. It changes where other viewers draw the avatar. It never changes anything the sim decides: physics, collisions, sit targets, Combat 2.0 hits, camera constraints.

Design to work out

  • Message: a version-tagged line in the helper's existing style, for example pos/1|<seq>|<region-local pos>|<velocity>|<rotation>|<flags>. Positions are region-local, at better than terse-update precision. It needs to cover:

    • seated and vehicle avatars: whether to send the position relative to the seat or root prim;
    • a flag for sitting, flying or stopped.
  • Transport and range:

    • The helper broadcasts on a public Slipstream channel. That could be llRegionSay limited by distance, or llSay/llShout to bound who hears it.
    • Each receiving helper forwards only lines from avatars its owner can plausibly see. That needs a draw-distance or interest list from its viewer.
    • Receiving helpers stay silent unless their viewer pinged within the last minute, as with poses today.
  • Update rate and budget:

    • Send only when the position or velocity changes beyond a threshold, with a low keep-alive, for example 2–10 Hz while moving and nothing when still.
    • Work within LSL chat throttles and the helper's per-speaker and overall rate budgets. The cost per region has to stay bounded with many Slipstream users present.
    • Fixed cost and bounded memory in the viewer: a per-avatar table with a cap and expiry, and no growth with crowd size beyond the cap.
  • Timing: there's no shared clock, so receivers need a way to order and age updates:

    • the sequence number;
    • a receive time;
    • optionally a helper-side timestamp (llGetTime or region time).

    Then blend from the sim-driven pose to the shared one smoothly, never snapping, and back again when updates stop or the bound is broken.

  • Combat and RLV:

    • Confirm it can't be used to look somewhere else while being somewhere else. The 2 m bound, visual-only, keeps hit boxes on the sim's position. State this in the docs.
    • Respect RLV restrictions that hide positions, and any privacy setting that opts out of sharing. Sharing should be on by default only if the owner decides so.
  • Interop: non-Slipstream viewers ignore the channel. Older Slipstream helpers without pos/1 simply don't send. The helper version bump redeploys automatically through the existing hash versioning.

Done when

  • Two Slipstream viewers side by side see each other's avatar in the same place, within a few centimetres, while walking, stopping, turning, jumping and sitting. Before and after measurements are recorded.
  • A forged or modified sender can't move another avatar, and can't place itself more than 2 m from its in-world position on a receiver.
  • Helper and viewer stay within their rate and memory budgets in a crowded region. Measure script time, chat volume and viewer CPU.
  • Nothing changes for non-Slipstream viewers, or when the helper isn't worn.
## Goal Fix avatar position desync between viewers by having each Slipstream user share their own precise position with nearby Slipstream viewers over the Slipstream helper (the LSL bridge, `slbridge.{h,cpp}` and `app_settings/slbridge/slipstream_helper.lsl`). Other viewers then draw that avatar where its own viewer shows it, instead of where their interpolation of the sim's updates puts it. Today every viewer reconstructs other avatars from the sim's object updates (terse updates with velocity, extrapolated between them). Where those reconstructions differ from what the owner sees, two people see each other in different places: - avatars stopping, turning or jumping; - movement under lag; - sitting and vehicle offsets; - hover height. ## Rules (owner's) - **The sender is authoritative for their own position.** Nobody sends positions for anyone else, and a receiver never accepts a position for avatar A from anything but A's own helper. Identity comes from the sim (`llGetOwnerKey()` of the speaking attachment), never from the message body, as the helper already does for poses. - **2 m bound.** A shared position may never differ by more than 2 m from that avatar's in-world position: - **Receivers** check it against the position they get from the sim for that avatar. More than 2 m away means the shared position is rejected for that update, and the avatar falls back to normal sim-driven placement. Receivers must enforce this themselves, because a modified helper or viewer can send anything. - **The sender's helper** also clamps against `llGetPos()` before speaking, as a first line. - **Visual only.** It changes where other viewers draw the avatar. It never changes anything the sim decides: physics, collisions, sit targets, Combat 2.0 hits, camera constraints. ## Design to work out - **Message:** a version-tagged line in the helper's existing style, for example `pos/1|<seq>|<region-local pos>|<velocity>|<rotation>|<flags>`. Positions are region-local, at better than terse-update precision. It needs to cover: - seated and vehicle avatars: whether to send the position relative to the seat or root prim; - a flag for sitting, flying or stopped. - **Transport and range:** - The helper broadcasts on a public Slipstream channel. That could be `llRegionSay` limited by distance, or `llSay`/`llShout` to bound who hears it. - Each receiving helper forwards only lines from avatars its owner can plausibly see. That needs a draw-distance or interest list from its viewer. - Receiving helpers stay silent unless their viewer pinged within the last minute, as with poses today. - **Update rate and budget:** - Send only when the position or velocity changes beyond a threshold, with a low keep-alive, for example 2–10 Hz while moving and nothing when still. - Work within LSL chat throttles and the helper's per-speaker and overall rate budgets. The cost per region has to stay bounded with many Slipstream users present. - Fixed cost and bounded memory in the viewer: a per-avatar table with a cap and expiry, and no growth with crowd size beyond the cap. - **Timing:** there's no shared clock, so receivers need a way to order and age updates: - the sequence number; - a receive time; - optionally a helper-side timestamp (`llGetTime` or region time). Then blend from the sim-driven pose to the shared one smoothly, never snapping, and back again when updates stop or the bound is broken. - **Combat and RLV:** - Confirm it can't be used to look somewhere else while being somewhere else. The 2 m bound, visual-only, keeps hit boxes on the sim's position. State this in the docs. - Respect RLV restrictions that hide positions, and any privacy setting that opts out of sharing. Sharing should be on by default only if the owner decides so. - **Interop:** non-Slipstream viewers ignore the channel. Older Slipstream helpers without `pos/1` simply don't send. The helper version bump redeploys automatically through the existing hash versioning. ## Done when - Two Slipstream viewers side by side see each other's avatar in the same place, within a few centimetres, while walking, stopping, turning, jumping and sitting. Before and after measurements are recorded. - A forged or modified sender can't move another avatar, and can't place itself more than 2 m from its in-world position on a receiver. - Helper and viewer stay within their rate and memory budgets in a crowded region. Measure script time, chat volume and viewer CPU. - Nothing changes for non-Slipstream viewers, or when the helper isn't worn.
sky_line added this to the Slipstream project 2026-11-04 01:04:25 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#1417
No description provided.