Files
sporel-lib-core.inventory-list/README.md
calic 788f499aeb fix(deps): cascade composition 0.4.0 + crafting 0.5.0 pins
Phase J (2026-08-03) bumped lib-core.composition 0.3.0->0.4.0 and
lib-core.crafting 0.3.0->0.5.0, but only vagrant-skeleton and
lib-core.crafting themselves were updated. Dependent manifests kept the
old pins, so dep-fetcher saw disagreeing pins on the same lib and
refused to start both spine-prototype (ENGINE_ERR_LIB_DEP_MISSING,
rc=19) and vagrant-skeleton ("dep check failed", conflict on
lib-core.composition + lib-core.crafting).

Unify all pins on the on-disk versions. No code changes required:
composition 0.4.0 is purely additive (the quality/condition loud-error
was removed; no signature changed), and crafting-display only consumes
crafting.can_craft + crafting.list_recipes, both still present, and
never referenced the `form` field retired by ADR-0055.

README "Requires:" lines synced to match the manifests (Gate 3).

milestone-check.sh: GREEN (build, ctest, smoke, devwrap-ci,
test-all-modules + anomaly scan). vagrant-skeleton headless run clean
at 60 CI frames.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 11:27:20 +02:00

4.8 KiB

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.4.0 Tags: inventory, entity, composition, list-container

Topology

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
  • add Loud-Errort, wenn das Container-Template ein Phase-F/G-Constraint-Feld deklariert (weight_max/volume_max/grid/accepts_fluid/accepts_gas/restrictions)

API

inventory.add(container, item)

Syntax: inventory.add(container: entity, item: entity) -> void

Example:

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:

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:

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

Example:

local has_rock = inventory.contains(backpack, rock)

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

Example:

local n = inventory.count(backpack)

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.