drs_garages

A safer lifecycle for personal, property, impound, and fleet vehicles.

Version
v2.6.0-drs.1
Updated
Aug 29, 2026
License
GPL-3.0
Resource GitHub
Browse documentationdrs_garages
Sections
01 / OVERVIEW

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.

02 / REQUIREMENTS

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
03 / INSTALLATION

Installation

  1. Back up the framework vehicle table, DRS operation tables, resource folders, and merged configuration before replacing another garage build.

  2. Stop lunar_garage, qb-garages, qbx_garages, and any other overlapping garage lifecycle before installing the exact drs_garages folder.

  3. Start oxmysql, ox_lib, the selected framework, vehicle keys, and optional target or radial provider before drs_garages; start property and shop consumers afterward.

  4. Review storage mode, automatic migration, garage identifiers, interaction providers, impounds, contracts, fleet policy, keys, and fuel integration before first use.

  5. Wait for database readiness, run drsgarages:doctor, resolve every FAIL, and complete the documented car, boat, aircraft, property, impound, restart, and fleet acceptance checks.

04 / CONFIGURATION

Configuration

01

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.

02

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.

Exampleconfig/config.lualua
Config.Storage = {
    Mode = 'global', -- global, garage, property
    DefaultGarages = {
        car = 'pillboxgarage',
        boat = 'lsymcboathouse',
        air = 'airporthangar'
    },
    RecoverUnassigned = true,
    RecoverInaccessibleProperties = true
}
03

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.

Exampleconfig/config.lualua
Config.Database = {
    AutoMigrate = true
}
04

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.

Exampleconfig/config.lualua
Config.Target = 'auto' -- ox_target, qb-target, qtarget, textui
Config.Interface.Mode = 'auto' -- auto, nui, context
Config.RadialMenu.Provider = 'auto'
05

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.

Exampleconfig/config.lualua
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.

05 / USAGE

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.

06 / DATABASE AND RECOVERY MODEL

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
01

Framework rows remain authoritative

DRS never creates, drops, replaces, or truncates player_vehicles or owned_vehicles. QB/Qbox migration adds only missing compatibility fields and DRS tables; ESX column validation remains read-only apart from an optional unique plate index.

02

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.

03

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.

07 / IMPOUNDS AND ENFORCEMENT

Impounds and enforcement

01

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.

02

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.

03

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.

08 / CONTRACTS AND MANAGED FLEETS

Contracts and managed fleets

01

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.

02

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.

03

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.

09 / TROUBLESHOOTING

Troubleshooting

Doctor reports database readiness FAIL
Checks

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
Checks

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
Checks

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
Checks

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
Checks

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
Checks

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
Checks

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.

10 / REFERENCE

Reference

01

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.

Referencelua
local canonicalId = exports.drs_garages:RegisterPropertyGarage(name, data)
exports.drs_garages:RemovePropertyGarage(canonicalId)
exports.drs_garages:RefreshPropertyGarage(canonicalId)
02

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.

Referencelua
exports.drs_garages:RegisterActiveVehicle(source, plate, netId)
exports.drs_garages:UnregisterActiveVehicle(plate, netId)
03

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.

Referencelua
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'
})
04

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.

Referencelua
local success, reason = exports.drs_garages:ImpoundVehicle(
    source,
    NetworkGetNetworkIdFromEntity(vehicle),
    'Blocking an emergency access lane',
    500
)

exports.drs_garages:OpenEnforcementImpound(vehicle, optionalDefaultFee)
05

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.

Referencetext
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.