Roles & moderation
Give room roles, decide game roles, 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 are. Instead, it gives your room a few building blocks:
Room roles: your room's own staff, such as Admin, with a badge.
Game roles: decide who holds the roles the loaded game declares.
The Room management modal: give players and staff buttons, settings and role switches.
Moderation: kick and ban.
Every call on this page returns a Promise that settles once the change has taken effect.
Room roles
A room role is a power over the room: kick, ban, options, the game it runs. Games never see room roles.
room.role(name, { label, color?, badge? })declares a role. Declare roles from highest to lowest rank: a player's name shows the color and badge of the highest-ranking role they hold, unless the room set the player's presentation.role.give(player)androle.take(player)change who holds it;role.has(player)androle.holders()read it right away.room.roles.editable(rule)decides who may give and take room roles by hand in the modal: a function of{ viewer, target, role }, ortrue/false. Without one, the room's owner may.Every change, in code or by hand, arrives as
role-change({ player, role, held }).
Game roles
Games declare roles with a default, such as "host, the
owner by default". In a room that decides nothing, the defaults apply:
"everyone", "nobody", or "owner" (the player signed in with the room
owner's account). room.game.roles.declared lists them, each with its
name, label and default.
For one player, who holds a game role is decided in this order:
Your room's resolver, if it answers
trueorfalse.A person in the Room management modal, where no resolver decides.
The game's own
giveandtake.The default.
Answers are kept
A resolver might be slow (it could look something up in a database), so the game never waits for it. disko asks ahead of time, at moments when the answer can change, and keeps the answers. The game reads the kept answer instantly.
room.game.roles.resolve(name, resolver)decides one role, androom.game.roles.resolve(resolver)every role the loaded game declares. A named resolver takes precedence; registering again replaces it.room.game.roles.remove(name?)removes one, or the catch-all without a name.A resolver receives
{ player, role, game }and returnstrue,false, orundefinedto leave it to a person and then the game. Errors are not caught: they reach Node'suncaughtException, and the game decides.disko asks again when a player joins, a game loads, resolvers change, and on
room.game.roles.refresh({ player?, role? }). Until the first answer arrives, the game reads the role as not held.room.game.roles.editable(rule)decides who may give and take game roles by hand, asroom.roles.editabledoes for room roles.To change anything else about a game, such as its match length, use the events it documents with
room.emit.
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. A player's detail view also lists their room roles and game roles, with switches for viewers who may change them.
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.
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. disko asksvisibleandeditableagain whenever a room role changes hands; callroom.actions.refresh({ viewer? })when other facts behind them change.
Presentation and moderation
Presentation is how a player's name looks everywhere it appears: a color
and a short badge. Room roles set it for you; setPresentation overrides
it. 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.