# dcl-bar-kit reference
Everything the package exports. For a first bar, see [Getting started](getting-started.md).
```ts
import {
setupBar, addBartender, closeBarMenu, barMenu,
BETA, BLIP, mocktails,
holdDrink, handBack, finishDrink, dropDrink, holdingDrink, heldDrink,
BarUi, BarMenu, AnotherDialog, DropNotice,
whisper, setBarAssetRoot, barAsset
} from 'dcl-bar-kit'
import type { Personality, Beat, BarOptions, BartenderPlacement, Drink, DrinksOptions, Line, BubbleStyle } from 'dcl-bar-kit'
```
dcl-bar-kit is built on [dcl-sittables](sittables-reference.md), which it installs: its sitting drinking emotes are
played in dcl-sittables' seats.
---
## The bar
### `setupBar(options: BarOptions)`
Sets up the menu, what the special does, and how drinks behave. Call it once, in `main()`, before `addBartender`.
```ts
setupBar({
drinks: [...mocktails(), myLemonade],
title: 'THE LOUNGE',
subtitle: 'mixed by {bartender} · on the house',
onSpecial: (bartender, item) => openTheBackRoom()
})
```
| `BarOptions` | Type | Default | |
|---|---|---|---|
| `drinks` | `Drink[]` | (required) | The menu, in order. Two cards a row. |
| `title` | `string` | `'THE BAR'` | The menu's heading. |
| `subtitle` | `string` | `'mixed by {bartender}'` | Under it. `{bartender}` becomes the name of the bartender who handed the menu over. |
| `onSpecial` | `(bartender: string, drink: Drink) => void` | — | Someone's ordered a special (a menu item with `glass: null`) and the bartender's played its routine for it. Only runs for the player who ordered it. |
| `visibleTo` | `(address: string) => boolean` | everyone | Whose glasses and drops to show, by lower-case wallet address. See [below](#hiding-some-players-drinks). |
| `holdSeconds` | `number` | `300` | How long a drink lasts. When it's up, it's gone (not dropped); mid-emote, it waits until you next move. |
| `spill` | `boolean` | `true` | Sprinting or jumping with a drink spills it. |
| `dropOnEmote` | `boolean` | `true` | Playing any other emote drops it. |
`setupBar` also takes over dcl-sittables' [sit handler](sittables-reference.md#setsithandlerfn--null), and loads every
drink's glass and emotes up front so the first of each isn't slow.
### `addBartender(personality, placement)`
Puts a bartender behind your bar.
```ts
addBartender(BETA(), { position: Vector3.create(14, 0, 21), facing: 180 })
```
| `BartenderPlacement` | | |
|---|---|---|
| `position` | `Vector3` | On the floor behind the counter (the models hover by themselves). |
| `facing` | `number` | The way it faces, degrees (0: +Z, 90: +X): toward the customers. |
Give each bartender a different `name`: the scene keeps track of them by name. The kit's bartenders hold the shaker
0.25–0.36 m in front of them, so put the counter's back edge about 0.6–1 m in front of `position` (the example has it
0.6 m). Their bodies are solid, and they take clicks from up to 6 m away.
What a bartender does:
- **Its head follows you** when you're within 9 m, and wanders a little when nobody is. It blinks.
- **Clicked**, it says a greeting and hands you the menu. Walk more than 9 m away and the menu goes back.
- **Ordered a drink**, it says its `preparing` line, shakes the shaker for 1.6 s, and hands the drink over: it's in your
hand, and it says its `served` line.
- **Clicked while you hold a drink**, it asks its `another` line and shows "Would you like another?": yes opens the
menu, no hands the glass back (it says `tookGlass`).
- **Ordered a special**, it plays its `special` routine, then your `onSpecial` runs.
- **Now and then** (every 40–80 s, if you're within 6 m and it isn't busy talking) it mutters one of its `mutters`.
It talks in a holographic readout over its head, typed out a character at a time, that turns to face you and clears
itself a few seconds after it's finished.
### `barMenu`, `closeBarMenu()`
`barMenu` is the menu's state: `{ open: boolean, asking: boolean, from: string }`. `open` while the menu's showing,
`asking` while "Would you like another?" is, and `from` the bartender who handed it over. Read it to hide your own UI
while the menu's up, say. `closeBarMenu()` closes both.
---
## The bartenders
### `BETA()`, `BLIP()`
The two that come with the kit. Each call returns a new `Personality` (plain data), so you can change it:
```ts
addBartender({ ...BETA(), name: 'GAMMA', greetings: ['Welcome to the Rusty Nail.'] }, { position, facing: 180 })
```
- **BETA**: a mid-century hover-bot in ivory, brass and navy, with a bow tie. Dry, a little paranoid. Asked for the
special, he gives you a dirty look, checks nobody's watching, drops his voice, asks if you were followed, and only
then obliges. Afterwards he doesn't know what you're talking about.
- **BLIP**: small, round and pastel, with big eyes, blushing cheeks and a heart on her antenna. Delighted by everything,
the special most of all.
Their models live in the bar-kit assets (`models/bartender_*.glb`, `models/blip_*.glb`). If you've moved the assets,
call `setBarAssetRoot` before `BETA()` and `BLIP()`.
### `Personality`
What a bartender looks like and how it behaves. See [Your own bartender](custom-bartenders.md) for a walkthrough.
| Field | Type | |
|---|---|---|
| `name` | `string` | Unique among your bartenders. Shown in its hover text ("Order a drink from BETA") and the menu's subtitle. |
| `body` | `string` | Model path: the body, its origin on the floor under it, facing +Z. Solid, and takes clicks. |
| `head` | `string` | Model path: the head, its origin at the neck. Turns to follow you. |
| `shaker` | `string` | Model path: the cocktail shaker it holds, its origin at its middle. |
| `neck` | `number` | The head's height above the body's origin, metres. |
| `hand` | `Vector3` | Where the shaker's held, relative to the body's origin, in the bartender's own frame: `+z` in front of it, `+x` to its right. |
| `eyes` | `'visor' \| 'round'` | Drawn eyes that blink: two bars on a visor, or big round glowing ones with a highlight. |
| `bubble` | `BubbleStyle` | Its speech readout's look. |
| `bob` | `number` | How far it bobs as it hovers, metres (BETA 0.02, BLIP 0.035). |
| `greetings` | `string[]` | Said when clicked (one at random). |
| `preparing` | `string` | Said as it starts on a drink. |
| `served` | `(drink: Drink) => string` | Said handing it over. Default: the drink's own `served`, or "Here you go." |
| `another` | `string` | Said when clicked by someone holding a drink. |
| `tookGlass` | `string` | Said taking the glass back. |
| `mutters` | `string[]` | Said now and then to anyone nearby. |
| `jittery` | `boolean` | Glances about when it mutters. |
| `special` | `(grant: () => void, again: boolean) => Beat[]` | Its routine for a special: the beats to play. Call `grant` in the last beat's `then`: that's when `onSpecial` runs. `again` is true if a special was granted in the last two minutes. Without one: "Coming right up." and straight to `onSpecial`. |
| `afterSpecial` | `string[]` | Said, instead of a greeting, when clicked within two minutes of granting a special. |
Eyes: `'visor'` eyes narrow when it's nervous and narrow and tilt into a scowl when it glares; `'round'` eyes squeeze
into happy arcs, and the head tilts and wiggles when it's happy. BLIP-style (`'round'`) bartenders also look delighted
whenever they're clicked or hand something over.
### `Beat`
One moment in a routine.
| Field | Type | |
|---|---|---|
| `at` | `number` | Seconds from the start of the routine. |
| `say` | `Line` | A line to say (a string, or `whisper('…')`). |
| `nervous` | `number` | Glance about for this many seconds. |
| `glare` | `number` | Lean in and stare the customer down for this many seconds. |
| `happy` | `number` | Look delighted (hop, wiggle) for this many seconds. |
| `then` | `() => void` | Run this. |
```ts
special: (grant, again) => again
? [{ at: 0, say: 'Again? Go on then.', then: grant }]
: [
{ at: 0, say: '…', glare: 2 },
{ at: 2, say: whisper('Not so loud.'), nervous: 2 },
{ at: 4.5, say: whisper('Through the back. Quick.'), then: grant }
]
```
Leave a couple of seconds between lines: each is typed out at 45 characters a second and then held for 4.5 s, and a
new line replaces the last.
### `BubbleStyle`, `Line`, `whisper(text)`
`BubbleStyle` is the speech readout's look:
| Field | Type | |
|---|---|---|
| `tag` | `string` | A small tag over the text (BETA's "BETA-7 // VOX"). |
| `edge` | `Color3` | The glowing frame. |
| `text` | `Color4` | The words. |
| `panel` | `Color4` | The panel behind them. |
A `Line` is a string, or `whisper(text)`: in italics, dimmer. Lines wrap at about 24 characters.
---
## Drinks
### `Drink`
A menu item. Most are drinks; one with `glass: null` is a special (a password, say).
| Field | Type | |
|---|---|---|
| `id` | `string` | Unique on the menu. Used in emote file and animation names: see [custom drinks](custom-drinks.md). |
| `name` | `string` | On its menu card. |
| `blurb` | `string` | A line about it (keep it to one line on the card). |
| `tag` | `{ text: string, color: Color4 }` | A badge on the card (the mocktails' rarity). |
| `ingredients` | `string[]` | Under "MAKE IT AT HOME", one per line (room for about five). Leave out to hide the heading. |
| `method` | `string` | How to make it, at the bottom of the card (two short lines). |
| `color` | `Color3` | The drink's colour: the splash when it's dropped. |
| `glass` | `string \| null` | The glass's model path, held in the hand. `null` for a special. |
| `emotes` | `{ stand, sit, couch }` | Its drinking emotes (model paths ending `_emote.glb`): standing, sitting on a stool or bench, and on a couch. Without them, the glass is held but never drunk. |
| `served` | `string` | What the bartender says handing it over (unless its personality says otherwise). |
### `mocktails(): Drink[]`
The three that come with the kit, each with its glass and emotes:
| `id` | Name | Tag | Glass |
|---|---|---|---|
| `helium3` | Helium-3 Fizz | COMMON | clear blue highball |
| `plasma` | Plasma Crystal | UNCOMMON | purple highball |
| `mythic` | Mythic Bloom | MYTHIC | pink highball |
All three are non-alcoholic, with real at-home recipes on their cards. Call `setBarAssetRoot` first if you moved the
assets.
The glasses are `barAsset('models/glasses/lumen_rift_highball.glb')`, `nebula_tear_highball.glb` and
`synapse_highball.glb`, and you're welcome to use them for drinks of your own.
### Holding and drinking
What happens once you've a drink, all by itself:
- **Held**: the glass is in your right hand, walking about too. Everyone in the scene sees it.
- **Drunk**: stand still for a second (or sit) and your drinking emote starts: the glass at your chest, a sip every
eight seconds, a little club sway standing, a gentle sway and a tapping heel sitting. Everyone near sees it. Move and
it stops; stand still again and it starts again.
- **Dropped**: play any other emote and it falls from your hand and smashes, with a crash and a splash of its colour,
for everyone near: "You dropped your drink…". Sitting down and your scene's own emotes (`triggerSceneEmote`) don't
count.
- **Spilled**: sprint (faster than 9 m/s for a moment) or jump with it, and the same: "You spilled your drink… (no
sprinting with a drink!)". Not while seated.
- **Handed back**: tell the bartender you're done and it's gone.
- **Finished**: after `holdSeconds` it's gone.
A teleport (or a seat moving you) doesn't count as sprinting.
### `holdDrink(drink)`, `heldDrink()`, `holdingDrink()`
Hand the local player a drink yourself (a free round when someone walks in; a quest reward), replacing any they hold;
`holdDrink` ignores a special. `heldDrink()` is the one they're holding, or `null`; `holdingDrink()` whether they are.
```ts
const [welcome] = mocktails()
holdDrink(welcome) // from a button, a quest's reward, a timer…
```
### `finishDrink()`, `handBack()`, `dropDrink(why?)`
- `finishDrink()`: the drink's gone, quietly. If they were mid-drinking-emote, it carries on (with the emote's own
glass) until they move.
- `handBack()`: the same, but a drinking emote in progress is ended properly (standing, with a moment and then
Decentraland's idle; sitting, sat as before with hands on the thighs). What the bartender does when you say you're
done.
- `dropDrink(why)`: they drop it: it smashes for everyone, and `why` is shown (default "You dropped your drink…").
### Hiding some players' drinks
If your scene hides some players' avatars from others (a private room; players in different instances of a game), hide
their drinks too:
```ts
setupBar({ drinks, visibleTo: (address) => sameRoomAsMe(address) })
```
`visibleTo` is asked about every other player's glass and dropped drinks, often, so keep it cheap. Your own always show.
---
## The UI
### `BarUi`
Everything the bar draws on screen, each only when it's needed: the menu, the "Would you like another?" dialog, and
the "You dropped your drink…" notice. Put it in your scene's UI:
```tsx
export const ui = () => (
)
```
It sizes itself for the window, from a 1080-pixel-high reference.
### `BarMenu`, `AnotherDialog`, `DropNotice`
The three parts, to place yourself instead of `BarUi` (in a different order among your own UI, say).
- `BarMenu`: the menu, in the middle of the screen: a card for each drink, two to a row, and a close button.
- `AnotherDialog`: "Would you like another?", with YES, PLEASE and NO, THANKS.
- `DropNotice`: the drop message, near the top, for a few seconds.
---
## Asset folders
### `setBarAssetRoot(path)`, `barAsset(file): string`
`npx dcl-bar-kit-copy-assets` copies the models, emotes and sound to `assets/dcl-bar-kit/`. Copied elsewhere? Say so
first thing in `main()`, before `mocktails()`, `BETA()` or `BLIP()` (which read it):
```ts
setBarAssetRoot('art/bar/')
```
`barAsset(file)` gives a file's scene path under the root: `barAsset('models/glasses/synapse_highball.glb')`.
What's in the folder:
```
models/ bartender_body.glb bartender_head.glb bartender_shaker.glb blip_body.glb blip_head.glb
glasses/lumen_rift_highball.glb nebula_tear_highball.glb synapse_highball.glb
emotes/ _emote.glb _sit_emote.glb _couch_emote.glb for helium3, plasma and mythic
empty_emote.glb empty_sit_emote.glb empty_couch_emote.glb
audio/ glass_break.mp3
```
## Limits
- One bar per scene: `setupBar` is called once, and every bartender serves the same menu.
- A player holds one drink at a time.
- A drink's emotes carry their own glass (the emote's prop, since an emote can't hold a scene's model), a plain
highball in the drink's colour; the glass in the hand is the drink's `glass` model. See [custom drinks](custom-drinks.md).
- The bartenders aren't shared between players: each player's client runs its own, so nobody else sees a bartender
talking to you, or shaking your drink. (Your drink itself, and drinking it, everyone sees.)