Skip to content

docs: drop the world.ack running-maximum workaround - #47

Merged
Taure merged 2 commits into
mainfrom
docs/ack-monotonic
Aug 14, 2026
Merged

Taure merged 2 commits into
mainfrom
docs/ack-monotonic

Conversation

@Taure

@Taure Taure commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

asobi v0.84.1 (widgrensit/asobi#479) made world.ack monotonic per connection. asobi_player_session holds a last_ack_seq and drops any ack that does not advance it; the session is per WebSocket and dies with it, so the mark resets exactly when the client's counter does.

The Unity docs told readers to keep a running maximum and ignore any ack that did not advance it, because until v0.84.1 the mark was recorded per zone and a crossing player could receive a lower seq from the zone they left. That can no longer happen, so the workaround now defends against something the server guarantees against.

Removed

  • The per-zone paragraph: the mark being "held per zone, not per connection", zones acking independently, more than one ack per broadcast after a crossing, payload.seq going backwards, and the instruction to keep a running maximum (README.md).
  • The widgrensit/asobi#477 reference. The issue is closed.
  • The long _acked = -1 high-water variable and its if (ack.seq <= _acked) return; filter from the reconciliation sample.
  • The claim that acks keep arriving with an older mark after an out-of-range seq. The monotonic filter drops a non-advancing ack, so they do not.
  • The "nine world.ack frames per broadcast" half of the broadcast_interval bullet.

Reconciliation is now simply: drop every buffered input at or below ack.seq, then replay the rest on top of the accumulated state.

Version floor

The README bullet is a bare floor: Requires asobi core v0.84.1 or later. Nothing about what an older server does, because v0.84.0 does send acks; they can simply regress across a zone crossing.

The AsobiDispatcher comment stays at v0.84.0. It records when world.ack first appeared on the wire, which is provenance, not the floor for the monotonicity guarantee.

Reserved data key

Narrowed to its v0.84.1 rule wherever the docs mentioned it: only a payload whose sole key is data mapped to an object is unwrapped (deprecated, removed at the next protocol break). A data alongside other keys, or one whose value is not an object, is forwarded verbatim - siblings are no longer dropped. A payload that is not an object at all draws an error frame with reason invalid_payload rather than being read as empty input, and WorldInputAsync's XML docs now tell that same story as WsFrame instead of claiming the server cannot report a bad input at all.

Kept, unchanged

The opt-in rule, the high-water-mark semantics, a rejected input still advancing the mark, the ack being addressed to one connection and never riding the shared world.tick, the world.tick delta/accumulate guidance with its a/u/r ops, the full-snapshot-per-new-subscription and interest-ring behaviour, and broadcast_interval defaulting to 3 with 1 giving an ack every tick.

Docs and comments only - no behaviour change. dotnet test Tests/AsobiCore.NET: 128 passed.

Taure added 2 commits August 14, 2026 07:55
asobi v0.84.1 (widgrensit/asobi#479) makes world.ack monotonic per
connection: asobi_player_session holds a last_ack_seq and drops any ack
that does not advance it. The session is per WebSocket and dies with it,
so the mark resets exactly when the client's counter does.

Remove the client-side high-water filter the docs prescribed against the
old per-zone mark, the claim that seq can go backwards, the per-zone ack
explanation, and the widgrensit/asobi#477 reference. Reconciliation is
now: drop every buffered input at or below ack.seq, then replay the rest.

State the floor as asobi >= v0.84.1 rather than v0.84.0, which was
superseded the same day.

Also narrow the reserved `data` key to its v0.84.1 rule: only a payload
whose sole key is `data` holding an object is unwrapped (deprecated);
siblings are no longer dropped, and a non-object payload draws an
invalid_payload error frame instead of being read as empty input.
Keep the bare v0.84.1 floor for ack monotonicity and drop the consequence
clause: v0.84.0 servers do send acks, so "an older one sends nothing" was
false.

Revert the dispatcher comment to v0.84.0. It records when world.ack first
appeared on the wire, which is provenance, not the monotonicity floor.

Align WorldInputAsync with WsFrame: a non-object world.input payload draws
an error frame with reason invalid_payload, uncorrelated because the frame
carries no cid.
@Taure
Taure merged commit 037fbfd into main Aug 14, 2026
3 checks passed
@Taure
Taure deleted the docs/ack-monotonic branch August 14, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant