2026-02-21 16:42:42 -05:00
|
|
|
# Item Types
|
|
|
|
|
|
|
|
|
|
This is behavior-focused documentation for item types and their defaults.
|
|
|
|
|
|
|
|
|
|
## Shared Item Behavior
|
|
|
|
|
|
|
|
|
|
- Items are server-authoritative.
|
|
|
|
|
- Global per-type fields are injected by the server and are not persisted per-instance:
|
|
|
|
|
- `capabilities`
|
|
|
|
|
- `useSound`
|
|
|
|
|
- `emitSound`
|
|
|
|
|
- `useCooldownMs` (from item catalog)
|
2026-02-21 19:37:08 -05:00
|
|
|
- `emitRange` (spatial range in squares)
|
|
|
|
|
- `directional` (directional attenuation enabled)
|
2026-02-21 16:42:42 -05:00
|
|
|
- Instance fields are persisted in `server/runtime/items.json`.
|
|
|
|
|
|
|
|
|
|
## `radio_station`
|
|
|
|
|
|
|
|
|
|
### Defaults
|
|
|
|
|
- Title: `radio`
|
|
|
|
|
- Params:
|
|
|
|
|
- `streamUrl=""`
|
|
|
|
|
- `enabled=true`
|
2026-02-21 22:55:20 -05:00
|
|
|
- `mediaChannel="stereo"`
|
2026-02-21 22:38:48 -05:00
|
|
|
- `mediaVolume=50`
|
2026-02-21 22:55:20 -05:00
|
|
|
- `mediaEffect="off"`
|
|
|
|
|
- `mediaEffectValue=50`
|
2026-02-21 19:37:08 -05:00
|
|
|
- `facing=0`
|
2026-02-21 20:31:34 -05:00
|
|
|
- `emitRange=20`
|
2026-02-21 16:42:42 -05:00
|
|
|
- Global:
|
|
|
|
|
- `useSound=none`
|
|
|
|
|
- `emitSound=none`
|
|
|
|
|
- `useCooldownMs=1000`
|
2026-02-21 19:37:08 -05:00
|
|
|
- `emitRange=20`
|
|
|
|
|
- `directional=true`
|
2026-02-21 16:42:42 -05:00
|
|
|
|
|
|
|
|
### Use
|
|
|
|
|
- `use` toggles `enabled` on/off and broadcasts chat status.
|
|
|
|
|
|
|
|
|
|
### Validation
|
2026-02-21 22:55:20 -05:00
|
|
|
- `mediaChannel`: `stereo | mono | left | right`
|
2026-02-21 22:38:48 -05:00
|
|
|
- `mediaVolume`: integer `0..100`
|
2026-02-21 22:55:20 -05:00
|
|
|
- `mediaEffect`: `reverb | echo | flanger | high_pass | low_pass | off`
|
|
|
|
|
- `mediaEffectValue`: number `0..100` with `0.1` precision
|
2026-02-21 19:37:08 -05:00
|
|
|
- `facing`: number `0..360` with `0.1` precision
|
2026-02-21 20:31:34 -05:00
|
|
|
- `emitRange`: integer `5..20`
|
2026-02-21 16:42:42 -05:00
|
|
|
|
|
|
|
|
## `dice`
|
|
|
|
|
|
|
|
|
|
### Defaults
|
|
|
|
|
- Title: `Dice`
|
|
|
|
|
- Params:
|
|
|
|
|
- `sides=6`
|
|
|
|
|
- `number=2`
|
|
|
|
|
- Global:
|
|
|
|
|
- `useSound=sounds/roll.ogg`
|
|
|
|
|
- `emitSound=none`
|
|
|
|
|
- `useCooldownMs=1000`
|
2026-02-21 19:37:08 -05:00
|
|
|
- `emitRange=15`
|
|
|
|
|
- `directional=false`
|
2026-02-21 16:42:42 -05:00
|
|
|
|
|
|
|
|
### Use
|
|
|
|
|
- Rolls `number` dice with `sides` sides and reports values + total.
|
|
|
|
|
|
|
|
|
|
### Validation
|
|
|
|
|
- `sides`: integer `1..100`
|
|
|
|
|
- `number`: integer `1..100`
|
|
|
|
|
|
|
|
|
|
## `wheel`
|
|
|
|
|
|
|
|
|
|
### Defaults
|
|
|
|
|
- Title: `wheel`
|
|
|
|
|
- Params:
|
|
|
|
|
- `spaces="yes, no"`
|
|
|
|
|
- Global:
|
|
|
|
|
- `useSound=sounds/spin.ogg`
|
|
|
|
|
- `emitSound=none`
|
|
|
|
|
- `useCooldownMs=4000`
|
2026-02-21 19:37:08 -05:00
|
|
|
- `emitRange=15`
|
|
|
|
|
- `directional=false`
|
2026-02-21 16:42:42 -05:00
|
|
|
|
|
|
|
|
### Use
|
|
|
|
|
- Announces spin immediately.
|
|
|
|
|
- Result is sent after delay.
|
|
|
|
|
|
|
|
|
|
### Validation
|
|
|
|
|
- `spaces`: comma-delimited values
|
|
|
|
|
- At least 1 entry
|
|
|
|
|
- Max 100 entries
|
|
|
|
|
- Max 80 chars per entry
|
|
|
|
|
|
|
|
|
|
## `clock`
|
|
|
|
|
|
|
|
|
|
### Defaults
|
|
|
|
|
- Title: `clock`
|
|
|
|
|
- Params:
|
|
|
|
|
- `timeZone="America/Detroit"`
|
|
|
|
|
- `use24Hour=false`
|
|
|
|
|
- Global:
|
|
|
|
|
- `useSound=none`
|
|
|
|
|
- `emitSound=sounds/clock.ogg`
|
|
|
|
|
- `useCooldownMs=1000`
|
2026-02-21 19:37:08 -05:00
|
|
|
- `emitRange=10`
|
|
|
|
|
- `directional=false`
|
2026-02-21 16:42:42 -05:00
|
|
|
|
|
|
|
|
### Use
|
|
|
|
|
- Reports current time from item timezone and format.
|
|
|
|
|
|
|
|
|
|
### Validation
|
|
|
|
|
- `timeZone`: one of `CLOCK_TIME_ZONE_OPTIONS` in `server/app/item_catalog.py`
|
|
|
|
|
- `use24Hour`: boolean or on/off style input
|
2026-02-21 18:31:25 -05:00
|
|
|
|
2026-02-21 22:20:15 -05:00
|
|
|
## `widget`
|
|
|
|
|
|
|
|
|
|
### Defaults
|
|
|
|
|
- Title: `widget`
|
|
|
|
|
- Params:
|
|
|
|
|
- `enabled=true`
|
|
|
|
|
- `directional=false`
|
|
|
|
|
- `facing=0`
|
|
|
|
|
- `emitRange=15`
|
2026-02-21 22:38:48 -05:00
|
|
|
- `emitVolume=100`
|
2026-02-21 23:10:17 -05:00
|
|
|
- `emitSoundSpeed=50`
|
2026-02-21 23:17:18 -05:00
|
|
|
- `emitSoundTempo=50`
|
2026-02-21 22:55:20 -05:00
|
|
|
- `emitEffect="off"`
|
|
|
|
|
- `emitEffectValue=50`
|
2026-02-21 22:20:15 -05:00
|
|
|
- `useSound=""`
|
|
|
|
|
- `emitSound=""`
|
|
|
|
|
- Global:
|
|
|
|
|
- `useSound=none`
|
|
|
|
|
- `emitSound=none`
|
|
|
|
|
- `useCooldownMs=1000`
|
|
|
|
|
- `emitRange=15`
|
|
|
|
|
- `directional=false`
|
2026-02-21 23:17:18 -05:00
|
|
|
- `emitSoundSpeed=50`
|
|
|
|
|
- `emitSoundTempo=50`
|
2026-02-21 22:20:15 -05:00
|
|
|
|
|
|
|
|
### Use
|
|
|
|
|
- `use` toggles `enabled` on/off and plays `useSound` when configured.
|
|
|
|
|
|
|
|
|
|
### Validation
|
|
|
|
|
- `enabled`: boolean or on/off style input
|
|
|
|
|
- `directional`: boolean or on/off style input
|
|
|
|
|
- `facing`: number `0..360` with `0.1` precision
|
|
|
|
|
- `emitRange`: integer `1..20`
|
2026-02-21 22:38:48 -05:00
|
|
|
- `emitVolume`: integer `0..100`
|
2026-02-21 23:17:18 -05:00
|
|
|
- `emitSoundSpeed`: integer `0..100` (`0=0.5x`, `50=1.0x`, `100=2.0x`) for speed/pitch
|
|
|
|
|
- `emitSoundTempo`: integer `0..100` (`0=0.5x`, `50=1.0x`, `100=2.0x`) for tempo
|
2026-02-21 22:55:20 -05:00
|
|
|
- `emitEffect`: `reverb | echo | flanger | high_pass | low_pass | off`
|
|
|
|
|
- `emitEffectValue`: number `0..100` with `0.1` precision
|
2026-02-21 22:20:15 -05:00
|
|
|
- `useSound`: empty, filename (assumed under `sounds/`), or full URL
|
|
|
|
|
- `emitSound`: empty, filename (assumed under `sounds/`), or full URL
|
|
|
|
|
|
2026-02-22 23:42:17 -05:00
|
|
|
## `piano`
|
|
|
|
|
|
|
|
|
|
### Defaults
|
|
|
|
|
- Title: `piano`
|
|
|
|
|
- Params:
|
|
|
|
|
- `instrument="piano"`
|
2026-02-23 00:22:36 -05:00
|
|
|
- `voiceMode="poly"`
|
|
|
|
|
- `octave=0`
|
2026-02-22 23:42:17 -05:00
|
|
|
- `attack=15`
|
|
|
|
|
- `decay=45`
|
2026-02-23 00:05:01 -05:00
|
|
|
- `release=35`
|
|
|
|
|
- `brightness=55`
|
2026-02-22 23:42:17 -05:00
|
|
|
- `emitRange=15`
|
|
|
|
|
- Global:
|
|
|
|
|
- `useSound=none`
|
|
|
|
|
- `emitSound=none`
|
|
|
|
|
- `useCooldownMs=1000`
|
|
|
|
|
- `emitRange=15`
|
|
|
|
|
- `directional=false`
|
|
|
|
|
|
|
|
|
|
### Use
|
|
|
|
|
- Announces that the user begins playing the piano (client enters piano key mode).
|
2026-02-23 00:36:36 -05:00
|
|
|
- Piano mode controls include `,` to start/stop recording (max 30s) and `.` to play saved recording.
|
|
|
|
|
- Recordings are stored on the item (server-authoritative), so nearby users hear playback.
|
2026-02-22 23:42:17 -05:00
|
|
|
|
|
|
|
|
### Validation
|
2026-02-23 00:22:36 -05:00
|
|
|
- `instrument`: `piano | electric_piano | guitar | organ | bass | violin | synth_lead | brass | nintendo | drum_kit`
|
|
|
|
|
- `voiceMode`: `poly | mono`
|
|
|
|
|
- `octave`: integer `-2..2`
|
2026-02-22 23:42:17 -05:00
|
|
|
- `attack`: integer `0..100`
|
|
|
|
|
- `decay`: integer `0..100`
|
2026-02-23 00:05:01 -05:00
|
|
|
- `release`: integer `0..100`
|
|
|
|
|
- `brightness`: integer `0..100`
|
2026-02-22 23:42:17 -05:00
|
|
|
- `emitRange`: integer `5..20`
|
2026-02-23 00:22:36 -05:00
|
|
|
- Instrument changes reset `voiceMode`/`octave`/`attack`/`decay`/`release`/`brightness` to instrument defaults.
|
2026-02-22 23:42:17 -05:00
|
|
|
|
2026-02-21 18:31:25 -05:00
|
|
|
## Adding A New Item Type (Registry V1)
|
|
|
|
|
|
2026-02-21 22:04:17 -05:00
|
|
|
Item types are currently code-registered on both server and client. Server item logic is split per item module and wired through one registry.
|
2026-02-21 18:57:02 -05:00
|
|
|
|
|
|
|
|
For a full copy/paste example with plain-English explanation, see `docs/item-type-template.md`.
|
2026-02-21 18:31:25 -05:00
|
|
|
|
2026-02-21 22:04:17 -05:00
|
|
|
1. Server item module: add a new file under `server/app/items/` with:
|
|
|
|
|
- defaults/capabilities
|
|
|
|
|
- property metadata/options
|
|
|
|
|
- `validate_update` and `use_item`
|
|
|
|
|
2. Server registry: add one entry in `server/app/items/registry.py`:
|
|
|
|
|
- `ITEM_MODULES`
|
|
|
|
|
- `ITEM_TYPE_ORDER` (if ordering changes)
|
2026-02-21 18:31:25 -05:00
|
|
|
3. Server models: extend `ItemType` literals in `server/app/models.py` and any packet enums that list item types.
|
2026-02-21 22:04:17 -05:00
|
|
|
4. Client fallback registry: add type defaults in `client/src/items/itemRegistry.ts` (`DEFAULT_ITEM_TYPE_SEQUENCE`, editable/global fallback metadata).
|
|
|
|
|
5. Client protocol/state types: update item-type unions in `client/src/network/protocol.ts` and `client/src/state/gameState.ts`.
|
2026-02-21 18:31:25 -05:00
|
|
|
6. Tests: add or update server tests under `server/tests/` for use/update validation and cooldown behavior.
|
|
|
|
|
|
|
|
|
|
### Example Shape
|
|
|
|
|
|
|
|
|
|
A minimal new item type usually needs:
|
|
|
|
|
|
|
|
|
|
- Catalog defaults:
|
|
|
|
|
- `default_title`
|
|
|
|
|
- `default_params`
|
|
|
|
|
- `use_sound` / `emit_sound`
|
|
|
|
|
- `use_cooldown_ms`
|
|
|
|
|
- Handler behavior:
|
|
|
|
|
- validate params on update
|
|
|
|
|
- build self/others use messages
|
|
|
|
|
- optionally return delayed result text
|