initial: inventory-list v0.1.0 — list-container inventory over engine entity-tree
Provides add/remove/contents/contains/count over composition entities acting as list containers. Items attach as synthetic children under item.<n> slots; renderable tag toggled via composition.set_tag on add/remove. Slot counter is reconstruction-safe (derived from get_children scan, no persisted state). Depends on lib-core.composition 0.2.0 (get_container + set_tag).
This commit is contained in:
134
README.md
Normal file
134
README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# lib-core.inventory-list
|
||||
|
||||
List-container inventory over the `engine.entity` tree. Attaches items
|
||||
as synthetic children under slot names `item.1`, `item.2`, ... and
|
||||
manages the composition tag-index so items are hidden from the renderable
|
||||
index while inside a container.
|
||||
|
||||
**Version:** 0.1.0
|
||||
**Lib-ID:** lib-core.inventory-list
|
||||
**Requires:** lib-core.composition 0.2.0
|
||||
**Tags:** inventory, entity, composition, list-container
|
||||
|
||||
## Topology
|
||||
|
||||
<!-- topology:start (auto-generated; do not edit) -->
|
||||
```mermaid
|
||||
graph LR
|
||||
this["lib-core.inventory-list"]
|
||||
comp["lib-core.composition"]
|
||||
engine["engine.*"]
|
||||
this --> comp
|
||||
this --> engine
|
||||
```
|
||||
<!-- topology:end -->
|
||||
|
||||
## Scope (v0.1.0)
|
||||
|
||||
Thin list-container inventory spine. Items must be `stack_mode="individual"`.
|
||||
No weight, volume, or grid constraints (Phase F/G). No stackable items (Phase C+).
|
||||
|
||||
**Supported:**
|
||||
- `add(container, item)` — attach item to container under synthetic slot
|
||||
- `remove(container, item)` — detach item, return it
|
||||
- `contents(container)` — ordered list of items currently in container
|
||||
- `contains(container, item)` — membership check
|
||||
- `count(container)` — number of items
|
||||
|
||||
**Deferred (Loud-Error or not applicable):**
|
||||
- Stack items (`stack_mode != "individual"`) → Loud-Error in v0.1
|
||||
- Capacity / weight / volume constraints → Phase F/G
|
||||
|
||||
## API
|
||||
|
||||
### `inventory.add(container, item)`
|
||||
|
||||
**Syntax:** `inventory.add(container: entity, item: entity) -> void`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local inventory = require("lib-core.inventory-list")
|
||||
|
||||
inventory.add(backpack, sword)
|
||||
-- sword is now a child of backpack under "item.1"
|
||||
-- sword is removed from the renderable index
|
||||
```
|
||||
|
||||
**Description:** Validates that `container` is a composition-entity with
|
||||
`container={kind="list"}` (Loud-Error if not). Validates `item` has
|
||||
`stack_mode` property (Loud-Error if missing) and `stack_mode == "individual"`
|
||||
(Loud-Error otherwise). Detaches `item` from its current parent if any,
|
||||
attaches to `container` under the next synthetic slot (`item.<n>`), and
|
||||
calls `composition.set_tag(item, "renderable", false)` to remove the item
|
||||
from the renderable index.
|
||||
|
||||
### `inventory.remove(container, item) -> item`
|
||||
|
||||
**Syntax:** `inventory.remove(container: entity, item: entity) -> entity`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local dropped = inventory.remove(backpack, sword)
|
||||
-- sword detached from backpack; renderable tag restored
|
||||
-- caller re-parents dropped into world + sets position
|
||||
```
|
||||
|
||||
**Description:** Finds `item` in `container`'s children (Loud-Error if not
|
||||
present), detaches it via `entity.detach`, calls
|
||||
`composition.set_tag(item, "renderable", true)`, returns `item`.
|
||||
|
||||
### `inventory.contents(container) -> {item, ...}`
|
||||
|
||||
**Syntax:** `inventory.contents(container: entity) -> {entity, ...}`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
for _, it in ipairs(inventory.contents(backpack)) do
|
||||
print(it:get_property("name"))
|
||||
end
|
||||
```
|
||||
|
||||
**Description:** Returns all items currently in `container`, ordered by
|
||||
insertion order (numeric suffix of synthetic slot names). Filters children
|
||||
by the item-recognition rule: child must have a `stack_mode` property.
|
||||
Non-item children (future use) are silently excluded.
|
||||
|
||||
### `inventory.contains(container, item) -> bool`
|
||||
|
||||
**Syntax:** `inventory.contains(container: entity, item: entity) -> bool`
|
||||
|
||||
**Description:** Returns `true` if `item` is currently a child of
|
||||
`container` under a synthetic slot.
|
||||
|
||||
### `inventory.count(container) -> number`
|
||||
|
||||
**Syntax:** `inventory.count(container: entity) -> number`
|
||||
|
||||
**Description:** Returns the number of items currently in `container`.
|
||||
Equivalent to `#inventory.contents(container)`.
|
||||
|
||||
## Notes
|
||||
|
||||
### Synthetic Slot Naming
|
||||
|
||||
Items are stored under slot names `item.<n>` where `n` is a
|
||||
monotonically-increasing integer per container. The counter is not
|
||||
persisted — on any cold call `next_slot` scans existing children for
|
||||
`item.<n>` patterns and takes `max(n) + 1`. This makes slot naming
|
||||
reconstruction-safe after engine reload without any additional state.
|
||||
|
||||
### Item-Recognition Rule
|
||||
|
||||
An entity is recognized as an item if it has a `stack_mode` property
|
||||
(any non-nil, non-empty string value). The `stack_mode` must be
|
||||
`"individual"` for `add` to succeed in v0.1. This rule is consistent
|
||||
with the template convention for item templates (declaring `stack_mode`
|
||||
in their properties block).
|
||||
|
||||
### set_tag Interaction
|
||||
|
||||
`add` calls `composition.set_tag(item, "renderable", false)`, which
|
||||
removes the item from `lib-core.composition`'s `list_by_tag("renderable")`
|
||||
index. `remove` calls `set_tag(item, "renderable", true)` to restore it.
|
||||
This ensures items in inventory are invisible to the render system without
|
||||
any per-frame filtering.
|
||||
Reference in New Issue
Block a user