Multiplayer --> Rooms and invites
createRoom() does not take a player-typed room key. joinRoom takes { inviteCode } only.
await client.authenticate(token);
const created = await client.createRoom();
showCode(created.inviteCode);
const joined = await client.joinRoom({ inviteCode: "123456" });
New rooms get a 6-digit code. Older 16-character hex codes still resolve. create() stays invite-only unless the game passes { visibility: "public" }.
Public rooms
const rooms = await client.listPublicRooms({ limit: 50 });
await room.create({ visibility: "public", modeLabel: "casual" });
await room.joinPublic({ roomId: rooms.rooms[0].roomId });
A public summary includes only an opaque roomId, occupancy, whether the room is joinable, and an optional bounded modeLabel. Invite codes, player identities, and authoritative state are never listed. Private, unlisted, and matchmaking rooms never appear. Rooms are scoped to the caller’s project.
Loki’s SDK does not add a public lobby screen. Every game builds the room browser and all loading, empty, joining, full-room, waiting, readiness, and error states, alongside a Create private room control and a Create public room control. The Loki overlay does not list, create, or join public rooms. Do not make every room public.
Matchmaking
const room = await client.matchmake({
minPlayers: 2,
maxPlayers: 8,
teamSize: 2,
});
Fill-N / team matchmaking creates the same Loki room type. Matchmaking is still blind pairing. Public rooms are a per-project browser, not a global cross-game pool.
Resolve and leave
const { roomId, inviteCode } = await client.resolveInvite("123456");
await client.leaveRoom();
Call leave() only from Leave / End Game. Invalid codes fail with INVITE_INVALID. A full room returns ROOM_FULL.