Dice / RNG API 0.1 — De Facto Specification
Status: Descriptive. Documents the dice/roll contract as it ships today (retroactively numbered
0.1; unversioned). Written from production source on branchversion/0.40.0. Quirks flagged ⚠︎.
1. The shared contract
packages/shared/src/utils/dice.ts
is the platform's canonical dice surface — deterministic, no I/O, usable on client
and server:
| Function | Line | Purpose |
|---|---|---|
rollDie(sides) |
:14 | single die |
rollD20() |
:21 | d20 shorthand |
rollDice(count, sides) |
:28 | array of rolls |
rollExpression(expr) |
:39 | evaluate a dice expression → DiceExpressionResult |
parseDiceExpression(expr) |
:85 | parse → ParsedDiceExpression | null |
rollSkillCheck(name, mod) |
:113 | skill-check helper |
rollAttack(input) |
:148 | attack roll |
rollDamage(input, isCritical) |
:194 | damage roll |
2. Consumers
- Action API —
roll()/rollDetailed()injected globals build on this contract (seeaction-api-0.1.md §3.4–3.5); ability shorthands (1d20+strength) resolve from property definitions. - Server —
rollAttack/rollDamage/rollExpressionare used server-side (e.g. roll tablesroutes/rollTables.ts,POST /:id/roll). - Module extension — the Module API's
DiceRollerExtensioncan replace the built-in 3D dice; the platform routes rolls through the active roller viadiceExtensionAdapter.tsDiceExtensionBridge.tsx.
3. Client rendering layer (in-house deterministic 3D dice)
apps/web renders rolls with an in-house deterministic 3D dice system (built-in
since v0.31.0; dice-box removed): the result is pre-simulated off-thread
(simulateRollOffThread,
InHouseDice/simClient.ts:108)
then the animation is symmetry-relabeled to land on the pre-decided value.
Rendering + chat integration:
Dice3D,
DiceRollMessage,
diceRoller.ts,
rollExpressionToChat.ts / rollDiceToChat.ts. Rolls sync to other clients over
the dice:roll socket event (see realtime-api-0.1.md),
wired by useDiceSync.ts.
4. Known gaps
- ⚠︎ Duplicate parser.
DiceRollMessage.tsxdefines its ownparseDiceExpression(:251) androllDice(:276), independent of the sharedutils/dice.tsimplementations — two dice grammars can drift apart. - Unversioned; expression grammar is defined only by the two parser implementations (no formal spec of supported syntax).