6.3 KiB
title, description
| title | description |
|---|---|
| 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.
{
"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:addgenerates a UUID plate automatically.fuel,damage, and every hit point value must be between0.0and1.0.hit_points.names,hit_points.selections, andhit_points.valuesmust have the same length.garage:get,garage:patch, andgarage:removerequire an existing garage.garage:addcreates 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.
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.
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.
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.
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.
private _remove = createHashMapFromArray [
["plate", _plate]
];
private _result = "forge_server" callExtension ["garage:remove", [
getPlayerUID player,
toJSON _remove
]];
Spawn a Stored Vehicle
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:patchfor frequent fuel and damage syncs. - Use
garage:updateonly when replacing the whole vehicle map intentionally. - Do not delete the world vehicle until
garage:addsucceeds. - Treat vehicle maps as hash maps keyed by plate, not arrays.