> For the complete documentation index, see [llms.txt](https://secret-code.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://secret-code.gitbook.io/docs/creators/secret-garage/advanced-integration.md).

# Advanced Integration

Secret Garage was designed to be integrated into different FiveM environments **without modifying the core resource**.

All public integration and customization files are located inside:

```
Secret-Garage/custom/
```

These files are included in the resource's `escrow_ignore`, which means they remain fully accessible and editable.

```
custom/
├── client_customizable.lua
├── database_customizable.lua
├── framework_customizable.lua
├── fuel_customizable.lua
├── keys_customizable.lua
├── keys_server_customizable.lua
├── server_customizable.lua
└── shared_customizable.lua
```

> **Recommended:** Whenever possible, customize Secret Garage through the `/custom` files instead of modifying the core files inside `/src`.

This makes future updates significantly easier and keeps your integration separated from the main Secret Garage codebase.

***

### Framework Integration

File:

```
custom/framework_customizable.lua
```

This file contains the main framework bridge used by Secret Garage.

By default:

```lua
Config.Framework = 'auto'
```

Secret Garage can automatically detect:

* ESX
* QBCore
* Qbox
* Standalone

The framework bridge handles functionality such as:

* Getting the current framework
* Retrieving player objects
* Player identifiers
* Jobs and grades
* Permission groups
* Money accounts
* Adding money
* Removing money
* Administrative permissions

For most servers, **no modifications are required**.

If your framework is heavily modified or you use a custom framework, this is the main file where you can adapt Secret Garage to your environment.

#### Available Bridge Functions

Some of the main functions available in this file include:

```lua
FrameworkCustom.GetFramework()
FrameworkCustom.GetFrameworkName()
FrameworkCustom.GetFrameworkObject()

FrameworkCustom.GetPlayer(source)
FrameworkCustom.GetIdentifier(source)

FrameworkCustom.GetJob(source)
FrameworkCustom.GetGroup(source)
FrameworkCustom.HasGroup(source, groups)

FrameworkCustom.GetMoney(source, account)
FrameworkCustom.RemoveMoney(source, account, amount, reason)
FrameworkCustom.AddMoney(source, account, amount, reason)
```

***

### Database Integration

File:

```
custom/database_customizable.lua
```

Secret Garage automatically selects the correct owned-vehicle database structure depending on the detected framework.

Default configuration:

```lua
SecretGarageDatabaseCustom.Mode = 'auto'
```

Available modes:

```
auto
esx
qbcore
qbox
standalone
custom
```

#### Standard Database Profiles

Secret Garage includes predefined profiles for:

* ESX
* QBCore
* Qbox
* Standalone

Each profile defines:

```lua
ownedVehiclesTable
ownerColumn
plateColumn
propertiesColumn
storedColumn
garageColumn
vehicleTypeColumn
secretDataColumn
```

For example:

```lua
esx = {
    ownedVehiclesTable = 'owned_vehicles',
    ownerColumn = 'owner',
    plateColumn = 'plate',
    propertiesColumn = 'vehicle',
    storedColumn = 'stored',
    garageColumn = 'garage',
    vehicleTypeColumn = 'type',
    secretDataColumn = 'secret_garages_data'
}
```

#### Custom Database Schema

If your server uses a completely custom vehicle table, change:

```lua
SecretGarageDatabaseCustom.Mode = 'custom'
```

Then configure:

```lua
SecretGarageDatabaseCustom.Custom = {
    ownedVehiclesTable = 'owned_vehicles',
    ownerColumn = 'owner',
    plateColumn = 'plate',
    propertiesColumn = 'vehicle',
    storedColumn = 'stored',
    garageColumn = 'garage',
    vehicleTypeColumn = 'type',
    secretDataColumn = 'secret_garages_data'
}
```

#### Column Overrides

If your framework is standard but only one or two column names are different, you do not need to create an entirely new profile.

Use:

```lua
SecretGarageDatabaseCustom.Overrides = {
    garageColumn = 'parking'
}
```

Only the specified values will override the automatically selected profile.

> Secret Garage validates the required database structure during startup. It does not automatically create or modify your vehicle tables.

***

### Fuel Integration

File:

```
custom/fuel_customizable.lua
```

Default configuration:

```lua
Config.FuelSystem = 'auto'
```

Secret Garage currently supports automatic detection for:

* `ox_fuel`
* `ps-fuel`
* `LegacyFuel`
* GTA Native Fuel

Available modes:

```
auto
ox_fuel
ps-fuel
LegacyFuel
native
custom
```

For supported resources, no additional configuration should normally be required.

#### Custom Fuel System

To integrate another fuel resource, configure:

```lua
Config.FuelSystem = 'custom'
```

Then modify:

```lua
function SecretGarageFuelCustom.GetFuel(vehicle)
    return GetVehicleFuelLevel(vehicle)
end

function SecretGarageFuelCustom.SetFuel(vehicle, fuel)
    SetVehicleFuelLevel(vehicle, fuel)
end
```

Example:

```lua
function SecretGarageFuelCustom.GetFuel(vehicle)
    return exports['my-fuel']:GetFuel(vehicle)
end

function SecretGarageFuelCustom.SetFuel(vehicle, fuel)
    exports['my-fuel']:SetFuel(vehicle, fuel)
end
```

Secret Garage will use these functions whenever vehicle fuel needs to be saved or restored.

***

### Vehicle Keys Integration

Vehicle key integration is divided into two files.

#### Client

```
custom/keys_customizable.lua
```

#### Server

```
custom/keys_server_customizable.lua
```

Default configuration:

```lua
Config.KeysSystem = 'auto'
```

Automatic detection currently supports:

* `qbx_vehiclekeys`
* `qb-vehiclekeys`
* `esx-vehiclekeys`
* Secret Garage internal keys

Available modes:

```
auto
qbx_vehiclekeys
qb-vehiclekeys
esx-vehiclekeys
internal
custom
```

Secret Garage remains authoritative over its own vehicle access permissions, while supported external key resources are synchronized when access is granted or revoked.

#### Custom Client Key System

Set:

```lua
Config.KeysSystem = 'custom'
```

Then customize:

```lua
function SecretGarageKeysCustom.GiveVehicleKeys(vehicle, plate)

end

function SecretGarageKeysCustom.HasVehicleKeys(vehicle, plate)
    return nil
end

function SecretGarageKeysCustom.RemoveVehicleKeys(vehicle, plate)

end
```

Example:

```lua
function SecretGarageKeysCustom.GiveVehicleKeys(vehicle, plate)
    exports['my-vehiclekeys']:GiveKeys(plate)
    return true
end

function SecretGarageKeysCustom.HasVehicleKeys(vehicle, plate)
    return exports['my-vehiclekeys']:HasKeys(plate)
end

function SecretGarageKeysCustom.RemoveVehicleKeys(vehicle, plate)
    exports['my-vehiclekeys']:RemoveKeys(plate)
    return true
end
```

#### Custom Server Key System

For key resources that require server-side operations, customize:

```lua
function SecretGarageKeysServerCustom.GiveVehicleKeys(source, vehicle, plate)

end

function SecretGarageKeysServerCustom.RemoveVehicleKeys(source, vehicle, plate)

end
```

This allows Secret Garage to synchronize its persistent shared-key system with external vehicle key resources.

***

### Client Customization

File:

```
custom/client_customizable.lua
```

This file contains general client-side hooks.

#### Notifications

You can completely replace the default notification system.

Default:

```lua
function SecretGarageCustom.Notify(description, notificationType)
    lib.notify({
        title = 'Secret-Garage',
        description = description,
        type = notificationType or 'inform'
    })
end
```

For example, you can redirect notifications to your own notification resource:

```lua
function SecretGarageCustom.Notify(description, notificationType)
    exports['my-notifications']:Notify(description, notificationType)
end
```

***

### UI Open / Close Hooks

Secret Garage provides hooks that are triggered when its full interface opens or closes.

```lua
function SecretGarageCustom.OnUiOpen(uiName, data)

end
```

```lua
function SecretGarageCustom.OnUiClose(uiName, data)

end
```

These are useful for hiding or restoring other UI elements such as:

* HUD
* Chat
* Phone UI
* Custom overlays
* Crosshair systems
* Other interfaces that may visually conflict

Example:

```lua
function SecretGarageCustom.OnUiOpen(uiName, data)
    exports['my-hud']:SetVisible(false)
end

function SecretGarageCustom.OnUiClose(uiName, data)
    exports['my-hud']:SetVisible(true)
end
```

***

### Vehicle Spawn Hook

Called after Secret Garage successfully spawns a vehicle.

```lua
function SecretGarageCustom.OnVehicleSpawned(vehicle, data)

end
```

This hook may be used for:

* Applying custom vehicle metadata
* Setting custom entity states
* Triggering external integrations
* Disabling radio
* Applying custom vehicle behavior
* Logging spawned vehicles

Secret Garage currently disables the GTA vehicle radio by default:

```lua
if vehicle and vehicle ~= 0 and DoesEntityExist(vehicle) then
    SetVehRadioStation(vehicle, 'OFF')
end
```

You can remove this behavior if your server prefers to preserve the radio station.

***

### Vehicle Stored Hook

Called before the local vehicle entity is removed when storing a vehicle.

```lua
function SecretGarageCustom.OnVehicleStored(vehicle, data)

end
```

This can be used to synchronize additional information before the vehicle disappears.

***

### Shared Key Hook

When a persistent Secret Garage shared key is received, the following client hook is available:

```lua
function SecretGarageCustom.OnVehicleKeyShared(vehicle, plate)

end
```

This is useful if another resource needs to react whenever Secret Garage grants shared vehicle access.

***

## Server Customization

File:

```
custom/server_customizable.lua
```

This file provides server-side hooks that can be used to connect Secret Garage with other systems.

***

### Custom Garage Access

```lua
function SecretGarageServerCustom.CanUseGarage(source, garage)
    return true
end
```

This function allows you to apply additional custom conditions before a player can use a garage.

Returning:

```lua
true
```

allows access.

Returning:

```lua
false
```

denies access.

Example:

```lua
function SecretGarageServerCustom.CanUseGarage(source, garage)
    if exports['my-system']:IsPlayerBlocked(source) then
        return false
    end

    return true
end
```

This can be used for integrations such as:

* Duty systems
* Player states
* Organizations
* Custom memberships
* VIP systems
* Server-specific restrictions

***

### Server Vehicle Spawn Hook

```lua
function SecretGarageServerCustom.OnVehicleSpawned(source, entity, data)

end
```

Triggered after a tracked vehicle is spawned.

This can be used for:

* Server logging
* Entity state bags
* External ownership systems
* Anticheat integration
* Custom tracking systems

***

### Server Vehicle Stored Hook

```lua
function SecretGarageServerCustom.OnVehicleStored(source, data)

end
```

Triggered when Secret Garage stores a vehicle.

***

### Rental Created Hook

```lua
function SecretGarageServerCustom.OnRentalCreated(source, rental)

end
```

Triggered whenever a new Secret Garage rental is created.

Possible integrations include:

* Logging
* Billing systems
* External rental tracking
* Analytics
* Discord logs

***

### Vehicle Destroyed Hook

```lua
function SecretGarageServerCustom.OnVehicleDestroyed(plate, data)

end
```

Called when Secret Garage detects that one of its tracked vehicles has been destroyed.

At this point, Secret Garage has already removed the vehicle from live tracking and will continue with the configured recovery / impound behavior.

This hook can be used for:

* Insurance systems
* Logging
* Vehicle damage systems
* Police integrations
* Custom impound logic
* Analytics

***

### Offline Player Name Resolver

```lua
function SecretGarageServerCustom.ResolveIdentifierName(identifier)
    return nil
end
```

This hook is primarily used by systems such as Photo Room when Secret Garage needs to display a player name from an identifier that does not currently belong to an online player.

Example:

```lua
function SecretGarageServerCustom.ResolveIdentifierName(identifier)
    return exports['my-identity']:GetPlayerName(identifier)
end
```

Online players are automatically resolved before this hook is used.

***

## Vehicle Label Integration

File:

```
custom/shared_customizable.lua
```

Secret Garage includes a shared hook for custom vehicle labels:

```lua
function SecretGarageSharedCustom.ResolveVehicleLabel(model, fallback)
    return fallback or tostring(model)
end
```

This can be useful when your server uses a custom vehicle catalog or custom label system.

Example:

```lua
function SecretGarageSharedCustom.ResolveVehicleLabel(model, fallback)
    local customLabel = exports['my-vehicles']:GetVehicleLabel(model)

    if customLabel then
        return customLabel
    end

    return fallback or tostring(model)
end
```

This allows custom vehicle names to be integrated without modifying Secret Garage's vehicle handling code.

***

## Recommended Structure

For a standard installation, we recommend leaving most integrations configured as:

```lua
Config.Framework = 'auto'
Config.FuelSystem = 'auto'
Config.KeysSystem = 'auto'

SecretGarageDatabaseCustom.Mode = 'auto'
```

Only modify the `/custom` files when your server requires behavior that is different from the supported defaults.

A typical custom server setup may only need something like:

```
custom/
├── client_customizable.lua       ← Notifications / HUD integration
├── framework_customizable.lua    ← Custom framework behavior
├── database_customizable.lua     ← Custom vehicle database schema
├── fuel_customizable.lua         ← Custom fuel system
├── keys_customizable.lua         ← Client key integration
├── keys_server_customizable.lua  ← Server key integration
├── server_customizable.lua       ← Server hooks / permissions
└── shared_customizable.lua       ← Vehicle labels
```

> **Important:** Keep your changes inside `/custom` whenever possible. This provides the cleanest integration path and helps prevent custom modifications from being overwritten during future Secret Garage updates.
