Browse docs
Fake Plate Integration
Sky Mechanic Job keeps two plate identities while a fake plate is active:
| Value | Purpose |
|---|---|
| Real plate | Persistent ownership, garage database lookups, keys, and stored vehicle records |
| Display plate | The plate visible on the vehicle and to Police, radar, dispatch, cameras, and UI |
A resource must deliberately choose which identity it needs. Do not apply the real-plate override to every resource.
Choose the plate by operation
The resource name alone does not decide which plate is correct. Choose the identity required by each operation:
| Operation | Plate identity | Recommended integration |
|---|---|---|
| Garage, impound, or parking ownership and database lookup | Real plate | Native override or explicit helper |
| Vehicle key ownership, lock authorization, and plate-based key grant/removal | Real plate | Native override or explicit helper |
| Persistent trunk, glovebox, fuel, mileage, damage, tuning, or service data keyed by plate | Real plate | Native override or explicit helper |
| Police, dispatch, radar, camera, plate scanner, or player-facing observation | Display plate | No native override |
| Resource that performs both persistent lookups and visible plate output | Real or display plate per operation | Explicit helper functions |
| Garage that despawns and later respawns vehicles | Real plate plus fake-plate state | Server exports in addition to one of the lookup integrations |
Native override for persistent-identity resources
Add the compatibility file to the resource that reads the vehicle plate, not to the Sky Mechanic Job manifest. This can be a garage, vehicle-key, inventory, fuel, mileage, persistence, or framework resource:
shared_script "@sky_mechanicjob/compat/fakeplates_realplate_native.lua"
dependency "sky_mechanicjob"
When the resource already has a shared_scripts block, add the compatibility file as its first entry and retain its existing entries:
shared_scripts {
"@sky_mechanicjob/compat/fakeplates_realplate_native.lua",
"config.lua"
}
dependency "sky_mechanicjob"
Place the compatibility entry before the consuming resource's own shared scripts. It makes calls to GetVehicleNumberPlateText(vehicle) inside that resource return the real plate while a Sky fake plate is active. It also patches common vehicle-property readers loaded by that resource.
FiveM gives every resource its own Lua environment. The override therefore affects only the resource that loads this file.
Use the native override when every plate read in that resource should represent persistent identity, for example:
- Granting, checking, or removing vehicle keys by plate
- Looking up ownership before storing, selling, transferring, or impounding a vehicle
- Opening persistent trunk or glovebox storage keyed by plate
- Reading or writing persistent fuel, mileage, damage, tuning, or service records
Do not load this override in:
- Police resources
- Dispatch resources
- Radar or speed-camera resources
- Plate overlays
- Other UI that should show the plate visible on the vehicle
Vehicle key resources
Vehicle key systems normally need the real plate so existing keys continue to work while a fake plate is installed. There are two common integration paths:
- If the vehicle-key resource calls
GetVehicleNumberPlateText(vehicle)itself, loadfakeplates_realplate_native.luain that vehicle-key resource. - If another resource reads the plate and then passes a string to a vehicle-key export or event, integrate the resource that performs that first read. The receiving key resource cannot recover the real plate from the display-plate string alone.
When the calling resource also displays the visible plate, use the explicit helper file instead of overriding every native read:
local real_plate = SkyGetVehicleRealPlateText(vehicle)
exports["your_vehiclekeys"]:GiveKeys(real_plate)
Replace the example resource and export names with the API of your installed vehicle-key resource. The important part is resolving real_plate while the vehicle entity is available, before passing the value across a resource boundary.
Explicit real/display plate helpers
Use the helper file when a resource must choose the identity per operation:
shared_script "@sky_mechanicjob/compat/fakeplates.lua"
dependency "sky_mechanicjob"
The file provides these functions inside the consuming resource:
| Function | Returns |
|---|---|
SkyGetVehicleDisplayPlateText(vehicle) | The currently displayed plate |
SkyGetVehicleRealPlateText(vehicle) | The persistent real plate |
SkyGetVehicleFakePlateState(vehicle) | Active fake-plate metadata, or nil |
local real_plate = SkyGetVehicleRealPlateText(vehicle)
local display_plate = SkyGetVehicleDisplayPlateText(vehicle)
local fake_plate = SkyGetVehicleFakePlateState(vehicle)
Use real_plate for ownership and database keys. Use display_plate for player-facing labels and observations.
The helper file is the safer choice for mixed resources. A garage menu, for example, may need the real plate for its database query but the display plate in a nearby-vehicle label. A key resource may need the real plate for authorization but the display plate in a notification.
Persist fake plates through garage storage
The compatibility file corrects plate reads, but it cannot persist entity state after the garage deletes the vehicle. A compatible garage must save the fake-plate state before despawning the entity and restore it after the new networked vehicle exists.
Store
Run this on the server while the vehicle entity still exists:
local resolved = exports["sky_mechanicjob"]:ResolveRealPlateForGarageStore(net_id)
if resolved then
vehicle_data.plate = resolved.realPlate
if resolved.resetOnGarageStore then
exports["sky_mechanicjob"]:ClearFakePlate(net_id, "garage_store")
vehicle_data.skyFakePlate = nil
else
vehicle_data.skyFakePlate = exports["sky_mechanicjob"]:GetFakePlateState(net_id)
end
end
Persist vehicle_data.skyFakePlate with the garage's other vehicle properties. Never replace the persistent database plate with displayPlate.
Restore
After the garage has spawned the vehicle and its network ID resolves to an existing server entity:
if vehicle_data.skyFakePlate then
local restored, result = exports["sky_mechanicjob"]:RestoreFakePlateState(
net_id,
vehicle_data.skyFakePlate,
"garage_spawn"
)
if not restored then
print(("[garage] Fake plate restore failed: %s"):format(tostring(result)))
end
end
RestoreFakePlateState validates the real plate, display plate, active state, vehicle entity, and expiry time. An expired fake plate is not restored.
Configuration
Config.FakePlates.resetOnGarageStore controls the intended storage policy:
| Value | Behavior |
|---|---|
true | Storing the vehicle removes the fake plate |
false | A compatible garage may save and restore the fake plate |
The default in version 1.20.0 is false.
Test checklist
- Store a normal vehicle and confirm its database plate is unchanged.
- Install a fake plate and confirm the garage still finds the vehicle by its real plate.
- Confirm keys granted before the fake plate was installed still lock, unlock, and start the vehicle.
- Grant and remove keys while the fake plate is active and confirm the key resource uses the real plate.
- Confirm plate-keyed storage and persistence resources do not create new records under the display plate.
- Confirm Police, radar, dispatch, and visible UI continue to show the display plate.
- Store and respawn the vehicle and confirm the configured reset/persist policy is respected.
- Confirm expired fake plates are not restored.
- Restart each consuming resource and verify its dependency starts after
sky_mechanicjob.