# 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 ```mermaid graph LR this["lib-core.inventory-list"] comp["lib-core.composition"] engine["engine.*"] this --> comp this --> engine ``` ## 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.`), 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.` 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.` 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.