Skip to content

[FEAT] Slot-based Inventory container support#39

Merged
Snifer merged 9 commits into
Snifer:masterfrom
AntonioMorenoRubio:feat/slot-and-container-inventory
Jul 4, 2026
Merged

[FEAT] Slot-based Inventory container support#39
Snifer merged 9 commits into
Snifer:masterfrom
AntonioMorenoRubio:feat/slot-and-container-inventory

Conversation

@AntonioMorenoRubio

Copy link
Copy Markdown
Contributor

Closes #38

Summary

Add proper support for slot-based and container-based inventory, so items inside named slots are tracked as individual entries and reflected correctly in the Resources & Inventory dashboard.

Implementation

Two optional fields are added to ParsedItem:

  • slotParent?: string — the name of the container this item belongs to, if any
  • isContainer: boolean — whether this entry is a container rather than a regular item

All slot logic is isolated in two new private methods — parseInventorySlot and upsertSlotContainer — so it is easy to locate, review, and extend independently of the rest of parseInventory.

When the parser encounters a tag whose name matches the pattern Word N (e.g. Slot 1, Backpack 2, Hand1), it treats it as a container and extracts its contents:

[Inv:Backpack 1|Torch×6]
  → map: "Backpack 1" { isContainer: true, quantity: "" }
  → map: "Torch"      { quantity: "6", slotParent: "Backpack 1" }

[Inv:Slot 1|Short Sword]
  → map: "Slot 1"      { isContainer: true, quantity: "" }
  → map: "Short Sword" { quantity: "1", slotParent: "Slot 1" }

[Inv:Slot 4|empty]
  → map: "Slot 4" { isContainer: true, quantity: "" }

Regular items and deltas work exactly as before:

[Inv:Torch-1]  → resolves against "Torch" entry → quantity "5"

Container mutation syntax is also supported:

[Inv:Backpack 1|+Pickaxe]        → adds "Pickaxe" with slotParent "Backpack 1"
[Inv:Backpack 1|-Pickaxe]        → removes "Pickaxe" from the map
[Inv:Backpack 1|Pickaxe->Shovel] → renames "Pickaxe" to "Shovel" in place
[Inv:Backpack 1|Pickaxe→Shovel]  → same, unicode arrow normalized before processing

Properties on slot items are also supported:

[Inv:Slot 2|Shield|cracked]      → Shield with property "cracked" inside Slot 2
[Inv:Slot 2|Potion×4|d4|healing] → Potion with quantity 4 and properties "d4", "healing" inside Slot 2

The unicode arrow is normalized to -> before processing quantities. Section 1.2 of the Resource Tracking Add-On manual uses it in examples such as [Inv:Torch|3→2] — whether intentional or a typo, users will copy and paste from the manual and should not be penalized for it.

Changes

  • src/utils/parser.tsParsedItem extended with slotParent and isContainer; parseInventorySlot and upsertSlotContainer added; unicode arrow normalization in quantities
  • src/ui/resource-view.ts — inventory grid now classifies items into containers, children, and loose items; containers render as labeled sections with their items inside; renderItemCard extracted as a private method
  • styles.css — added .ll-slot-section, .ll-slot-header, .ll-slot-name, .ll-slot-empty
  • tests/parser.test.ts — 20 new tests covering slot containers, sub-items, deltas, mutations, and properties

Current Limitations

Item name uniqueness

The inventory map uses the item name as its key. If two containers hold items with the same name, only the first entry is kept:

[Inv:Hand 1|Sword|d8|sharp]
[Inv:Hand 2|Sword|d4|rusty]  ← gets ignored. Sword only exists in Hand 1.

The manual already addresses this by recommending unique item names — Sword (main) vs Sword (off) — or using slot notation where the slot ID provides the disambiguation naturally. No changes to the data model are needed for this case; it is a player-side naming convention.

Additional Context

I also found this in the manual's Q&A section:

Q: How do I handle containers, bags of holding, saddle-bags?
A: Either nest descriptively — [Inv:Bag of Holding|contains: Wand, Scrolls×3, Gold 100] — or track the container and contents separately. For slot-based systems, just mark which slots are "in the bag." Don't over-engineer it.

This PR follows exactly that second approach — tracking containers and contents separately, with the slot name as the linking key. The descriptive nesting pattern (contains: ...) is left untouched and treated as freeform properties, as intended.

[Inv:Quiver|1|Arrow×15] and [Inv:Adventuring Kit|1|contains: rope, pitons, torch×2, rations×3] are intentionally out of scope. They represent a different pattern (item-as-container) that requires a design decision from the author. Should the notation evolve to something like [Inv:Quiver 1|Arrow×15], it would be handled naturally by this implementation without further changes.

It is my understanding that this follows the spirit of the Lonelog Addon Guidelines:

  • Does not replace Core Symbols
  • Does not conflict with existing tags
  • Extends, doesn't Invent
  • Applies to both Analog and Digital

Screenshots

imagen imagen imagen

@AntonioMorenoRubio

Copy link
Copy Markdown
Contributor Author

Just rebased my branch on top of your latest master (1.6.0 + Partylog support) as this feature was made in 1.5.7 — GitHub confirms no conflicts and the merge is clean. I have also checked the code myself and I can see that partylog-parser.ts uses the classes from parser.ts All 30+ tests in parser.test.ts still pass alongside the new ones in partylog-parser.test.ts suite.

I haven't touched CHANGELOG.md or manifest.json since versioning decisions are yours to make. Allow edits by mantainers is checked, if you need to do some quick changes directly.

imagen

@Snifer

Snifer commented Jun 19, 2026

Copy link
Copy Markdown
Owner

I had a quick look at the failing CI run and it seems to be a real TypeScript strictness issue rather than a CI misconfiguration. The errors on src/utils/parser.ts (TS2532 and TS2322) point to the new parseInventorySlot logic, specifically inside the isSlotMultiplier branch where parts, sub and sub are used as if they were always present.

I’ll take a deeper look at the overall slot‑based inventory design and tests over the weekend before merging, but I wanted to flag this TS issue first so we can get CI green again and merge.

Regards,
Snifer

@AntonioMorenoRubio

Copy link
Copy Markdown
Contributor Author

Fixed — added a type guard in the isSlotMultiplier loop to make sure the sub[] variables are not undefined in runtime. I have passed your CI build command, and tests are still green. CI should be green now.

@Snifer Snifer merged commit 04968c9 into Snifer:master Jul 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Slot-based inventory container support

2 participants