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.jobnames 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
SetShopStockandGetShopStock; with an older fork the 24/7s stay unlimited and the console says so once.
What staff get
/freight, for city staff (group.godandgroup.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.paidandfreight.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
What it replaces. Nothing by name. There are no items.
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_truckingDatabase. The tables make themselves on the first start, as two Jixryo Core migration steps:
jixryo_fr_depots,jixryo_fr_contracts,jixryo_fr_runsandjixryo_fr_stores.The ox_inventory fork. The 24/7s' counts need the fork's
SetShopStockandGetShopStock(in itsmodules/shops/server.luasince 2026-10-15); upload it with this resource and restart ox_inventory before Freight. TheGeneralshop's locations are read from the fork's owndata/shops.lua.Set up a depot in game with
/freight: nothing works until one has a desk and at least one bay.Set the 24/7s up for restocks, and give each restaurant a delivery dock.
The pages ship built in
web/build(game.htmlfor the desk's board, the run's card and the pay;board.htmlfor the app).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
Postand takes it back withCancel, and hears every step through its ownFreightEvent(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
Generalshop's locations from itsdata/shops.lua, item labels withItems, abuyItemhook filtered to that shop to hear each sale, and the fork'sSetShopStockandGetShopStockto 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:
| Export | What 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:
| Event | When | Data |
|---|---|---|
taken | a driver took it | driver |
released | back on the board (given up, the truck lost, a restart) | boxesIn |
atDock | the back opened at the dock | boxes, boxesIn, driver |
box | each box through the door | n, case, label, keep, spoiled |
done | the last box is in | boxes, spoiled, driver |
courier | nobody took it in Config.courierAfter | boxesIn |
Events:
| Event | Direction | What it carries |
|---|---|---|
jixryo_trucking:client:run | to the driver | the run as the HUD shows it (step, truck, boxes, reefer, pay), or false when it ends |
jixryo_trucking:client:paid | to the driver | the pay's parts: base, distance, boxes, cargo, on time, express, damage, spoiled, total |
jxfr_depots | global state | the 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 key | Who | What it does |
|---|---|---|
/freight | anyone may type it; the server refuses all but city staff | The depots menu: new depot, bays, desk, return lot, remove; the 24/7s' loading spots, doors and names |
| E at a depot's desk | anyone on foot | Opens the board; Esc or its Close button closes it |
| E at the truck's back | the run's driver | Opens the back, takes a box, loads the hand truck, closes the back |
| H at the truck's back | the run's driver, hands empty | Takes the hand truck, or puts it back |
| E at the door | the driver carrying boxes | Stocks them |
| E at the return lot | the driver, delivered | Returns the truck for the deposit |
There are no keybinds to rebind: the resource registers none.
Configuration
config.lua:
| Key | Default | What it does |
|---|---|---|
staff | group.god, group.admin | City staff, who use /freight |
job | false | Anyone signs on; a qbx job name limits it to that job |
name | Jixryo Freight | The company's name on the board, the HUD and bank statements |
trucks | Mule 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 |
deposit | 250 | The truck's deposit |
pay | base 350, perKm 95, perBox 15, roadFactor 1.3, frozen 0.25, chilled 0.15, onTime 0.15, express 0.20, damageMax 0.6 | The pay's parts |
onTime | base 300, perKm 150 | The on-time window in seconds, from taking the contract to the back opening |
fastest | 40 | No truck reaches the dock faster than this (m/s, straight line) |
courierAfter | 1800 | Seconds before nobody's contract goes back to its poster |
reefer | frozen 600, chilled 1200 | Seconds a cold load may warm before it spoils |
abandon | 900 | Seconds a delivered truck may sit before it goes with its deposit |
sample | 5000 | How often the server looks at every truck on a run (ms) |
carry | the heist box and the sack truck, the box carry clip, 4 boxes a trip | What the driver carries |
reach | desk 3.0, back 3.0, door 3.0, returnLot 20.0 | How close you must be |
stores | shop 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 weight | The 24/7s |
app | phone true, tablet true | The board on the phone and the tablet |
blip | sprite 477, colour 0, scale 0.8 | The 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.FreightEventgoes 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.
| Suite | Result | What it covers |
|---|---|---|
jixryo_trucking.lua | 13 passed, 0 failed | The 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.lua | 2 passed, 0 failed | A 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. |
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.luaThe 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
- 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. - In
/restaurantsat 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. - As Burger Shot's manager, order two cases of ground beef and one of buns in the Restaurant app. Supplies says "On the board".
- 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.
- Accept: the bank is down 250, a Mule stands in bay 1 with a
JXFplate, you have its keys and the GPS points at it. - 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.
- 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.
- Drive to the depot's lot: E returns the truck and the deposit comes back.
- Order again and leave it: 30 minutes on, the board drops it and the courier brings it.
- 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.