> ## Documentation Index
> Fetch the complete documentation index at: https://mythicframework.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Inventory - Exports

> Inventory management component API for items, slots, and storage

The Inventory component manages character inventories, item storage, weights, and item operations. It's one of the most complex and frequently used components in Mythic Framework.

## Overview

Access via `Inventory` (server-side only).

<CardGroup cols={2}>
  <Card title="Slot-Based System" icon="grid">
    Grid inventory with configurable slot count
  </Card>

  <Card title="Weight Management" icon="weight-scale">
    Item weight and max capacity limits
  </Card>

  <Card title="Item Metadata" icon="tags">
    Custom data per item instance
  </Card>

  <Card title="Multiple Inventories" icon="boxes-stacked">
    Character, vehicle, stash, shop inventories
  </Card>
</CardGroup>

<Warning>
  **Server-Side Only:** All inventory operations must be performed on the server. Never attempt to modify inventory from the client.
</Warning>

***

## Inventory Management

### Items:GetCounts

Get item counts for an inventory.

```lua theme={null}
Inventory.Items:GetCounts(owner, invType)
```

<ParamField path="owner" type="number" required>
  Owner identifier (Character SID for personal inventory)
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal, other values for stashes/vehicles)
</ParamField>

<ResponseField name="counts" type="table">
  Table of item name → count pairs
</ResponseField>

**Examples:**

```lua theme={null}
-- Get all item counts for a character
local counts = Inventory.Items:GetCounts(char:GetData('SID'), 1)

for itemName, count in pairs(counts) do
    print(itemName, ':', count)
end
```

***

### Create

Create a new inventory for a character.

```lua theme={null}
Inventory:Create(characterId, maxSlots, maxWeight)
```

<ParamField path="characterId" type="number" required>
  Character SID
</ParamField>

<ParamField path="maxSlots" type="number" optional default="50">
  Maximum number of inventory slots
</ParamField>

<ParamField path="maxWeight" type="number" optional default="100">
  Maximum weight capacity
</ParamField>

**Examples:**

```lua theme={null}
-- Create default inventory
Inventory:Create(char.SID)

-- Create with custom limits
Inventory:Create(char.SID, 75, 150)

-- Create inventory on character creation
AddEventHandler('mythic-characters:server:CharacterCreated', function(source, character)
    Inventory:Create(character.SID, 50, 100)

    -- Give starter items
    Inventory:AddItem(character.SID, 'phone', 1)
    Inventory:AddItem(character.SID, 'water', 2)
end)
```

***

### Delete

Delete an inventory permanently.

```lua theme={null}
Inventory:Delete(characterId)
```

<ParamField path="characterId" type="number" required>
  Character SID
</ParamField>

**Examples:**

```lua theme={null}
-- Delete inventory
Inventory:Delete(char.SID)

-- Delete on character deletion
AddEventHandler('mythic-characters:server:CharacterDeleted', function(source, characterId)
    Inventory:Delete(characterId)
end)
```

***

## Item Operations

### AddItem

Add an item to an inventory.

```lua theme={null}
Inventory:AddItem(owner, itemName, count, metadata, invType)
```

<ParamField path="owner" type="number" required>
  Owner identifier (Character SID for personal inventory)
</ParamField>

<ParamField path="itemName" type="string" required>
  Item identifier (e.g., 'water', 'phone', 'weapon\_pistol')
</ParamField>

<ParamField path="count" type="number" optional default="1">
  Quantity to add
</ParamField>

<ParamField path="metadata" type="table" optional>
  Custom item metadata (serial number, durability, etc.)
</ParamField>

<ParamField path="invType" type="number" optional default="1">
  Inventory type (1 = personal)
</ParamField>

<ResponseField name="success" type="boolean">
  `true` if item was added successfully
</ResponseField>

<ResponseField name="slot" type="number|nil">
  Slot where item was added, or `nil` if failed
</ResponseField>

**Examples:**

