Jixryo Freight

Truckers carry other resources' freight. Depots set up in game, a board at the desk and on the phone and tablet, the depot's truck with a deposit, the drive watched by the server, the dock, boxes carried in by hand or on the hand truck, the pay worked out by the server, and the 24/7s with real stock restocked by truck.

Version 0.2.0 Updated See it on its script page

On this page

Jixryo Freight gives the city truckers with real loads to carry. A contract is a load of boxes from a depot to a business's delivery dock, posted by another resource: today Jixryo Restaurants' supply orders, and the 24/7s' restocks that Freight posts itself. A driver signs on at a depot's desk, takes a contract from the board, takes the depot's truck, drives it to the dock, carries the boxes in and is paid by the server. City staff set the depots up in game; no coordinates live in a config file. The resource is jixryo_trucking.

What players get

  • Signing on at a depot's desk: E opens the board, and Sign on is there. Anyone may, or only one job when Config.job names it.
  • The board, at the desk and in the Freight app on Jixryo Phone and Jixryo Tablet: the contracts open now, express first, then by pay. Each shows its route on the map, the road distance, the boxes and their weight, the truck, the cargo (frozen, chilled or dry), when the courier takes it, and the pay as the server works it out: base, distance, the boxes, cold cargo, on time and express. Accept one at a time.
  • The truck. The lightest that holds the load (the Mule up to 500 kg, the Benson up to 1,500 kg, the Pounder for anything bigger) comes out at a free bay with its keys and the plate JXF#####. A 250 dollar deposit comes from your bank, and the GPS goes to the bay.
  • The drive. The GPS goes to the dock once you leave the bay. The card on the HUD shows the steps, the clock for the on-time pay, the load and a cold load's reefer. Frozen and chilled loads run their reefer off the engine: with the engine off after leaving the bay, or the back open, the load warms, and after 10 minutes for frozen (20 for chilled) the cold boxes have spoiled. Spoiled boxes still go in, but come off your pay.
  • The dock. Back the truck's rear into the dock's zone, stand at its back and press E to open the back. E takes a box into your arms; H takes the hand truck, which carries four a trip. At the door, E stocks what you carry into the restaurant's storage box by box, or onto the 24/7's shelf.
  • The pay, once, to your bank when the last box is in: 350 dollars base, 95 per road kilometre, 15 per box, 25 percent more for frozen cargo (15 for chilled), 15 percent for arriving inside the on-time window, 20 percent for express; less the truck's worst of body and engine damage up to 60 percent, less each spoiled box's share.
  • Returning the truck to the depot's return lot and pressing E gives the deposit back. Left more than 15 minutes after the last box, the truck goes and so does the deposit. Giving up before the dock puts the contract back on the board and loses the deposit; a truck gone or wrecked, or leaving the city, does the same. If the poster calls the order off, the deposit comes back.
  • The 24/7s have real stock: their food and drink are counted at every store, a purchase lowers the count, the shop says "out of stock" at 0, and under a third of a full shelf the city puts the store's restock on the board, paid by the city. Nobody takes it in 30 minutes: the city's courier refills the store 15 minutes later. Needs the Jixryo ox_inventory fork's SetShopStock and GetShopStock; with an older fork the 24/7s stay unlimited and the console says so once.

What staff get

  • /freight, for city staff (group.god and group.admin, Config.staff): New depot here puts its sign-on desk where you stand, facing where you face, with a name. On a depot: Add a truck bay saves the position and heading of the truck you sit in (up to 12 bays), Set the return lot here, Move the desk here, Remove bay N, Remove this depot (refused while one of its trucks is out).
  • The 24/7s, from the same menu: every store nearest first, with how many items run low and whether it is set up. Within 80 m of a store's shopkeeper, Loading spot here (stand where a truck's back should stand, facing the door), Door here (where the boxes go in), and a name for the store. A store not set up still counts down but gets no restocks.
  • Every change shows for everyone at once (the depots are one global state, with a blip each) and goes to the audit log: freight.depot, freight.store, freight.accept, freight.giveUp, freight.paid and freight.returned.
  • A restaurant needs a delivery dock for its orders to come by truck: in /restaurants, Back of house, Delivery dock, Mark point. Its zone is where the truck's back goes and its prompt spot (G) is the door the boxes go through, within 3 m of the zone.

