Sessions in Realms
Several worlds on one server — planets, interiors, space — each replicated at its own scale; a client is in one of them at a time.
Status: 🚧 Partial · Visibility: Public · Level: 🟣 Advanced · Category: Subscriptions
🎯 What it solves
A realm is an isolated world with its own spatial grid, cell size and dimensionality. A client must see the realm it is in and nothing of any other, even where two realms use the same local coordinates; a realm nobody watches must cost replication nothing; and a player walking through a door must switch worlds without a reconnect.
⚙️ How it works (in brief)
- One realm per session. The application places a session (
Place(session, realm, position),Enter(session, realm),Leave(session)), or its profile follows an entity (AroundControlled(),Bind(entity)), whose realm after the tick's fence is the session's — a teleport switches its sessions in the same tick. With several realms a session nobody placed is in none. - The switch is one frame: a
RESETwhose first block isREALM— the realm's bounds, cell, position width, kind and tag — over which every position that follows decodes. The committed realm (RealmOf) moves only when that frame is published; a skipped switch is retried. - Each realm with a session is served by its own replication, built on first use from the realm's
RealmConfig.Replication(kind, cell, tag) and put to sleep when its last session has left; a realm no session is in costs no replication work. - Kinds and variants.
subs.RealmKinds("planet", "interior"); a profile'sIn(kind, v => …)serves realms of that kind with other observers (a World in a one-room interior, a wide Sphere in space),NotIn(kinds)serves nothing there — one profile name for every scale. - Events are realm-scoped:
RouteNear(point, realm)andRouteToKnownfile in the point's or entity's realm;RouteToRealm(realm, subtree)reaches a realm, or with its subtree the realms below it in theParenttree. - Commands are decoded over the realm the client held when it built them; a position built in a realm the session has left is refused with
ACK REALM_CHANGED, and every command carriesClientCommand.Realm.
💻 Usage
dbe.Realms.Register(new RealmId(7), new RealmConfig
{
Grid = SpatialGridConfig.Flat(new Vector2(0, 0), new Vector2(64, 64), 16),
WhenUnobserved = RealmUnobserved.Sleep, SleepAfterTicks = 200, UnobservedTickDivisor = 1,
Parent = new RealmId(1), // a cantina on planet 1: routing only
Replication = new RealmReplicationConfig { Kind = "interior", CellM = 16, AppTag = 42 },
});
subs.RealmKinds("planet", "interior");
subs.Profile("player", p =>
{
p.Sphere(192, leave: 208).AroundControlled().Of<Player>().Of<Npc>();
p.In("interior", v => v.World().AroundControlled().Of<Player>().Of<Npc>());
});
ctx.Subscriptions.Enter(godSession, new RealmId(1)); // a camera with no entity to follow
⚠️ Guarantees & limits
- A session holds, hears and resolves only its own realm (SUB-28); a switch is one published
RESET|REALM(SUB-29); a positioned value is encoded and decoded with exactly one realm's frame (SUB-30). - An entity moving between realms leaves one and enters the other with a new network identity.
- A realm's position width is the replication block layout's (24 bits); a realm without
Replicationtakes no session. - Not built:
At(realm, position)(a fixed anchor is realm 0),Follow(entity),SessionsIn(realm), theRealmClosedsession event, per-realm position widths.
🧪 Tests
RealmSessionTests, RealmEventTests, RealmReplicationTests (engine); the REALM goldens and refusals (protocol, both SDKs).
🔗 Related
- Realms — Several Worlds in One Engine — registering realms,
[RealmKey], queries and policy - Wire protocol & catalog — the
REALMblock · Profiles & observers · Events - Design:
claude/design/Subscriptions/12-realms.md· Decision: ADR-068