Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Scope or overlay

A scope describes a group, an overlay describes an individual exception. That is the rule, stated in The shared view and scopes and Overlays. This page is about applying it.

The two mechanisms answer different questions

The name of this page is slightly misleading, and the confusion is worth clearing first. Scopes and overlays are not two ways of doing one thing.

A scope answers what does this connection see. That answer is always a scope, returned from observation, and there is no alternative mechanism for it.

An overlay answers who else sees this element, for an element that would otherwise be shared. Its alternative is the shared view, not a scope.

The demonstration application makes the split visible. Staff observe three scopes, the same set spectators observe, so what they see is expressed in scopes. Their own presence is rendered into no shared channel at all, only into overlays. One connection, both mechanisms, each for its own question.

#![allow(unused)]
fn main() {
fn observation(&mut self, connection: ConnectionId) -> ScopeSet {
    match self.roles.get(&connection) {
        Some(Role::Player(side)) => ScopeSet::new(&[side_scope(*side)]),
        Some(Role::Spectator | Role::Admin { .. }) => watcher_view(),
        None => ScopeSet::new(&[Scope::ROOT]),
    }
    .unwrap_or(ScopeSet::NONE)
}
}

Placing an element

Once observation is settled, each element rendered is either shared, and therefore seen by everyone whose observation reaches its scope, or private to the connections whose overlay carries it.

situationplacement
team channels and their membersshared, at the team’s scope
a spectator watching both teamsshared, at a scope of its own
a vanished administratoroverlay, their own
an administrator addressing one teamone overlay entry per member of that team
a private channel one person holdsoverlay
a per-connection buttonoverlay, as a context action
proximity voiceneither: an audio relation, with no structural change

The last row matters more than it looks. Audibility is a third mechanism, not a consequence of the first two, so a distinction that is purely about who hears whom needs no scope and no overlay. Reaching for one is how special cases start. See Audio as a relation.

When a scope is an overlay in disguise

A scope with one observer is an overlay in disguise. A role is a group by nature even while it holds a single member: player, host, spectator, staff. The test is not the current headcount but whether a second member would be a change of data or a change of model.

Two bounds turn that judgement into a hard limit: a scope is at most four segments deep, and a connection observes at most four scopes. Running out is a modelling signal rather than a configuration problem. A design needing a fifth observed scope is usually describing individuals with a group mechanism.

Cost

mechanismcost
shared view and scopesO(W) once, plus O(|D|) per connection
overlayO(|overlay|) per connection, every turn
audio relationO(N + edges)

A scope is rendered once whatever the number of observers. An overlay is recomputed for its connection at every turn and never journalled, so nothing amortises it.

That asymmetry is the whole argument. Overlays stay cheap while they stay exceptional. An overlay whose size grows with the population is the quadratic shape the model exists to avoid, arriving through the one door left open. See Cost.

A worked decision

A game wants an administrator who is invisible, hears everything, and can address one team at a time.

Observation. The administrator has to see both teams to address either, so their observation is the watcher set. A scope, like every observation.

Presence. Invisible means absent from the shared view rather than present and suppressed. Nothing is rendered for them in any shared channel. Their own client still needs to find itself when the handshake names its session, so one overlay carries their presence to themselves alone.

Hearing. One-way listening on both team domains. No structural change.

Addressing a team. Two declarations that cannot be separated: an overlay entry giving each member of that team sight of the administrator, and a directed audio edge to each. Declaring the edge alone builds a render the runtime refuses, because a receiver who cannot see the sender is a receiver whose client discards the audio. See Seeing the speaker.