Add plain-language item type template documentation
This commit is contained in:
@@ -48,6 +48,7 @@
|
|||||||
- Global/type-level properties are loaded from server registry in `server/app/item_catalog.py`.
|
- Global/type-level properties are loaded from server registry in `server/app/item_catalog.py`.
|
||||||
- Per-type use/update validation and message behavior are handled in `server/app/item_type_handlers.py`.
|
- Per-type use/update validation and message behavior are handled in `server/app/item_type_handlers.py`.
|
||||||
- Client-side add/edit metadata is handled in `client/src/items/itemRegistry.ts`.
|
- Client-side add/edit metadata is handled in `client/src/items/itemRegistry.ts`.
|
||||||
|
- End-to-end add-item template: `docs/item-type-template.md`.
|
||||||
|
|
||||||
## Type Params
|
## Type Params
|
||||||
|
|
||||||
|
|||||||
118
docs/item-type-template.md
Normal file
118
docs/item-type-template.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Item Type Template
|
||||||
|
|
||||||
|
This page is a practical, copy/paste template for adding a new item type with the current registry-based system.
|
||||||
|
|
||||||
|
Use this when you want a new item type without editing one huge `if/elif` chain.
|
||||||
|
|
||||||
|
## Plain-English Flow
|
||||||
|
|
||||||
|
When a new item type is added, you wire it in four places:
|
||||||
|
|
||||||
|
1. Server catalog (`item_catalog.py`)
|
||||||
|
- Defines global defaults shared by all instances of that type:
|
||||||
|
- default title
|
||||||
|
- default params
|
||||||
|
- use sound / emit sound
|
||||||
|
- cooldown
|
||||||
|
|
||||||
|
2. Server behavior (`item_type_handlers.py`)
|
||||||
|
- Defines what happens when users edit params (`validate_update`).
|
||||||
|
- Defines what happens when users press `use` (`use`).
|
||||||
|
|
||||||
|
3. Shared type unions (`models.py`, protocol/state types)
|
||||||
|
- Adds the new type name to type literals/unions so packets validate.
|
||||||
|
|
||||||
|
4. Client item registry (`itemRegistry.ts`)
|
||||||
|
- Defines add-menu order, editable properties, and optional property dropdown choices.
|
||||||
|
|
||||||
|
That is enough for a first working item type.
|
||||||
|
|
||||||
|
## Example: `counter`
|
||||||
|
|
||||||
|
This sample item increments a number each time it is used.
|
||||||
|
|
||||||
|
### 1. Server Catalog (`server/app/item_catalog.py`)
|
||||||
|
|
||||||
|
```py
|
||||||
|
ItemType = Literal["radio_station", "dice", "wheel", "clock", "counter"]
|
||||||
|
|
||||||
|
ITEM_DEFINITIONS: dict[ItemType, ItemDefinition] = {
|
||||||
|
# ...existing...
|
||||||
|
"counter": ItemDefinition(
|
||||||
|
default_title="counter",
|
||||||
|
capabilities=("editable", "carryable", "deletable", "usable"),
|
||||||
|
use_sound=None,
|
||||||
|
emit_sound=None,
|
||||||
|
default_params={"value": 0},
|
||||||
|
use_cooldown_ms=1000,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Server Handler (`server/app/item_type_handlers.py`)
|
||||||
|
|
||||||
|
```py
|
||||||
|
def _validate_counter_update(_item: WorldItem, next_params: dict) -> dict:
|
||||||
|
try:
|
||||||
|
value = int(next_params.get("value", 0))
|
||||||
|
except (TypeError, ValueError) as exc:
|
||||||
|
raise ValueError("value must be a number.") from exc
|
||||||
|
if value < 0:
|
||||||
|
raise ValueError("value must be 0 or greater.")
|
||||||
|
next_params["value"] = value
|
||||||
|
return next_params
|
||||||
|
|
||||||
|
|
||||||
|
def _use_counter(item: WorldItem, nickname: str, _clock_formatter: Callable[[dict], str]) -> ItemUseResult:
|
||||||
|
current = int(item.params.get("value", 0))
|
||||||
|
next_value = current + 1
|
||||||
|
return ItemUseResult(
|
||||||
|
self_message=f"{item.title}: {next_value}",
|
||||||
|
others_message=f"{nickname} uses {item.title}: {next_value}",
|
||||||
|
updated_params={**item.params, "value": next_value},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
ITEM_TYPE_HANDLERS: dict[ItemType, ItemTypeHandler] = {
|
||||||
|
# ...existing...
|
||||||
|
"counter": ItemTypeHandler(
|
||||||
|
validate_update=_validate_counter_update,
|
||||||
|
use=_use_counter,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Type Unions
|
||||||
|
|
||||||
|
Update item-type unions/literals in:
|
||||||
|
|
||||||
|
- `server/app/models.py`
|
||||||
|
- `client/src/network/protocol.ts`
|
||||||
|
- `client/src/state/gameState.ts`
|
||||||
|
|
||||||
|
Add `"counter"` anywhere item types are enumerated.
|
||||||
|
|
||||||
|
### 4. Client Registry (`client/src/items/itemRegistry.ts`)
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export const ITEM_TYPE_SEQUENCE: ItemType[] = ['clock', 'counter', 'dice', 'radio_station', 'wheel'];
|
||||||
|
|
||||||
|
const ITEM_TYPE_EDITABLE_PROPERTIES: Record<ItemType, string[]> = {
|
||||||
|
// ...existing...
|
||||||
|
counter: ['title', 'value'],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ITEM_TYPE_GLOBAL_PROPERTIES: Record<ItemType, Record<string, string | number | boolean>> = {
|
||||||
|
// ...existing...
|
||||||
|
counter: { useSound: 'none', emitSound: 'none', useCooldownMs: 1000 },
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
No dropdown options are needed here because `value` is a numeric text field.
|
||||||
|
|
||||||
|
## Checklist Before Commit
|
||||||
|
|
||||||
|
1. Add/adjust server tests for `use` and `update` validation.
|
||||||
|
2. Run `cd server && uv run --extra dev pytest`.
|
||||||
|
3. Run `cd client && npm run lint && npm run build`.
|
||||||
|
4. Update `docs/item-types.md` and `docs/item-schema.md` if behavior/defaults changed.
|
||||||
@@ -100,6 +100,8 @@ This is behavior-focused documentation for item types and their defaults.
|
|||||||
|
|
||||||
Item types are currently code-registered on both server and client so new types are additive instead of editing one large branch.
|
Item types are currently code-registered on both server and client so new types are additive instead of editing one large branch.
|
||||||
|
|
||||||
|
For a full copy/paste example with plain-English explanation, see `docs/item-type-template.md`.
|
||||||
|
|
||||||
1. Server catalog: add global defaults in `server/app/item_catalog.py` (`ITEM_DEFINITIONS`).
|
1. Server catalog: add global defaults in `server/app/item_catalog.py` (`ITEM_DEFINITIONS`).
|
||||||
2. Server handlers: add `validate_update` + `use` logic in `server/app/item_type_handlers.py` and register it in `ITEM_TYPE_HANDLERS`.
|
2. Server handlers: add `validate_update` + `use` logic in `server/app/item_type_handlers.py` and register it in `ITEM_TYPE_HANDLERS`.
|
||||||
3. Server models: extend `ItemType` literals in `server/app/models.py` and any packet enums that list item types.
|
3. Server models: extend `ItemType` literals in `server/app/models.py` and any packet enums that list item types.
|
||||||
|
|||||||
Reference in New Issue
Block a user