```lua theme={null}
-- Add single item
local success, slot = Inventory:AddItem(char.SID, 'water', 1)

if success then
    print('Added water to slot', slot)
else
    print('Failed to add item (inventory full or no space)')
end

-- Add multiple items
Inventory:AddItem(char.SID, 'sandwich', 5)

-- Add with metadata
Inventory:AddItem(char.SID, 'weapon_pistol', 1, {
    serial = 'ABC123456',
    durability = 100,
    ammo = 12
})

-- Add to specific slot
Inventory:AddItem(char.SID, 'phone', 1, {
    number = char.Phone
}, 1)  -- Always in slot 1

-- Add item with validation
function GiveItemToPlayer(source, itemName, count)
    local player = Fetch:Source(source)

    if not player then
        return false, 'Player not found'
    end

    local char = player:GetData('Character')

    if not char then
        return false, 'No character'
    end

    -- Check if item exists
    local itemData = Items:Get(itemName)
    if not itemData then
        return false, 'Invalid item'
    end

    -- Add item
    local stateId = char:GetData('SID')
    local success, slot = Inventory:AddItem(stateId, itemName, count)

    if success then
        -- Notify player
        TriggerClientEvent('mythic-notifications:client:Send', source, {
            message = 'Received ' .. count .. 'x ' .. itemData.label,
            type = 'success'
        })

        return true, slot
    else
        TriggerClientEvent('mythic-notifications:client:Send', source, {
            message = 'Inventory full',
            type = 'error'
        })

        return false, 'Inventory full'
    end
end
```

***

### Items:Remove

Remove an item from an inventory by item name.

```lua theme={null}
Inventory.Items:Remove(owner, invType, itemName, count)
```

<ParamField path="owner" type="number" required>
  Owner identifier (Character SID for personal inventory)
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal)
</ParamField>

<ParamField path="itemName" type="string" required>
  Item identifier to remove
</ParamField>

<ParamField path="count" type="number" optional default="1">
  Quantity to remove
</ParamField>

**Examples:**

```lua theme={null}
-- Remove single item by name
Inventory.Items:Remove(char:GetData('SID'), 1, 'water', 1)

-- Remove multiple
Inventory.Items:Remove(char:GetData('SID'), 1, 'lockpick', 3)

-- Remove with validation
local stateId = char:GetData('SID')
if Inventory.Items:Has(stateId, 1, 'lockpick', 1) then
    Inventory.Items:Remove(stateId, 1, 'lockpick', 1)
    Notification:Success(source, 'Used lockpick')
else
    Notification:Error(source, 'No lockpick found')
end
```

***

### Items:Has

Check if an inventory has a specific item in sufficient quantity.

```lua theme={null}
Inventory.Items:Has(owner, invType, itemName, count)
```

<ParamField path="owner" type="number" required>
  Owner identifier (Character SID for personal inventory)
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal)
</ParamField>

<ParamField path="itemName" type="string" required>
  Item identifier
</ParamField>

<ParamField path="count" type="number" optional default="1">
  Required quantity
</ParamField>

<ResponseField name="hasItem" type="boolean">
  `true` if inventory has the item in sufficient quantity
</ResponseField>

**Examples:**

```lua theme={null}
-- Check if has item
local stateId = char:GetData('SID')

if Inventory.Items:Has(stateId, 1, 'water', 1) then
    print('Has water')
else
    print('No water')
end

-- Require item for action
function CanCraftItem(stateId, recipe)
    for _, ingredient in ipairs(recipe.ingredients) do
        if not Inventory.Items:Has(stateId, 1, ingredient.item, ingredient.count) then
            return false, 'Missing ' .. ingredient.item
        end
    end
    return true
end

-- Consume items for crafting
function CraftItem(source, recipeId)
    local player = Fetch:Source(source)
    if not player then return false end

    local char = player:GetData('Character')
    if not char then return false end

    local stateId = char:GetData('SID')
    local recipe = Recipes[recipeId]

    -- Check has ingredients
    local canCraft, error = CanCraftItem(stateId, recipe)
    if not canCraft then return false, error end

    -- Remove ingredients
    for _, ingredient in ipairs(recipe.ingredients) do
        Inventory.Items:Remove(stateId, 1, ingredient.item, ingredient.count)
    end

    -- Give crafted item
    Inventory:AddItem(stateId, recipe.result, 1)
    return true
end
```

***

### Items:GetCount

Get the count of a specific item in an inventory.

```lua theme={null}
Inventory.Items:GetCount(owner, invType, itemName)
```

<ParamField path="owner" type="number" required>
  Owner identifier
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal)
</ParamField>

<ParamField path="itemName" type="string" required>
  Item identifier
</ParamField>

<ResponseField name="count" type="number">
  Total count of the item across all slots
</ResponseField>

**Examples:**

```lua theme={null}
local stateId = char:GetData('SID')
local waterCount = Inventory.Items:GetCount(stateId, 1, 'water')
print('Has', waterCount, 'water')
```

***

### GetItemInSlot

