forge/docs/LOCKER_USAGE_GUIDE.md
Jacob Schmidt ebfe77a340 feat: implement complete Forge framework with Rust/Redis backend and Arma 3 integration
Implemented features:
- High-performance Rust extension with Redis persistence
- Actor/player management with loadout, position, and state tracking
- Banking system with deposit, withdraw, and transfer operations
- Physical and virtual garage/locker systems for vehicle and equipment storage
- Organization management with member tracking and permissions
- Client-side UI with React-like state management
- Server-side event-driven architecture with CBA Events
- Security: Self-transfer prevention at multiple layers
- Logging system with per-module log files
- ICOM module for inter-server communication

Co-Authored-By: Warp <agent@warp.dev>
2026-01-04 12:52:15 -06:00

219 lines
5.8 KiB
Markdown

# 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 stored as a single JSON object (map) at Redis key: `locker:{playerUID}`
- 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];
};
```