gameOverRoom

fun CoroutineScope.gameOverRoom(room: Room, storage: RaftStorage = InMemoryRaftStorage(), raftConfig: RaftConfig = RaftConfig(), identity: ClientIdentity = ClientIdentity.Auto, overlay: CoroutineScope.(Seam) -> Seam? = null): RoomGameSession

Bootstrap a RoomGameSession over an already-adopted Room, so the game surfaces the room's presence directly instead of the caller hand-wiring a room.events → presence adapter.

This is the roster-given path: the voter set is taken from the room's current Room.roster (plus this peer), and Raft elects the leader symmetrically — there is no appoint-the-host quorum block (which would suspend gameOverRoom until enough peers joined). The game rides a single named Room.channel view (GAME_ROOM_CHANNEL); the game's internal mux tags nest inside that one channel.

Single-ownership contract. gameOverRoom takes ownership of room: the returned session's lifecycle owns it. Do not call Room.leave on room directly afterwards — hand the adopted room straight into gameOverRoom and drive teardown through RoomGameSession.close.

Mesh-latency note. On a mesh, joiner↔joiner Raft frames over the room channel are dropped until the host has admitted each member; Raft retries make convergence eventual.

Clock. The game inherits the room's time domain — the room's own detectors run on the clock it was constructed with — so, like gameNode (the other roster-given path), gameOverRoom takes no clock. Timing is the room's concern here.

Parameters

room

The already-adopted room (e.g. from an election lobby's adopt). Its current Room.roster plus this peer becomes the voter set.

storage

Durable Raft state. Defaults to InMemoryRaftStorage.

raftConfig

Timing and behaviour parameters. Tests pass RaftConfig(expectVirtualTime = true).

identity

How this peer obtains its Raft §8 dedup id. See gameNode.

overlay

Optional gossip-flood wrapper for the broadcast plane; null (default) gives a flat mux over the room channel. See gameNode.