Jacob Schmidt 827f3303a2 feat: add initial Docus setup and sync tool for documentation generation
- Created package.json for Docus with necessary scripts and dependencies.
- Implemented sync-docus-docs.mjs to automate the generation of documentation files from source markdown.
- Defined mappings for generated pages and virtual routes to ensure proper linking in documentation.
- Added static content files for the documentation structure, including navigation and index pages.
2026-04-21 16:07:27 -05:00

213 lines
6.3 KiB
Markdown

# Garage Usage Guide
The garage module stores physical player vehicles. Each record keeps the
vehicle classname, generated plate UUID, fuel, overall damage, and detailed hit
point damage.
## Storage Model
Garage data is persisted through SurrealDB by the server extension.
```json
{
"plate-uuid": {
"plate": "plate-uuid",
"classname": "B_Quadbike_01_F",
"fuel": 1.0,
"damage": 0.0,
"hit_points": {
"names": ["hitengine"],
"selections": ["engine_hitpoint"],
"values": [0.0]
}
}
}
```
Rules validated by the Rust service:
- A player garage can contain up to 5 vehicles.
- `garage:add` generates a UUID plate automatically.
- `fuel`, `damage`, and every hit point value must be between `0.0` and `1.0`.
- `hit_points.names`, `hit_points.selections`, and `hit_points.values` must have
the same length.
- `garage:get`, `garage:patch`, and `garage:remove` require an existing garage.
- `garage:add` creates an empty garage automatically when one does not exist.
## Commands
All commands are called on the `garage` group.
| Command | Arguments | Returns |
| --- | --- | --- |
| `garage:create` | `uid` | Empty vehicle map as JSON. |
| `garage:get` | `uid` | Vehicle map as JSON. |
| `garage:add` | `uid`, `vehicle_json` | Updated vehicle map as JSON. |
| `garage:update` | `uid`, `vehicles_json` | Replaced vehicle map as JSON. |
| `garage:patch` | `uid`, `patch_json` | Updated vehicle map as JSON. |
| `garage:remove` | `uid`, `remove_json` | Updated vehicle map as JSON. |
| `garage:delete` | `uid` | `OK`. |
| `garage:exists` | `uid` | `true` or `false`. |
## Error Handling
Every command returns a string payload. Always check for the `Error:` prefix
before parsing JSON.
```sqf
private _result = "forge_server" callExtension ["garage:get", [getPlayerUID player]];
private _payload = _result select 0;
if (_payload find "Error:" == 0) exitWith {
systemChat format ["Garage error: %1", _payload];
};
private _garage = fromJSON _payload;
```
## Add a Vehicle
`garage:add` requires `classname`, `fuel`, `damage`, and `hit_points`.
```sqf
private _hitPointData = getAllHitPointsDamage _vehicle;
private _hitPoints = createHashMapFromArray [
["names", _hitPointData select 0],
["selections", _hitPointData select 1],
["values", _hitPointData select 2]
];
private _vehicleData = createHashMapFromArray [
["classname", typeOf _vehicle],
["fuel", fuel _vehicle],
["damage", damage _vehicle],
["hit_points", _hitPoints]
];
private _result = "forge_server" callExtension ["garage:add", [
getPlayerUID player,
toJSON _vehicleData
]];
private _payload = _result select 0;
if (_payload find "Error:" == 0) exitWith {
hint format ["Failed to store vehicle: %1", _payload];
};
private _garage = fromJSON _payload;
```
The returned value is a hash map keyed by generated plate. To find the newly
stored vehicle, compare returned keys before and after the add, or search by
classname if your workflow guarantees a unique pending vehicle.
```sqf
private _storedPlate = "";
{
private _vehicleRecord = _garage get _x;
if ((_vehicleRecord get "classname") == typeOf _vehicle) then {
_storedPlate = _x;
};
} forEach keys _garage;
```
## Patch a Vehicle
`garage:patch` updates selected fields for one plate. The `plate` field is
required. `fuel`, `damage`, and `hit_points` are optional.
```sqf
private _patch = createHashMapFromArray [
["plate", _vehicle getVariable ["forge_garage_plate", ""]],
["fuel", fuel _vehicle],
["damage", damage _vehicle]
];
private _result = "forge_server" callExtension ["garage:patch", [
getPlayerUID player,
toJSON _patch
]];
```
## Remove a Vehicle
`garage:remove` expects JSON with a `plate` field.
```sqf
private _remove = createHashMapFromArray [
["plate", _plate]
];
private _result = "forge_server" callExtension ["garage:remove", [
getPlayerUID player,
toJSON _remove
]];
```
## Spawn a Stored Vehicle
```sqf
fnc_spawnGarageVehicle = {
params ["_plate"];
private _result = "forge_server" callExtension ["garage:get", [getPlayerUID player]];
private _payload = _result select 0;
if (_payload find "Error:" == 0) exitWith {
hint format ["Failed to load garage: %1", _payload];
objNull
};
private _garage = fromJSON _payload;
private _vehicleData = _garage getOrDefault [_plate, createHashMap];
if (_vehicleData isEqualTo createHashMap) exitWith {
hint "Vehicle plate was not found in your garage.";
objNull
};
private _vehicle = (_vehicleData get "classname") createVehicle (player getPos [10, getDir player]);
_vehicle setFuel (_vehicleData getOrDefault ["fuel", 1]);
_vehicle setDamage (_vehicleData getOrDefault ["damage", 0]);
_vehicle setVariable ["forge_garage_plate", _plate, true];
private _hitPoints = _vehicleData getOrDefault ["hit_points", createHashMap];
private _names = _hitPoints getOrDefault ["names", []];
private _values = _hitPoints getOrDefault ["values", []];
{
_vehicle setHitPointDamage [_x, _values select _forEachIndex];
} forEach _names;
private _remove = createHashMapFromArray [["plate", _plate]];
"forge_server" callExtension ["garage:remove", [getPlayerUID player, toJSON _remove]];
_vehicle
};
```
## Hot State
The `garage:hot:*` commands keep a runtime copy of a player's garage and write
it back only when `garage:hot:save` runs.
| Command | Arguments | Returns |
| --- | --- | --- |
| `garage:hot:init` | `uid` | Vehicle map as JSON. |
| `garage:hot:get` | `uid` | Vehicle map as JSON. |
| `garage:hot:override` | `uid`, `vehicles_json` | Vehicle map as JSON. |
| `garage:hot:add` | `uid`, `vehicle_json` | Vehicle map as JSON. |
| `garage:hot:remove_vehicle` | `uid`, `remove_json` | Vehicle map as JSON. |
| `garage:hot:save` | `uid` | Current hot vehicle map as JSON. |
| `garage:hot:remove` | `uid` | `OK`. |
Use hot state for session-heavy vehicle workflows. Use the durable commands for
simple store/retrieve operations.
## Best Practices
- Store the generated plate on spawned vehicles with `setVariable`.
- Use `garage:patch` for frequent fuel and damage syncs.
- Use `garage:update` only when replacing the whole vehicle map intentionally.
- Do not delete the world vehicle until `garage:add` succeeds.
- Treat vehicle maps as hash maps keyed by plate, not arrays.