Get the item in a specific slot.

```lua theme={null}
Inventory:GetItemInSlot(characterId, slot)
```

<ParamField path="characterId" type="number" required>
  Character SID
</ParamField>

<ParamField path="slot" type="number" required>
  Slot number
</ParamField>

<ResponseField name="item" type="table|nil">
  Item data or `nil` if slot is empty
</ResponseField>

**Examples:**

```lua theme={null}
-- Get item in slot
local item = Inventory:GetItemInSlot(char.SID, 1)

if item then
    print('Slot 1 contains:', item.label)
    print('Count:', item.count)
    print('Weight:', item.weight)
else
    print('Slot 1 is empty')
end

-- Use item callback
Callbacks:RegisterServerCallback('inventory:useItem', function(source, data, cb)
    local player = Fetch:Source(source)

    if not player then
        return cb(false, 'Player not found')
    end

    local char = player:GetData('Character')

    if not char then
        return cb(false, 'No character')
    end

    local stateId = char:GetData('SID')
    local item = Inventory:GetItemInSlot(stateId, data.slot)

    if not item then
        return cb(false, 'No item in slot')
    end

    -- Use item
    local success = Items:Use(source, item)

    cb(success)
end)
```

***

### MoveItem

Move an item from one slot to another.

```lua theme={null}
Inventory:MoveItem(characterId, fromSlot, toSlot, count)
```

<ParamField path="characterId" type="number" required>
  Character SID
</ParamField>

<ParamField path="fromSlot" type="number" required>
  Source slot
</ParamField>

<ParamField path="toSlot" type="number" required>
  Destination slot
</ParamField>

<ParamField path="count" type="number" optional>
  Amount to move (moves all if not specified)
</ParamField>

**Examples:**

```lua theme={null}
-- Move entire stack
Inventory:MoveItem(char.SID, 1, 5)

-- Move partial stack
Inventory:MoveItem(char.SID, 1, 5, 3)  -- Move 3 items from slot 1 to slot 5

-- Swap items
Inventory:MoveItem(char.SID, 1, 2)  -- Swaps items in slots 1 and 2
```

***

## Weight Management

### GetWeight

Get the current weight of an inventory.

```lua theme={null}
Inventory:GetWeight(characterId)
```

<ParamField path="characterId" type="number" required>
  Character SID
</ParamField>

<ResponseField name="currentWeight" type="number">
  Total weight of all items in inventory
</ResponseField>

**Examples:**

```lua theme={null}
-- Get current weight
local weight = Inventory:GetWeight(char.SID)

print('Current weight:', weight, 'kg')

-- Check before adding item
function CanAddItem(characterId, itemName, count)
    local currentWeight = Inventory:GetWeight(characterId)
    local itemData = Items:Get(itemName)

    local additionalWeight = itemData.weight * count

    if currentWeight + additionalWeight > inventory.maxWeight then
        return false, 'Too heavy'
    end

    -- Check slot availability
    local emptySlots = Inventory:GetEmptySlots(characterId)

    if #emptySlots == 0 and not CanStack(characterId, itemName) then
        return false, 'No empty slots'
    end

    return true
end
```

***

### GetEmptySlots

Get all empty slots in an inventory.

```lua theme={null}
Inventory:GetEmptySlots(characterId)
```

<ParamField path="characterId" type="number" required>
  Character SID
</ParamField>

<ResponseField name="emptySlots" type="table">
  Array of empty slot numbers
</ResponseField>

**Examples:**

```lua theme={null}
-- Get empty slots
local emptySlots = Inventory:GetEmptySlots(char.SID)

print('Empty slots:', #emptySlots)

for _, slot in ipairs(emptySlots) do
    print('Slot', slot, 'is empty')
end

-- Check if full
if #emptySlots == 0 then
    print('Inventory is full')
end
```

***

## Item Search

### Items:GetFirst

Get the first instance of an item in an inventory.

```lua theme={null}
Inventory.Items:GetFirst(owner, invType, itemName)
```

<ParamField path="owner" type="number" required>
  Owner identifier
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal)
</ParamField>

<ParamField path="itemName" type="string" required>
  Item identifier
</ParamField>

<ResponseField name="item" type="table|nil">
  First item instance found, or `nil` if not found
</ResponseField>

**Examples:**

```lua theme={null}
-- Find first instance of an item
local stateId = char:GetData('SID')
local item = Inventory.Items:GetFirst(stateId, 1, 'lockpick')

if item then
    print('Found lockpick')
else
    print('No lockpick found')
end
```

