Skip to main content

Database

Auto-installed MySQL tables — players, mileage, dashcam recordings.

This section

Database

Carplay V2 uses three MySQL tables, all created automatically on server start via oxmysql. There is no manual SQL import required — but the same schema is in the included data.sql if you prefer manual setup.

Tables

TablePurpose
code9_carplay2Per-player settings, liked songs, playlist, volume
code9_carplay2_mileageInternal mileage tracking (per plate)
code9_carplay2_dashcamUploaded dashcam / security cam recordings

Table: code9_carplay2

Per-player profile, music preferences, and arbitrary settings.

ColumnTypeDefaultDescription
identifierVARCHAR(64)(PK)Player identifier (license, steam, discord — depends on Config.IdentifierType)
settingsLONGTEXT'{}'JSON blob of settings (theme, accent, name, avatar, notes, places, …)
liked_songsLONGTEXT'[]'JSON array of liked song objects
playlistLONGTEXT'[]'JSON array of user playlists
volumeINT50Player's last volume setting (0-100)
created_atTIMESTAMPCURRENT_TIMESTAMPRow creation timestamp
updated_atTIMESTAMPCURRENT_TIMESTAMP ON UPDATEAuto-updated on any change

Settings JSON Shape

The settings column holds a flexible JSON object. Common keys:

json
{
"firstName": "John",
"lastName": "Doe",
"avatar": "12.png",
"avatarUrl": null,
"theme": "dark",
"accent": "#007AFF",
"notes": [ ... ],
"places": [
{ "name": "Home", "icon": "home", "x": 100.0, "y": 200.0 }
],
"recents": [ ... ],
"favorites": [ ... ],
"autopilotFlags": { "DF_STOP_AT_LIGHTS": true },
"speedLimiter": 80,
"suspensionPreset": "standard",
"autoLowerSpeed": 65
}

The exact shape is determined by the React app — feel free to add new keys for custom features.

Auto-Creation

When a player first opens Carplay (or first triggers any persistence write), the server runs INSERT IGNORE to ensure the row exists. Existing rows are never overwritten — only updated.


Table: code9_carplay2_mileage

Internal mileage tracking — used only when Config.MileageSystem = "internal" (or "auto" falls back to internal because no third-party provider is detected).

ColumnTypeDefaultDescription
plateVARCHAR(32)(PK)Vehicle plate text
mileageFLOAT0Total mileage in km
updated_atTIMESTAMPCURRENT_TIMESTAMP ON UPDATELast update

How Mileage Is Tracked

When MileageSystem = "internal":

  1. Client thread polls vehicle position every ~1 second
  2. Computes distance from last position, accumulates per plate
  3. Periodically (and on resource stop) flushes to server
  4. Server writes to code9_carplay2_mileage via INSERT … ON DUPLICATE KEY UPDATE

When MileageSystem = "jg-vehiclemileage" or "cd_garage", this table is not used — the script reads via the third-party export instead.


Table: code9_carplay2_dashcam

Stores metadata for uploaded dashcam and security camera recordings. The actual video file lives at the upload provider (Fivemanage or Discord).

ColumnTypeDefaultDescription
idINT (PK, AI)Auto-increment record ID
identifierVARCHAR(64)Owner identifier (indexed)
video_urlVARCHAR(512)Public URL to the uploaded video
durationINT0Length in seconds
file_sizeINT0Bytes
vehicle_plateVARCHAR(32)NULLPlate the recording was made in
camera_angleVARCHAR(16)'front''front' or 'rear'
sourceVARCHAR(16)'dashcam''dashcam' or 'securitycam'
created_atTIMESTAMPCURRENT_TIMESTAMPUpload timestamp

Index

There is an index on identifier for fast per-player recording lookups.

Cleanup

Old recordings beyond Config.DashCam.recording.maxRecordingsPerPlayer (or the security cam equivalent) are not auto-deleted from the upload provider — only from this table. If you want to enforce hard limits, add a server-side cleanup job that calls the Fivemanage delete API or unfurls the Discord message.


Database Driver

Carplay V2 uses oxmysql onlymysql-async and ghmattimysql are not supported. This was a deliberate choice for performance and modern API surface.

If you absolutely must run an older driver, you would need to rewrite the SQL calls in server/open.lua and the relevant module files.