refactor: collapse item modules into plugins and remove no-op client item behaviors

This commit is contained in:
Jage9
2026-02-24 03:00:30 -05:00
parent d4dbb807da
commit 7903bab131
38 changed files with 375 additions and 345 deletions

View File

@@ -49,7 +49,7 @@
- Persisted state stores only instance data.
- Global/type-level properties are loaded from server registry in `server/app/item_catalog.py`.
- Per-type use/update validation and message behavior are implemented in per-item modules under `server/app/items/`, discovered via plugins in `server/app/items/types/*/plugin.py`.
- Per-type use/update validation and message behavior are implemented in per-item modules under `server/app/items/types/*/module.py`, discovered via plugins in `server/app/items/types/*/plugin.py`.
- Client-side add/edit metadata is consumed from `welcome.uiDefinitions` via `client/src/items/itemRegistry.ts` (no local fallback definitions).
- End-to-end add-item template: `docs/item-type-template.md`.

View File

@@ -1,50 +1,54 @@
# Item Type Template
This page is a practical template for adding a new item type with the current per-item module + single registry system.
This page is the practical template for the current plugin-driven item architecture.
## Plain-English Flow
When a new item type is added, wire it in these places:
When adding a new item type:
1. Server item module (`server/app/items/<name>.py`)
- Define item metadata constants:
- label/tooltip
- editable properties
- defaults/capabilities/sounds/cooldown/range/directional
- property metadata
1. Server item module
- Add `server/app/items/types/<item_type>/module.py`.
- Define metadata/constants:
- `LABEL`, `TOOLTIP`
- `EDITABLE_PROPERTIES`
- `CAPABILITIES`
- `USE_SOUND`, `EMIT_SOUND`
- `USE_COOLDOWN_MS`, `EMIT_RANGE`, `DIRECTIONAL`
- `DEFAULT_TITLE`, `DEFAULT_PARAMS`
- `PROPERTY_METADATA`
- Implement behavior:
- `validate_update(item, next_params)`
- `use_item(item, nickname, clock_formatter)`
2. Server registry (`server/app/items/registry.py`)
- Add one module entry in `ITEM_MODULES`.
- Update `ITEM_TYPE_ORDER` if needed.
2. Server plugin file
- Add `server/app/items/types/<item_type>/plugin.py` exporting:
- `type`
- `order`
- `module`
3. Shared item type unions
3. Shared item-type unions
- Add the type in:
- `server/app/models.py`
- `client/src/network/protocol.ts`
- `client/src/state/gameState.ts`
4. Client fallback metadata
- Add defaults in `client/src/items/itemRegistry.ts`:
- `DEFAULT_ITEM_TYPE_SEQUENCE`
- `DEFAULT_ITEM_TYPE_EDITABLE_PROPERTIES`
- `DEFAULT_ITEM_TYPE_GLOBAL_PROPERTIES`
4. Client runtime behavior (optional)
- Default: no item-specific client module needed.
- Add `client/src/items/types/<item_type>/behavior.ts` only if this item needs custom client runtime UX/audio logic (for example piano mode).
That is enough for a first working item type.
## Minimal Server Module Example: `counter`
`server/app/items/counter.py`:
`server/app/items/types/counter/module.py`:
```py
from __future__ import annotations
from typing import Callable
from ..item_types import ItemUseResult
from ..models import WorldItem
from ...item_types import ItemUseResult
from ...models import WorldItem
LABEL = "counter"
TOOLTIP = "Counts up each time you use it."
@@ -84,19 +88,15 @@ def use_item(item: WorldItem, nickname: str, _clock_formatter: Callable[[dict],
)
```
Then register it in `server/app/items/registry.py`:
Then add plugin registration in `server/app/items/types/counter/plugin.py`:
```py
from . import clock, counter, dice, radio, wheel
from . import module
ITEM_TYPE_ORDER: tuple[str, ...] = ("clock", "counter", "dice", "radio_station", "wheel")
ITEM_MODULES: dict[str, ItemModule] = {
"clock": clock,
"counter": counter,
"dice": dice,
"radio_station": radio,
"wheel": wheel,
ITEM_TYPE_PLUGIN = {
"type": "counter",
"order": 25,
"module": module,
}
```

View File

@@ -42,7 +42,7 @@ This is behavior-focused documentation for item types and their defaults.
- `mediaVolume`: integer `0..100`
- `mediaEffect`: `reverb | echo | flanger | high_pass | low_pass | off`
- `mediaEffectValue`: number `0..100` with `0.1` precision
- `facing`: number `0..360` with `0.1` precision
- `facing`: number `0..360` with step `1`
- `emitRange`: integer `5..20`
## `dice`
@@ -141,7 +141,7 @@ This is behavior-focused documentation for item types and their defaults.
### Validation
- `enabled`: boolean or on/off style input
- `directional`: boolean or on/off style input
- `facing`: number `0..360` with `0.1` precision
- `facing`: number `0..360` with step `1`
- `emitRange`: integer `1..20`
- `emitVolume`: integer `0..100`
- `emitSoundSpeed`: integer `0..100` (`0=0.5x`, `50=1.0x`, `100=2.0x`) for speed/pitch
@@ -193,7 +193,7 @@ Server is the source of truth for item type definitions and metadata. The client
For a full copy/paste example with plain-English explanation, see `docs/item-type-template.md`.
1. Server item module: add a new file under `server/app/items/` with:
1. Server item module: add a new file under `server/app/items/types/<item_type>/module.py` with:
- defaults/capabilities
- property metadata/options
- `validate_update` and `use_item`
@@ -204,7 +204,7 @@ For a full copy/paste example with plain-English explanation, see `docs/item-typ
The server auto-discovers plugins at boot, so no central registry edit is needed.
3. Server models: extend `ItemType` literals in `server/app/models.py` and any packet enums that list item types.
4. Client protocol/state types: update item-type unions in `client/src/network/protocol.ts` and `client/src/state/gameState.ts`.
5. Client runtime behavior: add `client/src/items/types/<item_type>/behavior.ts` only if custom client runtime is needed.
5. Client runtime behavior: add `client/src/items/types/<item_type>/behavior.ts` only if custom client runtime is needed (for example piano mode).
6. Tests: add or update server tests under `server/tests/` for use/update validation, unknown-key stripping, and `uiDefinitions` completeness.
### Example Shape