Install

  1. What it replaces. Nothing by name. There are no items.

  2. Order. It depends on ox_lib, oxmysql, qbx_core and Jixryo Core. Jixryo Restaurants may start before or after it. It uses Jixryo Phone and Jixryo Tablet (the board as an app), Jixryo MDT (its map tiles draw the board's route map; without it the map is blank), Jixryo Keys (the truck's keys, through Jixryo Core) and the Jixryo ox_inventory fork (the 24/7s' stock) when they run.

    server.cfg
    ensure ox_lib
    ensure oxmysql
    ensure qbx_core
    ensure jixryo_core
    ensure jixryo_trucking
  3. Database. The tables make themselves on the first start, as two Jixryo Core migration steps: jixryo_fr_depots, jixryo_fr_contracts, jixryo_fr_runs and jixryo_fr_stores.

  4. The ox_inventory fork. The 24/7s' counts need the fork's SetShopStock and GetShopStock (in its modules/shops/server.lua since 2026-10-15); upload it with this resource and restart ox_inventory before Freight. The General shop's locations are read from the fork's own data/shops.lua.

  5. Set up a depot in game with /freight: nothing works until one has a desk and at least one bay.

  6. Set the 24/7s up for restocks, and give each restaurant a delivery dock.

  7. The pages ship built in web/build (game.html for the desk's board, the run's card and the pay; board.html for the app).

  8. Restart the whole server the first time, so Jixryo Phone, Jixryo Tablet and ox_inventory pick it up together.

How other scripts' calls behave

  • It answers as itself only. Its exports live under jixryo_trucking; nothing is provided under another name.
  • The poster. Another server resource posts a contract with Post and takes it back with Cancel, and hears every step through its own FreightEvent(ref, event, data) export, only while it runs. Jixryo Restaurants posts its supply orders this way; Freight's own posts are the 24/7s' restocks.
  • qbx_core, through Jixryo Core's player module: the citizen ID, name, job and bank money.
  • ox_inventory. The General shop's locations from its data/shops.lua, item labels with Items, a buyItem hook filtered to that shop to hear each sale, and the fork's SetShopStock and GetShopStock to set and read the counts. When ox_inventory restarts, the counts and the hook are set again two seconds later.
  • Jixryo Phone and Jixryo Tablet. It adds the app jixryo_freight ("Freight", web/build/board.html, folded and open on the phone) to each that runs, again when either restarts.
  • Jixryo Keys. The truck's keys go to the driver through Jixryo Core's vehicles module.
  • Jixryo Core. It uses the database, validation, permission, rate limit, player, audit, HUD and vehicles modules.
  • Global state. Every game reads jxfr_depots: each depot's desk, bays and return lot.

Its own API

Server exports:

ExportWhat it does
Post(spec)Posts a contract and returns its id, or nil and why. spec = { ref, kind = 'restaurant' or 'store', express, to = { label, area, dock = { x, y, z, h, sx, sy, sz }, door = { x, y, z } }, boxes = { { case, label, keep = 'frozen', 'chilled' or 'dry' (or 'freezer', 'fridge'), kg }, ... } }, 1 to 200 boxes in carrying order. The server picks the nearest depot with bays, measures the road, picks the truck by weight and works out the pay
Cancel(id)Takes a contract back; only the resource that posted it. A driver on it is told and gets the deposit back

What the poster's FreightEvent(ref, event, data) receives:

EventWhenData
takena driver took itdriver
releasedback on the board (given up, the truck lost, a restart)boxesIn
atDockthe back opened at the dockboxes, boxesIn, driver
boxeach box through the doorn, case, label, keep, spoiled
donethe last box is inboxes, spoiled, driver
couriernobody took it in Config.courierAfterboxesIn

Events:

EventDirectionWhat it carries
jixryo_trucking:client:runto the driverthe run as the HUD shows it (step, truck, boxes, reefer, pay), or false when it ends
jixryo_trucking:client:paidto the driverthe pay's parts: base, distance, boxes, cargo, on time, express, damage, spoiled, total
jxfr_depotsglobal statethe depots

The pages' calls go through 23 server callbacks named jixryo_trucking:server:<name> (the depots and stores for staff, signing on and off, the board, accepting and giving up, the back, boxes, the hand truck, stocking and returning); they are not an API, and the server checks every one.

Commands and keybinds

Command or keyWhoWhat it does
/freightanyone may type it; the server refuses all but city staffThe depots menu: new depot, bays, desk, return lot, remove; the 24/7s' loading spots, doors and names
E at a depot's deskanyone on footOpens the board; Esc or its Close button closes it
E at the truck's backthe run's driverOpens the back, takes a box, loads the hand truck, closes the back
H at the truck's backthe run's driver, hands emptyTakes the hand truck, or puts it back
E at the doorthe driver carrying boxesStocks them
E at the return lotthe driver, deliveredReturns the truck for the deposit

There are no keybinds to rebind: the resource registers none.

Configuration

config.lua:

KeyDefaultWhat it does
staffgroup.god, group.adminCity staff, who use /freight
jobfalseAnyone signs on; a qbx job name limits it to that job
nameJixryo FreightThe company's name on the board, the HUD and bank statements
trucksMule 500 kg (rear 4.2 m), Benson 1,500 kg (5.0 m), Pounder anything (5.6 m)The trucks, lightest first, and how far behind the middle the back doors are
deposit250The truck's deposit
paybase 350, perKm 95, perBox 15, roadFactor 1.3, frozen 0.25, chilled 0.15, onTime 0.15, express 0.20, damageMax 0.6The pay's parts
onTimebase 300, perKm 150The on-time window in seconds, from taking the contract to the back opening
fastest40No truck reaches the dock faster than this (m/s, straight line)
courierAfter1800Seconds before nobody's contract goes back to its poster
reeferfrozen 600, chilled 1200Seconds a cold load may warm before it spoils
abandon900Seconds a delivered truck may sit before it goes with its deposit
sample5000How often the server looks at every truck on a run (ms)
carrythe heist box and the sack truck, the box carry clip, 4 boxes a tripWhat the driver carries
reachdesk 3.0, back 3.0, door 3.0, returnLot 20.0How close you must be
storesshop General, label 24/7, restockBelow 1/3, courier 900, reach 80.0, dock 4 by 6 by 4, 12 items (hotdogs, burritos, churros, donuts, snacks, peanuts, pretzels, two sodas, water) with a full shelf, a case's count and weightThe 24/7s
appphone true, tablet trueThe board on the phone and the tablet
blipsprite 477, colour 0, scale 0.8The depots' blip

Security

  • Every callback checks the caller every time: city staff for the depots and stores, signed on at a desk (and the job when set) to take a contract, only the run's own driver for its steps, near the truck's back or the door, all rate limited.
  • The truck is the server's. It is made by the server and its net id is tied to the run; every few seconds the server reads where it is, its health and its engine. The back opens only when the truck's own back is inside the dock and the driver stands at it, and no sooner than the distance allows at Config.fastest.
  • Money. The pay is worked out only on the server, from the contract, the time and the truck's health. It is paid once: the contract closes before anything waits, and a box cannot be counted twice. The deposit is taken before the truck comes out and given back if the truck cannot. Every step is audited.
  • One contract per driver. A contract taken is nobody else's until it is delivered or released.
  • The 24/7s. The shop's own buy keeps deciding what is sold; Freight only sets the counts and reads them back after a sale that went through. A restock box can only add its own item's case, at its own store.
  • Posted contracts are checked even though only server resources can call Post: the places, at most 200 boxes, their cargo kind and weights. FreightEvent goes only to the resource that posted the contract.

Tests

Two suites in dev-tools/luarun/tests, sharing jixryo_trucking.setup.lua (a real database with Jixryo Core's real validate, perm and db modules, its keys and money stood in, the poster recording every step, and ox_inventory's 24/7s with the fork's stock exports). Both run on 2026-10-31.

SuiteResultWhat it covers
jixryo_trucking.lua13 passed, 0 failedThe tables; a depot set up by staff; signing on; a posted contract's depot, distance, truck, cargo and pay, broken specs refused; the board's order, the courier and Cancel; taking a contract with the deposit, the bay, the truck, plate and keys; the drive watched, the reefer, spoiling, the truck gone or wrecked, giving up, leaving; the dock, the boxes, the hand truck, the pay once with damage off; late and spoiled; returning the truck and a truck left too long; a restart; the 24/7s' counts, sales, restocks, a restock run, the courier and staff setting a store up.
jixryo_trucking.client.lua2 passed, 0 failedA stand-in player's game against the real server: the board in both app stores and again on a restart, the depot's blip, the desk's E and the board with focus, the page's calls; a whole run with the HUD's card and the GPS for each step, the back opened with E, a box in the arms, the hand truck with H, stocking at the door, the pay on screen and the truck returned.
bash
cd dev-tools/luarun
node run.mjs ../../jixryo_scripts/jixryo_trucking tests/jixryo_trucking.lua
node run.mjs ../../jixryo_scripts/jixryo_trucking tests/jixryo_trucking.client.lua

The README also records 39 bugs planted in the server and 11 in the client for the runs, and 20 for the 24/7s, each caught by these tests, and the Lua checks dev-tools/luacheck/check.mjs, configpaths.cjs and dev-tools/natives/audit.mjs.

Check it in game

  1. As staff at a warehouse yard, /freight, New depot here: a blip appears. Drive a Mule into the first bay, park it straight, Add a truck bay, then remove the truck. Stand at the gate and Set the return lot here.
  2. In /restaurants at Burger Shot, Back of house, Delivery dock, Mark point: the zone where a truck's back should stand, with its prompt spot at the back door.
  3. As Burger Shot's manager, order two cases of ground beef and one of buns in the Restaurant app. Supplies says "On the board".
  4. As a driver with 250 dollars in the bank, E at the desk: the board opens. Sign on. The contract shows its map, road, boxes, truck and pay. The Freight app is in the phone's store and its board matches.
  5. Accept: the bank is down 250, a Mule stands in bay 1 with a JXF plate, you have its keys and the GPS points at it.
  6. Leave the bay: the GPS goes to the dock and the card shows the drive and the clock. Stop with the engine off: the reefer timer runs down. Start it again: it stops.
  7. Back in so the truck's rear is in the dock's zone, get out at the back: E opens the back doors, E puts a box in your arms, E at the door stocks it into the freezer, and the app says unloading 1 of 3. H takes the hand truck for the other two: the pay shows and your bank goes up by it.
  8. Drive to the depot's lot: E returns the truck and the deposit comes back.
  9. Order again and leave it: 30 minutes on, the board drops it and the courier brings it.
  10. With the ox_inventory fork, open a 24/7: the food and drink show how many are left. Buy two waters: the count drops, and another 24/7 keeps its own. As staff, set the store's loading spot and door and name it; buy the water down under a third: within half a minute its restock is on the board, and each case carried in shows on the shelf at once. Restart ox_inventory and then Freight: the counts hold.
Next step

Ready to look around?

Browse the suite, or paste your server.cfg and see what each script does to your server.