RoomGameSession

A GameSession bootstrapped over a membership-aware Room — so the game speaks the same presence vocabulary the room already emits, with no second source of truth.

Returned by gameOverRoom. In addition to everything a GameSession offers (drive the game through node, ride app traffic over appChannel), a room-backed session exposes the backing room's live membership: presence is room.events and roster is room.roster. A consumer that already knew how to render "who dropped / who's back" for a Room renders it for a game unchanged.

The raw, no-Room bootstraps (gameNode / gameHost / gameJoin) return a plain GameSession with no presence surface — "this session has presence" is a compile-time fact of the type, not a silently-empty flow.

Samples

runTest(StandardTestDispatcher(), timeout = TEST_WEDGE_BACKSTOP) {
    val loom = InMemoryLoom()
    val clock = { Instant.fromEpochMilliseconds(0) }
    fun factory() = SeamRoomFactory(loom, backgroundScope, clock)

    // Two peers form one room; the host hands its room to gameOverRoom.
    val hostRoom = factory().host(Pattern("my-game"))
    backgroundScope.launch { factory().join(InMemoryTag("my-game")) }
    hostRoom.roster.first { it.size == 1 }

    val game = backgroundScope.gameOverRoom(
        hostRoom,
        raftConfig = RaftConfig(expectVirtualTime = true, random = Random(1)),
    )

    // Render "who dropped / who's back" from the game's presence — the room's vocabulary, unchanged:
    // game.presence.collect { event ->
    //     when (event) {
    //         is MembershipEvent.Partitioned -> greyOut(event.peerId) // a link went silent
    //         is MembershipEvent.Resumed -> unGrey(event.peerId)      // …a legitimate link heal
    //         else -> Unit
    //     }
    // }
    assertEquals(1, game.roster.value.size) // the joiner is a live member of the game's roster

    game.close()
}

Properties

Link copied to clipboard

Host-verified principals of currently-linked peers, keyed by the PeerId each was verified against at admission — the hosted-path analogue of the relay path's Member.principal.

Link copied to clipboard
Link copied to clipboard

Live membership/presence events — identical to the backing Room's events.

Link copied to clipboard
val roster: StateFlow<Set<Member>>

Live roster with per-member Member.liveness — identical to the backing Room's roster.

Functions

Link copied to clipboard
fun appChannel(name: String): Seam

Returns the application Seam for the channel named name, idempotent per name.

Link copied to clipboard
open suspend override fun close(reason: CloseReason = CloseReason.Normal)

Tears down the game and the room it owns: stops the consensus node and closes the game channel view (GameSession.close), then leaves the backing Room.

Link copied to clipboard
fun leave()

Signals a voluntary departure from the game session.

Link copied to clipboard

The host-verified Principal of peer, or null if that peer is not currently linked with an attestation. A convenience snapshot of attestedPrincipals.