Permissions & moderation
Resolve game permissions, fill the Room management modal, and kick or ban players.
Most community rooms have some kind of staff: an owner, admins, maybe moderators. disko doesn't decide what those roles are. Instead, it gives your room a few building blocks, and you combine them into whatever roles your room needs:
Permissions: decide who may do the things games let you restrict.
The Room management modal: give players and staff buttons and settings.
Presentation: show who's who, such as an "Admin" badge.
Moderation: kick and ban.
An owner-and-admins room, for example, needs nothing more than these pieces. Every call on this page returns a Promise that settles once the change has taken effect.
Permissions
Games declare permissions with a
default, such as "pick-teams, restricted by default". In a room that decides
nothing, those defaults apply: "everyone", "restricted", or "owner" (the
player signed in with the room owner's account).
Your room can take over any permission with a resolver: a function that
answers "may this player do this?". room.game.permissions lists what the
loaded game declares, each with its name, label and default.
Answers are cached
A game checks permissions constantly, many times a second, and a resolver might be slow (it could look something up in a database). So the game never waits for your resolver. disko asks your resolver ahead of time, at moments when the answer can change, and keeps the answers. The game reads the kept answer instantly.
When your room's own facts change, for example when someone becomes an admin,
call room.permissions.refresh(...) so disko asks again.
room.permissions.resolve(name, resolver)decides one permission, androom.permissions.resolve(resolver)is a catch-all for every permission the loaded game declares. A named resolver takes precedence, and registering again replaces the resolver.room.permissions.remove(name?)removes a named resolver, or the catch-all without a name.A resolver receives
{ player, permission, game }and returnstrue,false, orundefinedfor the game's default (the declared default, or what the game set for that player withpermission.setDefault). Any other value, or an error, applies the default for that decision; errors are not caught and reach Node'suncaughtException.disko asks again when a player joins, when a game loads, when resolvers change, and on
room.permissions.refresh({ player?, permission? }). Until the first answer arrives, the game reads the permission as denied.
Room management modal
Every player has a Room button in the play client. It opens a modal with three sections: the player list, the room's options, and actions.
Your room doesn't draw this modal. It describes what's in it (which actions exist, which options, who may see or use them) and the client draws it the same way in every room. So players always find moderation and settings in a familiar place.
Player actions appear when someone clicks a player, such as Kick or Give admin.
Room actions appear in the Actions section, such as Clear bans.
Options are settings, such as which game to play or whether guests may join.
Player actions (
room.actions.player(id, definition)) appear in a player's detail view, room actions (room.actions.room(id, definition)) in the Actions section. A definition has alabel(1–48 bytes), an optionalconfirm(true, or{ reason: true }for an optional reason field), an optionalvisiblepredicate (omitted: everyone) andrun.Options come in four formats:
room.options.toggle,choice(1–32 choices),number(min,max, optionalstep) andtext(maxLengthup to 128, optionalsecret, whose value is never sent to viewers). Each has alabel, the currentvalue, and optionalvisible,editable(omitted: nobody, so the row is read-only) andchange.room.options.set(id, value)changes a value from the room; every viewer sees values live.visibleandeditableare checked again beforerunorchange, so a stale modal cannot act. A predicate that throws denies. Whenrunorchangethrows, the action or change is rejected and the viewer sees the error message.Ids are 1–64 bytes, and defining an action with the same id replaces it.
room.actions.remove("player" | "room", id)androom.options.remove(id)take entries away. Callroom.actions.refresh({ viewer? })when the facts behindvisiblechange.
Presentation and moderation
Presentation is how a player's name looks everywhere it appears: a color and a short badge, such as "Admin". Moderation is removing players: a kick lets them come back, a ban doesn't.
player.setPresentation({ color, badge })shows a palette role ("accent","success","warning","danger"or"muted") and a short badge (at most 12 characters) wherever the player's name appears;nullclears a field.player.kick(reason?)disconnects a player and shows them the reason. They may rejoin.player.ban({ reason? })bans and disconnects a player: signed-in players by account, guests by an engine-held network identity the room never sees. The reason is at most 256 bytes.room.bans.list()returns the bans, each withid,kind("account"or"guest"), the player'sname, thereason, asealedexport andlift(). A ban contains no address and no account.Bans last for the room's lifetime. To keep them across a restart, store the
sealedexports and pass each toroom.bans.import(sealed)when the same room starts again. Exports are sealed with a key derived from the room's hosting token, so they import only with that token.player.isOwnertells whether the player is signed in with the account that owns the room. Guests never are.
See the @disko-game/room reference for
every signature.