Skip to content

useInventory

useInventory is a hook that reads one of the player’s containers — a backpack, a bank, worn equipment — and returns a handle you read slots from.

useInventory(inv: InvRef): Container

The component follows the whole container.

src/inventory.ts2
export const Backpack = (): Component => {
const inventory = useInventory(Inventories.INVENTORY);
  • inv: An Inventories.* reference from a generated dictionary.

A Container handle:

inv[slot]the item in a slot, or -1 if it is empty
inv.count(slot)how many of the item in that slot
inv.total(item)how many of an item across the whole container
inv.sizehow many slots the container has
inv.param(slot, ref), inv.paramText(slot, ref), inv.paramSprite(slot, ref)a parameter of the item in a slot, typed as the accessor names — see param
inv.map(fn)one component per slot; fn(item, i) — Rendering lists
inv.scan(fn, by, from?)the same walk carrying a running total — Rendering lists
inv.filter(fn)the slots fn(item, slot) keeps, for a .map() after it

Every member works anywhere in the render.

  • Read-only. Moving or using items is the server’s business, reached through options.
  • An empty slot reads -1, not 0 — 0 is a real item.
  • map visits every slot, empty ones included, so a slot keeps its place when it empties. Its second parameter is the visible index: the count of rows built so far, which is the slot number until a .filter() drops some. .filter()’s own second parameter is the real slot.
  • A .filter() under a component that reads state draws a warning (TS2E251). Put the test inside the row instead, as Slot does.
  • The handle cannot travel as a prop (TS2E101). Pass the reference and let the child call the hook.
refused/use-inventory.ts2
const Purse = ({ bag }: { bag: Container }): Component => ( // no such prop type
src/inventory.ts2
const Slot = ({ item, count, slot }: { item: Item; count: Int; slot: Int }): Component => (
<layer x={(slot % COLUMNS) * SLOT_W} y={(slot / COLUMNS) * SLOT_H} w={SLOT_W} h={SLOT_H}>
{item !== -1 && (
<sprite x="center" y="center" w={36} h={32} item={item} itemCount={count}
options={['Use', '', '', '', 'Drop', '', '', '', '', 'Examine']} />
)}
</layer>
);
export const Backpack = (): Component => {
const inventory = useInventory(Inventories.INVENTORY);
return (
<layer w="fill" h="fill">
{inventory.map((item, slot) => (
<Slot item={item} count={inventory.count(slot)} slot={slot} />
))}
</layer>
);
};

Arithmetic is whole-number, so slot / COLUMNS is the row index with nothing to round.

src/equipment.ts2
<WornSlot item={worn[HEAD]} slot={HEAD} x={77} y={4} />
<WornSlot item={worn[CAPE]} slot={CAPE} x={36} y={43} />
src/inventory.ts2
const Purse = (): Component => {
const inventory = useInventory(Inventories.INVENTORY);
const coins = inventory.total(Items.COINS);
src/reference-arrays.ts2
let slot: Int = 0;
while (slot < bag.size) {
if (bag[slot] === -1) {
counts[EMPTY] = counts[EMPTY] + 1;
} else if (bag.count(slot) > 1) {
counts[STACK] = counts[STACK] + 1;
} else {
counts[SINGLE] = counts[SINGLE] + 1;
}
slot = slot + 1;
}

An empty slot is -1. Test item !== -1, not item !== 0 — item 0 exists.

Check the read is in the code producing markup rather than in a handler, and that the component is visible.

I want to pass the inventory to a child component

Section titled “I want to pass the inventory to a child component”

Pass the reference, not the handle, and let the child call useInventory itself.