Administrator Guide
This guide covers server-side configuration, framework integration, audio backend management, and common administrative tasks for ARS CarPlay.
Configuration Management
Section titled “Configuration Management”All admin-configurable settings live in config.lua (escrow-ignored, buyer-editable). The file loads first in the manifest so framework auto-detection runs before the guarded framework files.
Framework Selection
Section titled “Framework Selection”Config.Framework = 'auto' -- 'auto' | 'qb' | 'qbx' | 'esx'auto(default): Detects at startup —qbx_core→qb-core→es_extended.- Pin explicitly if you run multiple frameworks or want deterministic behavior.
Enable/Disable Apps
Section titled “Enable/Disable Apps”Config.CarPlay.apps = { home = true, music = true, navigation = true, vehicle = true, radio = true, phone = true, messages = true, settings = true,}Set any app to false to hide it from the dock entirely. Disabled apps cannot be opened by players.
Vehicle Restrictions
Section titled “Vehicle Restrictions”Config.CarPlay.disabledVehicleClasses = { 8, 13, 14, 15, 16 }GTA vehicle class IDs to block CarPlay:
| Class ID | Category |
|---|---|
| 8 | Motorcycles |
| 13 | Cycles (bicycles) |
| 14 | Boats |
| 15 | Helicopters |
| 16 | Planes |
Add/remove IDs to customize. Class 0 (compacts) through 12 (industrial) are allowed by default.
Persistence Scope
Section titled “Persistence Scope”Config.CarPlay.settingsScope = 'plate' -- 'plate' | 'player'| Scope | Behavior |
|---|---|
plate (default) |
Per-vehicle. Owned cars persist to localStorage (durable). NPC cars = memory only. |
player |
Per-character (citizenid/license). One profile follows the player. Always persists. |
Ownership Gating (Plate Scope Only)
Section titled “Ownership Gating (Plate Scope Only)”Config.CarPlay.ownership = { enabled = true, tableName = nil, -- nil = auto: 'player_vehicles' (QB/QBX) or 'owned_vehicles' (ESX) plateColumn = 'plate', fallbackOwned = true, -- true = assume owned when DB unavailable}enabled = false→ skip ownership check, persist everything.fallbackOwned = true(default) prevents players losing settings on misconfigured servers (oxmysql not started).
Audio Backend (xsound)
Section titled “Audio Backend (xsound)”xsound is a hard dependency (listed in fxmanifest.lua). The Music and Internet Radio apps will not produce audio if xsound is not started.
Load Order (Critical)
Section titled “Load Order (Critical)”ensure ox_libensure xsoundensure ars_carplayxsound must start before ars_carplay. If order is wrong, the UI opens but audio commands fail silently (returns { ok = false, reason = 'xsound not started' }).
Positional Audio Behavior
Section titled “Positional Audio Behavior”- Positional (default):
PlayUrlPoswithsource = -1(broadcast to all clients). Each client’s 3D audio engine renders proximity from the vehicle. Passengers and nearby players hear it. - Non-positional:
PlayUrlwithsource = player. Only the triggering player hears it (2D). - Controlled per-app:
Config.Music.positional,Config.Radio.positional. - Distance falloff:
Config.Music.audibleDistance(default 5.0),Config.Radio.audibleDistance(default 12.0) GTA units.
YouTube Support
Section titled “YouTube Support”xsound resolves YouTube links via its internal IFrame API. No extra setup required — just paste a YouTube URL in the Music app.
Framework Integration
Section titled “Framework Integration”ARS CarPlay supports three frameworks behind a unified Bridge global. The correct framework file is loaded via fxmanifest.lua globs with a self-guard (if Config.Framework ~= '...' then return end).
Supported Frameworks
Section titled “Supported Frameworks”| Config Value | Resource Name | Export Used |
|---|---|---|
qb |
qb-core |
exports['qb-core']:GetCoreObject() |
qbx |
qbx_core |
exports.qbx_core (server: GetPlayer(src), client: GetPlayerData()) |
esx |
es_extended |
exports['es_extended']:getSharedObject() |
Bridge API (Internal — Do Not Depend On Directly)
Section titled “Bridge API (Internal — Do Not Depend On Directly)”The Bridge table provides identical method names across all frameworks:
Client:
Bridge.GetPlayer()→ player data tableBridge.GetIdentifier()→ citizenid / identifierBridge.GetMoney(type)→ cash/bankBridge.GetJob()→{ name, label, grade }Bridge.GetName()→ full name string
Server:
Bridge.GetPlayer(src)→ player objectBridge.GetIdentifier(src)→ citizenid / identifierBridge.GetMoney(src, type)→ amountBridge.AddMoney(src, type, amount)→ booleanBridge.RemoveMoney(src, type, amount)→ booleanBridge.GetJob(src)→{ name, label, grade }Bridge.GetName(src)→ full name stringBridge.IsVehicleOwned(src, plate)→ boolean (soft oxmysql query)
Note: Other resources should use their framework’s native exports, not
Bridge.
Fuel System Compatibility
Section titled “Fuel System Compatibility”The Vehicle app’s fuel gauge auto-detects the running fuel system. Supported out of the box:
| System | Method | Scale |
|---|---|---|
ox_fuel |
Entity(veh).state.fuel |
0–100 (state bag) |
cdn-fuel |
exports['cdn-fuel']:GetFuel(veh) |
0–100 |
ps-fuel |
exports['ps-fuel']:GetFuel(veh) |
0–100 |
LegacyFuel |
exports['LegacyFuel']:GetFuel(veh) |
0–100 |
qb-fuel |
exports['qb-fuel']:GetFuel(veh) |
0–100 |
qb-sna-fuel |
exports['qb-sna-fuel']:GetFuel(veh) |
0–100 (decor = liters!) |
lj-fuel |
exports['lj-fuel']:GetFuel(veh) |
0–100 |
lc_fuel |
exports['lc_fuel']:GetFuel(veh) |
0–100 |
LNS_Fuel |
exports['LNS_Fuel']:GetFuel(veh) |
0–100 |
okokGasStation |
exports['okokGasStation']:GetFuel(veh) |
0–100 |
frfuel |
exports['frfuel']:getCurrentFuelLevel() |
Liters → normalized % |
Configuring Fuel Source
Section titled “Configuring Fuel Source”Config.Vehicle.fuelSource = 'auto' -- 'auto' | 'native' | '<key>' | 'custom'Config.Vehicle.fuelExport = nil -- { resource = '...', method = '...' } when 'custom'auto(default): Probes in priority order above. First running match wins.native: ForceGetVehicleFuelLevel(GTA native). Ignores all fuel resources.'<key>': Pin a specific system (e.g.,'ox_fuel').custom: UsefuelExportfor unsupported systems. Export receives vehicle entity, must return 0–100.
Tip:
client/utils.luais escrow-ignored — add custom fuel systems to theFUEL_SYSTEMStable there.
Radio Browser API
Section titled “Radio Browser API”Internet radio browsing uses the community Radio Browser API (api.radio-browser.info).
Configuration
Section titled “Configuration”Config.Radio.browser = { enabled = true, server = 'https://de1.api.radio-browser.info', -- Single mirror (DNS round-robin is flaky) cacheSeconds = 300, -- Server-side cache TTL limit = 40, -- Max stations per fetch categories = { 'rock', 'pop', 'jazz', 'electronic', 'classical', 'news' },}enabled = false→ only curatedConfig.Radio.stationsshow (no API calls).server: Pinned mirror for reliability. Change if EU mirror has issues.categories: Radio Browser tags passed tobytagexact/<tag>. Add/remove to change browse tabs.
Curated Stations (Offline-Friendly)
Section titled “Curated Stations (Offline-Friendly)”Config.Radio.stations = { { name = 'SomaFM Groove Salad', url = 'https://ice1.somafm.com/groovesalad-128-mp3', genre = 'Ambient / Chill', bitrate = 128 }, -- ... more entries}- Always available, no API needed.
- URL must be a direct stream (
.mp3,.aac,.m3u8), not a playlist page. - Edit freely in
config.lua(escrow-ignored).
Localization
Section titled “Localization”Player-facing strings in locales/*.json (flat keys, %s placeholders only).
Adding a Language
Section titled “Adding a Language”- Create
locales/<locale>.json(e.g.,fr.json,de.json,es.json). - Copy
locales/en.jsonas a base. - Translate values — keep keys identical.
- ox_lib auto-detects player locale.
Key Format
Section titled “Key Format”{ "menu_opened": "CarPlay opened", "must_be_driver": "You must be in the driver seat to use CarPlay", "music_add_failed": "Couldn't add — check the link"}- Flat keys only (no nesting).
%splaceholders only (no%d,%f, etc.).lib.locale()called once inconfig.lua. Do not call again.
Common Administrative Tasks
Section titled “Common Administrative Tasks”Change Default Keybind
Section titled “Change Default Keybind”Config.UI = { openCommand = 'carplay', openDescription = 'Open CarPlay', defaultKey = 'F7', -- Change here}Players can still rebind in GTA settings.
Disable Music App Entirely
Section titled “Disable Music App Entirely”Config.CarPlay.apps.music = falseRemoves from dock, NUI never loads the module.
Restrict to Owned Vehicles Only
Section titled “Restrict to Owned Vehicles Only”Config.CarPlay.ownership.enabled = trueConfig.CarPlay.ownership.fallbackOwned = false -- Strict: NPC cars never persistRequires oxmysql started for ownership checks to work.
Switch to Player-Scope Persistence
Section titled “Switch to Player-Scope Persistence”Config.CarPlay.settingsScope = 'player'One settings profile per character. No ownership checks needed. Always persists.
Add Custom POI Categories (Navigation)
Section titled “Add Custom POI Categories (Navigation)”Config.Navigation.categories = { fuel = { blips = { 361 } }, hospital = { blips = { 153 } }, ammo = { blips = { 110 } }, police = { blips = { 60, 137 } }, mechanic = { blips = { 446, 72 } }, -- Add custom: my_poi = { blips = { 123, 456 } }, -- Your server's blip sprites}Blip sprite IDs from the GTA blip reference. Scan radius = Config.Navigation.scanRadius (default 4000).
Troubleshooting (Admin-Side)
Section titled “Troubleshooting (Admin-Side)”“No framework detected” in Console
Section titled ““No framework detected” in Console”^1[ars_carplay] No framework detected. Set Config.Framework manually in config.lua.^7Fix: Set Config.Framework = 'qb' | 'qbx' | 'esx' explicitly.
Music/Radio UI Opens But No Audio
Section titled “Music/Radio UI Opens But No Audio”Check: xsound resource state in resmon — must be started before ars_carplay.
Fix: Reorder server.cfg:
ensure ox_libensure xsoundensure ars_carplayFuel Gauge Reads 0% or Wrong Value
Section titled “Fuel Gauge Reads 0% or Wrong Value”Cause: Fuel system not detected or misconfigured. Fixes:
- Set
Config.Vehicle.fuelSource = 'native'to force GTA native. - Pin your system:
Config.Vehicle.fuelSource = 'ox_fuel'. - Add custom export in
Config.Vehicle.fuelExport.
Settings Don’t Persist After Restart
Section titled “Settings Don’t Persist After Restart”Plate scope checks:
- Is
oxmysqlstarted? (Soft dependency) - Is vehicle owned? Check
player_vehicles/owned_vehiclestable. Config.CarPlay.ownership.fallbackOwned = true(default) treats unknown as owned.
Player scope: Always persists if settingsScope = 'player'.
“CarPlay unavailable for this vehicle”
Section titled ““CarPlay unavailable for this vehicle””Cause: Vehicle class in disabledVehicleClasses.
Fix: Remove the class ID from the array or use a different vehicle.
Radio Browser API Fails / Empty Results
Section titled “Radio Browser API Fails / Empty Results”Check: Config.Radio.browser.server reachable from server machine.
Test: curl https://de1.api.radio-browser.info/json/stations/bytagexact/rock?limit=10&order=clickcount&reverse=true&hidebroken=true
Fix: Change server to a working mirror (e.g., https://nl1.api.radio-browser.info).
File Reference (Escrow-Ignored / Buyer-Editable)
Section titled “File Reference (Escrow-Ignored / Buyer-Editable)”| File | Purpose |
|---|---|
config.lua |
All configuration (framework, UI, apps, audio, persistence, fuel, radio, navigation) |
client/utils.lua |
Fuel system registry, vehicle helpers (Client.GetVehicleFuelLevel, Client.CanUseCarPlay, etc.) |
frameworks/**/shared.lua |
Framework bridge shared methods (Bridge.GetCoreObject) |
locales/*.json |
Translations (add new languages here) |
All other files ship encrypted in escrow releases.
Updating the Resource
Section titled “Updating the Resource”- Replace the resource folder.
- Restart resource in-game.
Warning: Never edit files in
html/— they are generated and git-ignored.
Note: This guide is written by a third party. If you find any incorrect or outdated information, please contact us on Discord so we can update it for you.