Teams & Banners
A team is a name, a short tag, a banner and a roster, and it belongs to the players rather than to the server. Create one from the referee desk's Team screen or with /vbteam anywhere on the map, invite people, paint a flag, and that flag is what flies over your half of the net.
Nothing here gates playing. Config.Teams.enabled = false and every court, command, referee desk, ball cart and beach circle behaves exactly as before; what goes away is the Team screen, the banners on the scorebar and the "Play with team" button. It is a social layer over the game, never a door in front of it.
The roster
A team holds up to Config.Teams.maxMembers: six as shipped.
| Role | May |
|---|---|
| Owner | Everything: invite, remove, edit the banner, rename, promote and demote, start a team match, disband |
| Officer | Invite, remove, edit the banner, rename, start a team match |
| Member | Play |
An officer may remove people but may not promote them, and that pair is the design: give an officer promotions and any officer can raise a friend to owner-adjacent power or demote their peers, and together that is a takeover from a rank handed out to save the owner some clicking.
Rank is asked as well as permission. You may only act on somebody strictly below you, so two officers cannot remove each other and nobody can act on themselves. There is exactly one owner and no way to mint a second, so an owner's own exit is disband, or leave, on a team of one.
One table decides all of it and both the panel and the server read it, so a button the panel draws and an action the server accepts can never drift apart.
Invites
Adding a member is an invite the other player has to accept. It arrives as a focus-less prompt (ENTER accepts, BACKSPACE declines) that never takes your mouse or your controls.
- Thirty seconds before the same person may be asked again, by anyone. The limit is on the person being asked, not the sender: an invite lands on somebody else's screen, so a per-sender limit still lets ten players take turns putting a prompt in front of one victim.
- A decline mutes that pairing for three minutes, because otherwise "no" means nothing.
- One open invite per person, and every condition is re-checked when the offer is accepted rather than when it was sent: in thirty seconds a team can be disbanded, renamed or filled.
- There is no proximity requirement. A team is not a place, so the candidate list is every eligible player connected. Anyone already in a team is left out rather than shown greyed out.
The banner
Two kinds, and one validator that the panel and the server both run, so what a player is allowed to paint and what the server will keep can never disagree. No two-minute paint job refused on save.
Painted. A 16×12 grid of palette colours, fifteen of them plus transparent. The editor is in the panel: brush, eraser, flood fill, eyedropper, clear, thirty steps of undo, a strip of fifteen swatches you can replace with a colour picker, and two previews, one at true size and one at 4×. A whole banner is under 350 bytes, which is why it can ride a match snapshot instead of being a download.
A link. One https:// URL, which each viewer's own browser fetches. Setting a URL replaces the painted art and vice versa; a banner has exactly one kind.
Any https host is allowed by default, which means any player can put any image on every other player's scorebar. There is no review queue: a banner is live on every screen in the match the moment it is saved. To restrict it, list hostnames in Config.Teams.imageHosts: the host is parsed off the URL rather than searched for inside it, so i.imgur.com.evil.com is refused by a list that names imgur. The painted kind is untouched by any of this and is what to point players at on a server that does not want links at all.
Team names and tags are cleaned at the one door into the registry: control characters and GTA colour codes are stripped, whitespace collapses, and a tag is uppercased down to letters and digits. Lengths are refused, never truncated: a truncation can cut a UTF-8 character in half and persist the mojibake onto every scorebar that name ever appears on.
Playing as a team
"Play with team" appears on the roster when the panel was opened at a referee desk. It calls your online team-mates to that court's lobby and puts everyone who accepts on the same side.
The court decides the format and there is no size on the wire at all: a 2v2 court runs a 2v2 whoever calls it. The panel shows the court's own format rather than asking, and caps the invite list at the seats left beside the host. A 1v1 court says so instead of offering a party nobody could join.
Passive grouping is the quiet half: walk up to a court where a team-mate is already in the lobby, press Join, and you land on their half instead of having to notice which one they picked. It is a seat, never a decision; you are not readied, the side picker is still in front of you, and one click moves you. It applies in the lobby only, never overrides a side you picked yourself, and Config.Teams.autoSide = false turns it off.
Where the banner shows up
On the scorebar, in the plate beside each side's name:
- A one-on-one: the player, not their team, whatever team they are in. A 1v1 has no side to represent, and two members of the same team meeting across the net would otherwise get one identical name and one identical picture on both halves of the bar, so the bar could not name either of them. It is the match's format that decides this and not the court's: a 1v1 played on the 3v3 court is a 1v1 here.
- The team, at 2v2 and 3v3, when every human on that side belongs to the same one.
- A lone player: when there is exactly one human on the side, their own name.
- Neither: when the side mixes teams, or teamed and unteamed players. Two players from different teams have no shared identity to draw, and picking one of their flags would put the other under it.
Admin
A team is player-owned, so nobody but its owner can remove one in game, which is right until a team is named something you will not have on your server. From the server console:
vsvb_teams | Every team, with id, tag, name, member count and whether it has a banner |
vsvb_team_delete <id> | Delete one. Everybody in it is told and their panel refreshes |
There is no rename and no transfer here on purpose: an admin who needs one has the table and a SQL client.