Equipment Slots
Create named equipment slots with optional type restrictions. Perfect for character gear, crafting stations, or any UI with specific input positions.
Prerequisites
Before starting, you should:
Overview
We'll create an equipment system by:
- Creating a container with
mode: 'slots'and aslotsarray - Optionally adding
slotFiltersfor type restrictions - Using
setSlot,getSlot, andclearSlotto manage equipment - Checking equippability with
canEquip
Step 1: Create a Slots Container
Define which slots exist using the slots array.
import { createInventoryManager } from '@motioneffector/inventory'
const inventory = createInventoryManager()
inventory.createContainer('equipment', {
mode: 'slots',
slots: ['head', 'chest', 'legs', 'feet', 'mainhand', 'offhand'],
})
Slot names are arbitrary strings—use whatever makes sense for your game.
Step 2: Add Slot Filters (Optional)
Restrict what items can go in each slot using filter functions.
inventory.createContainer('equipment', {
mode: 'slots',
slots: ['head', 'chest', 'legs', 'feet', 'mainhand', 'offhand'],
slotFilters: {
head: (itemId) => itemId.includes('helmet') || itemId.includes('hat'),
chest: (itemId) => itemId.includes('armor') || itemId.includes('robe'),
mainhand: (itemId) => itemId.includes('sword') || itemId.includes('staff'),
offhand: (itemId) => itemId.includes('shield') || itemId.includes('tome'),
},
})
Slots without filters accept any item.
Step 3: Equip Items
Use setSlot to equip items. It returns the previously equipped item (or null).
// Equip a helmet
inventory.setSlot('equipment', 'head', 'iron-helmet')
// Swap weapons - setSlot returns the old item
const oldWeapon = inventory.setSlot('equipment', 'mainhand', 'steel-sword')
console.log(oldWeapon) // null (nothing was equipped)
// Replace with a better weapon
const replaced = inventory.setSlot('equipment', 'mainhand', 'magic-sword')
console.log(replaced) // 'steel-sword'
Step 4: Query and Clear Slots
// Check what's equipped
const helmet = inventory.getSlot('equipment', 'head')
console.log(helmet) // 'iron-helmet'
// Get all slots at once
const allSlots = inventory.getAllSlots('equipment')
console.log(allSlots)
// { head: 'iron-helmet', chest: null, legs: null, feet: null, mainhand: 'magic-sword', offhand: null }
// Unequip an item
inventory.clearSlot('equipment', 'head')
// Or: inventory.setSlot('equipment', 'head', null)
Step 5: Check Before Equipping
Use canEquip to check if an item can go in a slot before trying.
// Check if a sword can go in the head slot
const result = inventory.canEquip('equipment', 'head', 'steel-sword')
console.log(result)
// { canAdd: false, maxAddable: 0, reason: 'slot_filter_failed' }
// Check valid equipment
const valid = inventory.canEquip('equipment', 'mainhand', 'steel-sword')
console.log(valid)
// { canAdd: true, maxAddable: 1 }
Complete Example
import { createInventoryManager } from '@motioneffector/inventory'
const inventory = createInventoryManager()
// Character equipment with slot restrictions
inventory.createContainer('gear', {
mode: 'slots',
slots: ['head', 'chest', 'legs', 'feet', 'mainhand', 'offhand', 'ring1', 'ring2', 'amulet'],
slotFilters: {
head: (id) => id.endsWith('-helmet') || id.endsWith('-hat') || id.endsWith('-hood'),
chest: (id) => id.endsWith('-armor') || id.endsWith('-robe'),
legs: (id) => id.endsWith('-pants') || id.endsWith('-greaves'),
feet: (id) => id.endsWith('-boots'),
mainhand: (id) => id.includes('sword') || id.includes('staff') || id.includes('axe'),
offhand: (id) => id.includes('shield') || id.includes('tome') || id.includes('dagger'),
ring1: (id) => id.startsWith('ring-'),
ring2: (id) => id.startsWith('ring-'),
amulet: (id) => id.startsWith('amulet-'),
},
})
// Equip a full set
inventory.setSlot('gear', 'head', 'steel-helmet')
inventory.setSlot('gear', 'chest', 'plate-armor')
inventory.setSlot('gear', 'mainhand', 'longsword')
inventory.setSlot('gear', 'offhand', 'tower-shield')
inventory.setSlot('gear', 'ring1', 'ring-of-strength')
inventory.setSlot('gear', 'amulet', 'amulet-of-protection')
// Check equipped items
const equipped = inventory.getAllSlots('gear')
console.log(equipped)
// Try to equip invalid item
try {
inventory.setSlot('gear', 'head', 'longsword') // Throws!
} catch (e) {
console.log('Cannot equip sword as helmet')
}
Variations
Crafting Station Slots
Use slots for crafting input/output positions.
inventory.createContainer('forge', {
mode: 'slots',
slots: ['input1', 'input2', 'fuel', 'output'],
slotFilters: {
input1: (id) => id.includes('ore') || id.includes('ingot'),
input2: (id) => id.includes('ore') || id.includes('ingot'),
fuel: (id) => id === 'coal' || id === 'wood',
// output has no filter - anything can go there
},
})
Dynamic Filter Based on Game State
// Filter that checks external game state
const canEquipTwoHander = (itemId: string) => {
const isTwoHanded = gameData.items[itemId]?.twoHanded
const offhandEmpty = inventory.getSlot('equipment', 'offhand') === null
return !isTwoHanded || offhandEmpty
}
inventory.createContainer('equipment', {
mode: 'slots',
slots: ['mainhand', 'offhand'],
slotFilters: {
mainhand: canEquipTwoHander,
},
})
Swapping Items Between Slots
function swapSlots(container: string, slot1: string, slot2: string) {
const item1 = inventory.getSlot(container, slot1)
const item2 = inventory.getSlot(container, slot2)
inventory.transaction(() => {
inventory.setSlot(container, slot1, null)
inventory.setSlot(container, slot2, null)
if (item1) inventory.setSlot(container, slot2, item1)
if (item2) inventory.setSlot(container, slot1, item2)
})
}
Troubleshooting
setSlot Throws Error
Symptom: setSlot throws ValidationError instead of returning false.
Cause: The slot filter rejected the item.
Solution: Use canEquip first to check, or wrap in try/catch:
if (inventory.canEquip('equipment', 'head', itemId).canAdd) {
inventory.setSlot('equipment', 'head', itemId)
}
Slot Not Found
Symptom: getSlot or setSlot throws "slot does not exist".
Cause: The slot name wasn't included in the slots array when creating the container.
Solution: Ensure all slot names are defined in the container config.
See Also
- Storage Modes - Overview of all container modes
- Slot Operations API - Reference for
setSlot,getSlot,getAllSlots,clearSlot,canEquip - Events - The
slotChangedevent fires on equipment changes