***

### Items:GetAll

Get all instances of an item in an inventory.

```lua theme={null}
Inventory.Items:GetAll(owner, invType, itemName)
```

<ParamField path="owner" type="number" required>
  Owner identifier
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal)
</ParamField>

<ParamField path="itemName" type="string" required>
  Item identifier
</ParamField>

<ResponseField name="items" type="table">
  Array of all item instances found
</ResponseField>

**Examples:**

```lua theme={null}
-- Find all instances of an item
local stateId = char:GetData('SID')
local items = Inventory.Items:GetAll(stateId, 1, 'water')

print('Found', #items, 'water stacks')
```

***

### Items:Use

Use an item in a specific slot.

```lua theme={null}
Inventory.Items:Use(owner, invType, slot)
```

<ParamField path="owner" type="number" required>
  Owner identifier
</ParamField>

<ParamField path="invType" type="number" required>
  Inventory type (1 = personal)
</ParamField>

<ParamField path="slot" type="number" required>
  Slot number of item to use
</ParamField>

**Examples:**

```lua theme={null}
-- Use item in slot 1
Inventory.Items:Use(char:GetData('SID'), 1, 1)
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Always Validate Before Operations" icon="shield-check">
    **❌ Bad:**

    ```lua theme={null}
    -- Assume operation succeeds
    Inventory:AddItem(char.SID, 'water', 1)
    print('Item added')  -- Maybe not!
    ```

    **✅ Good:**

    ```lua theme={null}
    local success, slot = Inventory:AddItem(char.SID, 'water', 1)

    if success then
        print('Item added to slot', slot)
        -- Notify player
        TriggerClientEvent('notify', source, 'Item added')
    else
        print('Failed to add item')
        TriggerClientEvent('notify', source, 'Inventory full')
    end
    ```
  </Accordion>

  <Accordion title="Check Weight Before Adding" icon="weight-scale">
    ```lua theme={null}
    function SafeAddItem(characterId, itemName, count)
        local canAdd, error = CanAddItem(characterId, itemName, count)

        if not canAdd then
            return false, error
        end

        return Inventory:AddItem(characterId, itemName, count)
    end
    ```
  </Accordion>

  <Accordion title="Use Metadata for Unique Items" icon="tags">
    ```lua theme={null}
    -- Weapons with serial numbers
    Inventory:AddItem(char.SID, 'weapon_pistol', 1, {
        serial = GenerateSerial(),
        durability = 100,
        ammo = 12,
        attachments = { 'flashlight', 'suppressor' }
    })

    -- Phones with numbers
    Inventory:AddItem(char.SID, 'phone', 1, {
        number = char.Phone,
        contacts = {},
        messages = {}
    })

    -- ID cards
    Inventory:AddItem(char.SID, 'id_card', 1, {
        name = char.First .. ' ' .. char.Last,
        dob = char.DOB,
        photo = 'url_to_photo'
    })
    ```
  </Accordion>

  <Accordion title="Clean Up on Character Delete" icon="broom">
    ```lua theme={null}
    AddEventHandler('mythic-characters:server:CharacterDeleted', function(source, characterId)
        Inventory:Delete(characterId)
    end)
    ```
  </Accordion>

  <Accordion title="Sync Inventory to Client" icon="arrows-rotate">
    ```lua theme={null}
    -- After inventory changes, update client
    function UpdateInventoryUI(source)
        local player = Fetch:Source(source)

        if not player then return end

        local char = player:GetData('Character')

        if not char then return end

        local stateId = char:GetData('SID')
        -- The inventory UI is automatically synced by the Inventory component
    end

    -- Call after add/remove
    local stateId = char:GetData('SID')
    Inventory:AddItem(stateId, 'water', 1)
    UpdateInventoryUI(source)
    ```
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Inventory - Events" icon="bolt" href="/api/inventory/events">
    Inventory-related events
  </Card>

  <Card title="Inventory - Item Definition" icon="tags" href="/api/inventory/item-definition">
    Item data structure and definitions
  </Card>

  <Card title="Characters API" icon="user" href="/api/characters/exports">
    Character management
  </Card>

  <Card title="Items System" icon="cube" href="/features/inventory/items">
    Using and creating items
  </Card>
</CardGroup>

<Tip>
  **Performance Tip:** Inventory operations update the database. For bulk operations (giving many items at once), consider batching updates or using transactions where possible.
</Tip>
