Overview
drs_garages 2.6.0-drs.1 is a DRS-namespaced vehicle lifecycle for Qbox, QB-Core, and ESX. It provides car, boat, and aircraft storage; compact NUI and context interfaces; target, TextUI, radial, and keybind access; protected parking and impounds; property registration; Contract V2; managed job fleets; and integration exports behind database readiness and server validation.
Requirements
- Required
- ox_lib, oxmysql, and OneSync
- Framework
- Exactly one of qbx_core, qb-core, or es_extended
- Interaction
- Optional ox_target, qb-target, or qtarget; TextUI fallback
- Keys
- qbx_vehiclekeys, qb-vehiclekeys, or a custom ESX hook when enabled
- Resource name
- Must remain drs_garages
Installation
Back up the framework vehicle table, DRS operation tables, resource folders, and merged configuration before replacing another garage build.
Stop lunar_garage, qb-garages, qbx_garages, and any other overlapping garage lifecycle before installing the exact drs_garages folder.
Start oxmysql, ox_lib, the selected framework, vehicle keys, and optional target or radial provider before drs_garages; start property and shop consumers afterward.
Review storage mode, automatic migration, garage identifiers, interaction providers, impounds, contracts, fleet policy, keys, and fuel integration before first use.
Wait for database readiness, run drsgarages:doctor, resolve every FAIL, and complete the documented car, boat, aircraft, property, impound, restart, and fleet acceptance checks.
Configuration
Keep the exact runtime identity
Install the manifest directly inside a folder named drs_garages. Run exactly one supported core: qbx_core, qb-core, or es_extended. Companion resources call exports.drs_garages and new integrations should use only the drs_garages:* namespace.
Select the storage contract
Global keeps one type-wide pool across accessible public and property garages. Garage enforces the saved public or property assignment. Property keeps public garages shared while isolating vehicles assigned to an active property. Recovery options expose unknown, deleted, or inaccessible assignments virtually instead of rewriting every row at startup.
Config.Storage = {
Mode = 'global', -- global, garage, property
DefaultGarages = {
car = 'pillboxgarage',
boat = 'lsymcboathouse',
air = 'airporthangar'
},
RecoverUnassigned = true,
RecoverInaccessibleProperties = true
}Choose migration or read-only validation
With AutoMigrate enabled, QB/Qbox startup adds only missing job, type, stored, and state compatibility fields and validates the DRS tables and indexes. At least one stored/state source must already exist. Duplicate or invalid normalized plates stop readiness; DRS never merges or deletes owned rows. Disable AutoMigrate only when every required schema object was installed manually.
Config.Database = {
AutoMigrate = true
}Choose interface and interaction providers
Target auto-detection prefers ox_target, then qb-target, then qtarget; otherwise DRS uses ox_lib TextUI. Radial auto-detection prefers qbx_radialmenu, then qb-radialmenu, then ox_lib. Provider selection happens at DRS startup, so restart drs_garages after switching providers. Interface auto mode uses the NUI after its readiness handshake and otherwise falls back to context menus.
Config.Target = 'auto' -- ox_target, qb-target, qtarget, textui
Config.Interface.Mode = 'auto' -- auto, nui, context
Config.RadialMenu.Provider = 'auto'Tune protected parking
Every parking path shares a cancellable progress operation. The client watches speed, occupants, vehicle identity, location, job or property access, and network identity; the server independently repeats stationary, proximity, type, ownership, and storage-state validation before committing the exact database row and deleting the entity.
Config.Parking = {
ProgressDuration = 5000,
ProgressCanCancel = true,
MaximumSpeed = 0.5,
TargetEnabled = true,
TargetDistance = 3.0
}06Configure enforcement impounds
Enable the authorized job action, reason and fee limits, tow delay, owned-vehicle release behavior, and optional natural-traffic removal deliberately. The action has no TextUI equivalent and requires a supported target provider. Mission, script, managed, occupied, moving, unauthorized, or mismatched vehicles fail closed.
07Keep Contract V2 conservative
The supplied safe policy enables boss-authorized personal-to-society donations only. Player sales and society withdrawals are separate opt-ins. Install the configured contract item manually, keep administrator actions behind ACE, and resolve ambiguous journal rows only after verifying inventory, money, keys, and ownership.
08Configure managed job fleets
Give each participating public job garage a stable ID and exact job allowlist. Configure boss and ACE permissions, trusted resources, allowed models, minimum grades, society banking, and the drs_vehicleshop fleet catalog. Managed assets always honor their assigned garage even when ordinary storage is global.
09Review framework-specific boundaries
Qbox needs qbx_vehicles for fleet issuance and qbx_vehiclekeys for normal key handoff. QB can use qb-vehiclekeys, but that provider cannot safely reset offline plate keys, so ownership-domain contract registration is blocked. Stock ESX supports only global storage and requires keys disabled or a custom SetVehicleOwner hook.
Usage and validation
Complete first-start diagnostics
Wait for schema readiness, run drsgarages:doctor from the server console, and resolve every FAIL. Review intentional WARN entries for target, radial, keys, banking, companions, locations, contract item, fleet service, and unresolved operations before opening the server.
Verify car, boat, and aircraft storage
Retrieve, park, restart, locate, and impound at least one vehicle of every enabled type. Confirm spawn checks, keys, fuel, locked presentation, stored/state values, active tracking, and type separation remain correct.
Exercise every access path
Use an attendant or TextUI point, the E interaction, the G parking key, nearby radial access, and empty-vehicle target parking where configured. Cancel one progress operation, then confirm movement, a new occupant, leaving the area, or losing access cancels safely.
Verify property and housing access
Test property listing, interior entry, parking, and retrieval as owner, keyholder, and unauthorized player. Remove a key or end a rental and confirm access and recovery follow the selected storage policy. Restart each companion once and confirm the current public qbx_properties build restores its DRS registrations.
Verify enforcement recovery
As an authorized on-duty job, enter a bounded reason and fee for an empty owned vehicle, confirm the delayed tow and audit fields, then recover it from a clear impound point without being placed in the seat. Confirm unauthorized jobs and legacy authority holds remain protected.
Verify contracts and managed fleets
Donate a personal vehicle as a boss, enforce a minimum grade, move and retrieve the managed asset, and retire only a disposable test vehicle. Separately test ACE issuance and one paid Qbox society purchase; each should produce exactly one intended debit, shop order, fleet operation, and stored vehicle.
Database and recovery model
- QB/Qbox table
- Existing player_vehicles
- ESX table
- Existing owned_vehicles
- Plate policy
- Trimmed 1–8 characters · full-column UNIQUE index
- DRS records
- Impound, contract, fleet metadata, and operation journals
Ambiguity stops instead of guessing
At least one authoritative stored or state field must preexist. Duplicate normalized plates, invalid plate values, incompatible indexes, nontransactional tables, conflicting cores, and unresolved schema requirements keep database-backed actions unavailable.
Recovery records preserve uncertainty
Impound, contract, and fleet journals support restart reconciliation and explicit review. Offline repair SQL is never automatic; stop the server, preserve a backup, and inspect every affected row before applying it.
Impounds and enforcement
Owned-vehicle impounds
The server repeats job, duty, grade, distance, occupancy, identity, ownership, state, fee, and reason checks before committing the framework row and namespaced DRS record together. Recovery uses the ordinary spawn and key presentation and removes the active record only after success.
Natural traffic removal
When explicitly enabled, an authorized job can schedule an empty natural GTA vehicle for delayed removal without creating framework ownership, garage, DRS impound, or MDT records. Managed, persistent, mission, and script vehicles are rejected.
Legacy police holds remain distinct
DRS-recorded release fees take precedence. Compatible Qbox/QB depot pricing can remain payable, while state-2 vehicles without a DRS release record stay authority holds by default instead of becoming ordinary paid recovery rows.
Contracts and managed fleets
Contract V2
Personal sales, boss society donations, and society withdrawals have independent policy gates. Signing remains cancellable, exact eligibility is revalidated before mutation, and every transfer enters the contract journal for restart recovery or administrator review.
Fleet Manager
Configured job bosses can donate personal vehicles, assign a compatible garage, set a minimum grade, move stored assets, and retire them with an audit reason. ACE administrators can manage another job and issue only server-allowlisted models.
Society purchasing
Qbox bosses can purchase shop-allowlisted models through the current drs_vehicleshop catalog. The shop and garage maintain independent request and recovery journals; uncertain banking or creation outcomes stop for review instead of replaying a debit or vehicle grant.
Troubleshooting
Doctor reports database readiness FAIL
Check the exact resource and framework name, existing vehicle table, required model and ownership fields, stored/state source, table engine, full-column plate index, normalized duplicates, invalid plates, DRS journal schemas, and runtime schema privileges. Back up and correct the reported issue instead of bypassing the gate.
A vehicle is missing or appears in the wrong garage
Verify its trusted vehicle type, stored/state value, canonical garage assignment, active entity, current storage mode, property access, job and grade, and configured type fallback. Recovery is virtual until the vehicle is parked again; DRS does not bulk-rewrite legacy assignments.
Qbox startup reports a persistence conflict
Disable Qbox full vehicle persistence or set qbx:vehiclePersistenceType semi, then perform the first combined deployment through a full server restart. Do not let two resources own restart/world-spawn reconciliation.
Target, radial, or TextUI behavior is unexpected
Set the desired provider explicitly or start it before drs_garages. Restart DRS after adding, removing, or switching providers. TextUI is a valid location fallback, but enforcement vehicle targeting specifically requires a supported target resource.
A property garage does not register
Confirm the current qbx_properties build starts after drs_garages, both folders use their exact runtime names, and the row has an owner plus valid entry and spawn coordinates. Review both resource logs for schema or registration failures, then confirm the property bridge sends its stable property_qbx ID, owner, and current keyholders.
Contract registration is blocked on QB-Core
Stock qb-vehiclekeys cannot safely reset global or offline plate keys, so DRS blocks ownership-domain contracts with that combination. Disable the DRS key integration or use a compatible key resource before enabling transfers.
A society purchase or fleet operation needs review
Inspect the matching drs_vehicleshop order, DRS fleet operation, society-bank transaction, framework vehicle row, plate, actor, and timestamp. Renewed-Banking reports only best-effort asynchronous persistence; use the Doctor warning and never replay an uncertain debit or creation blindly.
Reference
Property registration exports
Register a stable property garage, then remove or refresh the same canonical id when ownership, keys, coordinates, or resource lifecycle changes. DRS revalidates the current owner and keyholder list before each protected action.
local canonicalId = exports.drs_garages:RegisterPropertyGarage(name, data)
exports.drs_garages:RemovePropertyGarage(canonicalId)
exports.drs_garages:RefreshPropertyGarage(canonicalId)Server-created vehicle tracking
Companion resources such as drs_vehicleshop register a server-created delivery entity after exact plate and network identity are known, then unregister that mapping when the tracked entity is no longer active.
exports.drs_garages:RegisterActiveVehicle(source, plate, netId)
exports.drs_garages:UnregisterActiveVehicle(plate, netId)Trusted job-fleet creation
Only a resource listed in Config.JobFleet.TrustedResources may request a fleet vehicle. DRS still validates the connected actor, boss or ACE authority, job, garage, model allowlists, stable request fingerprint, and final database row.
local result = exports.drs_garages:CreateJobFleetVehicle({
requestId = durableRequestId,
actorSource = source,
action = 'society_purchase',
job = 'police',
model = 'police3',
garageIndex = configuredGarageIndex,
minGrade = 0,
reason = 'Optional audit note'
})Enforcement impound exports
The server export schedules the protected action for the connected authorized player and returns success plus a stable reason. The client export only opens the same DRS dialog; all permission, entity, ownership, location, and database checks remain server-side.
local success, reason = exports.drs_garages:ImpoundVehicle(
source,
NetworkGetNetworkIdFromEntity(vehicle),
'Blocking an emergency access lane',
500
)
exports.drs_garages:OpenEnforcementImpound(vehicle, optionalDefaultFee)Administrative commands
Use the restricted commands to inspect deployment health and unresolved journal work. Never resolve an operation until its framework row, money, keys, external service, and audit history prove the real outcome.
drsgarages:doctor
drsgarages:contracts
drsgarages:contractresolve <operation_id> <completed|compensated|cancelled>
drsgarages:fleetops [plate]
drsgarages:fleetresolve <operationId> <committed|failed> <reason>- The exact resource folder and runtime name is drs_garages. New integrations should use its DRS namespace and documented exports rather than legacy Lunar events or callbacks.
- The public main branch reports version 2.6.0-drs.1 but currently has no GitHub tag or packaged Release. Pin the tested commit deployed to your server.
- The GPL-3.0 repository is a modified Lunar Scripts lunar_garage 2.0.3 rework and retains upstream attribution in NOTICE.md.
- The optional repair_qbox_vehicle_storage_state.sql changes stored vehicle state and must be reviewed offline with the FiveM server and every persistence resource stopped.
- Internal drs_garages network events and callbacks are implementation details. Treat only the documented property, active-vehicle, fleet-creation, and enforcement exports as the public integration surface.