# Locker System Integration Guide

## Overview

The locker system provides persistent item storage for Arma 3 players. Each player can store multiple items (weapons, magazines, equipment) with quantity tracking.

## Data Storage

- Each player's locker is persisted by the server extension through SurrealDB.
- The map is keyed by the item's **classname** (String)
- Each item tracks: `category`, `classname`, and `amount`
- **Maximum Capacity**: 25 unique items per locker
- **Empty lockers are auto-created** when a player first fetches their locker if it doesn't exist

## Extension Commands

All commands are accessed via the `locker` group:

### Create Locker

Creates a new empty locker for a player. Should be called when initializing a new player if one doesn't exist.

```sqf
private _result = "forge_server" callExtension ["locker:create", [getPlayerUID player]];
// Returns: {} (empty map) or Error message
```

### Get Locker

Retrieves all items in a player's locker.

```sqf
private _result = "forge_server" callExtension ["locker:get", [getPlayerUID player]];
private _lockerMap = fromJSON (_result select 0);
// Returns: {"arifle_MX_F": {"classname":"arifle_MX_F","category":"Weapon","amount":1}, ...}
```

### Add Item

Adds a new item to the locker or updates the amount if it already exists.
**Checks capacity limit (25 items).**

```sqf
private _data = createHashMapFromArray [
    ["classname", "arifle_MX_F"],
    ["category", "Weapon"],
    ["amount", 1]
];

private _result = "forge_server" callExtension ["locker:add", [
    getPlayerUID player,
    toJSON _data
]];

private _updatedLocker = fromJSON (_result select 0);
// Returns updated locker map
```

### Update Locker (Sync)

Updates the entire locker state. Useful for syncing changes made locally (e.g., bulk moves).
**Replaces the entire locker content.**

```sqf
// _lockerMap is the local HashMap of items
private _result = "forge_server" callExtension ["locker:update", [
    getPlayerUID player,
    toJSON _lockerMap
]];

private _updatedLocker = fromJSON (_result select 0);
```

### Patch Item

Updates specific fields (currently `amount`) of an existing item without sending the entire locker.
**Efficient for quantity changes.**

```sqf
private _classname = "arifle_MX_F";
private _data = createHashMapFromArray [
    ["classname", _classname],
    ["amount", 5] // New amount
];

private _result = "forge_server" callExtension ["locker:patch", [
    getPlayerUID player,
    toJSON _data
]];

private _updatedLocker = fromJSON (_result select 0);
```

### Remove Item

Removes a specific item from the locker by classname.

```sqf
private _classname = "arifle_MX_F";
private _data = createHashMapFromArray [
    ["classname", _classname]
];

private _result = "forge_server" callExtension ["locker:remove", [
    getPlayerUID player,
    toJSON _data
]];

private _updatedLocker = fromJSON (_result select 0);
```

### Delete Locker

Permanently deletes all items from a player's locker.

```sqf
private _result = "forge_server" callExtension ["locker:delete", [getPlayerUID player]];
// Returns: "OK" or "Error: ..."
```

### Check Existence

Checks if a player has a locker created.

```sqf
private _result = "forge_server" callExtension ["locker:exists", [getPlayerUID player]];
private _exists = (_result select 0) == "true";
```

## Complete Integration Example

### Storing an Item

```sqf
fnc_storeCurrentWeapon = {
    private _weapon = currentWeapon player;
    if (_weapon == "") exitWith { hint "No weapon in hand!"; };

    // Create item data
    private _data = createHashMapFromArray [
        ["classname", _weapon],
        ["category", "Weapon"],
        ["amount", 1]
    ];

    // Add to locker
    private _result = "forge_server" callExtension ["locker:add", [
        getPlayerUID player,
        toJSON _data
    ]];

    // Check for error (e.g., full locker)
    if ((_result select 0) find "Error:" == 0) exitWith {
        hint format ["Failed to store item: %1", _result select 0];
        false
    };

    // Remove weapon from player
    player removeWeapon _weapon;
    hint format ["Stored %1 in locker!", _weapon];
    true
};
```

### Retrieving an Item

```sqf
fnc_retrieveItem = {
    params ["_classname"];

    // Get locker
    private _result = "forge_server" callExtension ["locker:get", [getPlayerUID player]];
    private _locker = fromJSON (_result select 0);

    // Check if item exists
    private _item = _locker getOrDefault [_classname, locationNull];
    if (_item isEqualTo locationNull) exitWith {
        hint "Item not found in locker!";
        false
    };

    // Get amount
    private _amount = _item get "amount";
    if (_amount <= 0) exitWith {
        // Should not happen, but safe to handle
        hint "Item out of stock!";
        false
    };

    // Add to player
    if (player canAdd _classname) then {
        player addItem _classname;

        // Decrement amount or remove if 0
        if (_amount > 1) then {
             private _patchData = createHashMapFromArray [
                ["classname", _classname],
                ["amount", _amount - 1]
            ];
            "forge_server" callExtension ["locker:patch", [getPlayerUID player, toJSON _patchData]];
        } else {
             private _removeData = createHashMapFromArray [
                ["classname", _classname]
            ];
            "forge_server" callExtension ["locker:remove", [getPlayerUID player, toJSON _removeData]];
        };

        hint format ["Retrieved %1 from locker!", _classname];
        true
    } else {
        hint "Not enough space in inventory!";
        false
    };
};
```

## Error Handling

All commands return errors in the format `"Error: <message>"`.

```sqf
private _result = "forge_server" callExtension ["locker:add", ...];
private _data = _result select 0;

if (_data find "Error:" == 0) then {
    systemChat format ["Locker error: %1", _data];
};
```
