Integration API
Exports and events for phones and other scripts: duty, stores and the tablet.
DashKart exposes a small API so other resources can work with the rider job without editing DashKart’s code. The exports keep working when DashKart is delivered through the Cfx.re asset escrow.
The typical use is a phone app with Clock in / Clock out buttons. Any phone works (lb-phone, qb-phone, NPWD, yseries, a custom one): the phone’s app calls DashKart’s client exports from its own client script.
1. Allow clocking in / out away from the store
By default riders clock in and out at the store’s duty point. To allow it from a phone, turn it on in config/rider.lua:
remoteDuty = {
clockIn = true, -- clock in at a chosen store from anywhere
clockOut = true, -- clock out from anywhere
},
The server still decides everything:
- Clocking in earns nothing by itself. The rider still rents the scooter / van at the store (and returns it there), and every order still starts with picking at the store.
- A remote clock out is refused while an order is active (
rider.finish_order_first) or a rental is out (rider.return_rental_first). The rental is never forfeited from a phone. - Staff-only stores, double clock-ins and the rate limit apply exactly as at the counter.
- With
remoteDutyoff, the exports still work for a player standing at the duty point; anywhere else they getrider.duty_at_store.
A first clock-in from the phone gives the free DashKart tablet exactly like the counter (Config.Tablet.giveOnClockIn: straight into the inventory, once per character per day, only without one). With a full inventory the player is told to make room and clock in again. Servers that want the tablet without any item set Config.Tablet.requireItem = false; OpenTablet() then works for everyone.
The player always sees DashKart’s own notification for the result (clocked in, or why not), so your app only needs to refresh its buttons.
2. Client exports
| Export | Returns | What it does |
|---|---|---|
exports.dashkart:ClockIn(storeId?) |
ok, err |
Clocks in at storeId (a Config.Stores[].id), or at the nearest store when nil. |
exports.dashkart:ClockOut() |
ok, err |
Clocks out. |
exports.dashkart:IsOnDuty() |
boolean |
On duty right now. |
exports.dashkart:GetDuty() |
table|nil |
{ storeId, storeLabel, streak, deliveries, rental = { kind, plate }|nil, order = { code, state, customerName }|nil }, nil when off duty. |
exports.dashkart:GetStores() |
table[] |
Every store, nearest first: { id, label, coords = { x, y, z }, distance, ownable }. Use it for a store picker. |
exports.dashkart:CanUseRemoteDuty() |
table |
{ clockIn = boolean, clockOut = boolean } from Config.Rider.remoteDuty, to show or hide your buttons. |
exports.dashkart:OpenTablet() |
- | Opens the DashKart tablet (same item check as F6). |
err is a DashKart locale key, e.g. rider.already_on_duty, rider.staff_only, rider.finish_order_first, rider.return_rental_first, rider.duty_at_store.
ClockIn, ClockOut and OpenTablet wait for the server, so call them from a thread. NUI callbacks, command handlers and CreateThread bodies already are one. Called outside a thread they still run (in a new thread) but return nil, 'async'.
Event
-- fires on every clock in / out: phone app, store counter, logout
AddEventHandler('dashkart:client:dutyChanged', function(onDuty, storeId)
-- refresh your app's state here
end)
3. Server exports
| Export | Returns |
|---|---|
exports.dashkart:IsOnDuty(source) |
boolean |
exports.dashkart:GetDuty(source) |
{ storeId, storeLabel, since, deliveries, streak, rental = { kind, plate }|nil, order = { id, code, state }|nil } or nil |
Read-only: they never change a rider’s state or move money.
4. Examples
Any phone: NUI callbacks in your app’s client script
Most phone app systems let your app’s web page call NUI callbacks of your own resource. Wire the buttons to DashKart there:
-- client.lua of your phone app resource
RegisterNUICallback('dashkart:state', function(_, cb)
cb({
onDuty = exports.dashkart:IsOnDuty(),
duty = exports.dashkart:GetDuty(),
stores = exports.dashkart:GetStores(),
remote = exports.dashkart:CanUseRemoteDuty(),
})
end)
RegisterNUICallback('dashkart:clockIn', function(data, cb)
local ok, err = exports.dashkart:ClockIn(data and data.storeId) -- nil = nearest store
cb({ ok = ok == true, err = err })
end)
RegisterNUICallback('dashkart:clockOut', function(_, cb)
local ok, err = exports.dashkart:ClockOut()
cb({ ok = ok == true, err = err })
end)
RegisterNUICallback('dashkart:openTablet', function(_, cb)
exports.dashkart:OpenTablet()
cb({})
end)
-- push duty changes to your app (use your phone's own "send to app" function here)
AddEventHandler('dashkart:client:dutyChanged', function(onDuty, storeId)
SendNUIMessage({ action = 'dashkart:duty', onDuty = onDuty, storeId = storeId })
end)
How the app’s page reaches these callbacks, and how you register the app on the home screen, depends on your phone resource (for lb-phone: its custom app template and AddCustomApp; for qb-phone / NPWD: their app docs). DashKart’s part is only the exports above.
Simple test command (no phone needed)
RegisterCommand('dkduty', function()
if exports.dashkart:IsOnDuty() then
exports.dashkart:ClockOut()
else
exports.dashkart:ClockIn() -- nearest store
end
end, false)
Server side: only paid for on duty, HUD badge, …
local duty = exports.dashkart:GetDuty(source)
if duty then
print(('%s is riding for %s (%d deliveries)'):format(GetPlayerName(source), duty.storeLabel, duty.deliveries))
end