Skip to content

Releases: MSK-Scripts/msk_fuel

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 08:44
e4a32ea

Dashboard access now works the same on every framework.

Requires

  • msk_core 4.0.0 or newer. This release reads the player through the
    rewritten bridge. On msk_core 3.x the group lookup returns nothing, and
    dashboard access then depends entirely on your ACE setup. Update msk_core
    along with this script.

Changed

  • The framework group is read on QBCore and Qbox too. Group membership means
    "ACE principal OR framework group", and the framework half only ever worked on
    ESX. It went through xPlayer.getGroup(), a method QBCore and Qbox do not
    have, so an admin without the matching add_principal line was refused there.
    player.group is a plain string on all three frameworks since msk_core 4.0.0:
    ESX hands over what it stores, QBCore and Qbox reduce their permission table to
    the highest level they find.
  • MSK.GetPlayer is called with the server id instead of a {source = } table,
    which is what msk_core 4.0.0 expects.

Fixed

  • The QBCore-only fallback ran on every framework. GetQbPermission starts
    with a check that leaves the function unless QBCore is running, and that check
    could never pass: in a consumer resource MSK.Bridge used to resolve to a
    function, so reading MSK.Bridge.Framework raised
    attempt to index a function value instead of returning. msk_core 4.0.0 makes
    MSK.Bridge a real table, so the branch now does what it says. On Qbox the
    same information already arrives through the framework group.

Changed files

fxmanifest.lua
server/admin/permissions.lua

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 15:54
b832937

Stable release of the fuel business. Same content as the 1.2.0-beta.1
pre-release from 2026-08-29, promoted after testing. The numbers behind the
mechanics (prices, wear rates, delivery pay) are balanced for a normal server,
so check them against your own economy before going live.
Fuel stations stop being blip coordinates and become businesses: they can be
bought, staffed, priced, supplied and worn out. Everything a player does with
one is checked against where they are actually standing, and the money and the
fuel are only ever moved by the server.

Requires

  • New dependency oxmysql. Nine tables are created and seeded automatically
    on first start, no SQL file to import.
  • Add this line to your server.cfg if it is not there already, so group
    permissions work (it covers every MSK script at once):
    add_ace resource.msk_core command.add_ace allow

Added

Stations as entities

  • All 30 map stations became named entities with a zone (center plus radius),
    their own stock and, once bought, an owner. The server resolves the station
    from the pump position, so no pump had to be re-mapped and this works on any
    map. Seed definitions live in config.stations.lua.
  • Blips are built from the station list and carry the station name, so renaming
    a station shows on the map right away.
    Economy
  • Stock per station per fuel type. An empty tank blocks that fuel type: the pump
    option greys out and the server refuses the sale.
  • Price per liter per station, either dynamic (rising as the tank empties and as
    demand goes up) or a fixed price, always clamped to the admin limits.
  • Market tick: the server-wide base price moves with total demand across all
    stations and eases back toward its anchor in quiet hours, which is what makes
    one busy station felt across the whole map.
  • Company account per station plus a full transaction log.
    Ownership
  • Buying a station at the pump, and selling it back for a configurable share of
    the purchase price plus whatever is on the company account.
  • Owner dashboard with eight tabs: overview, finance, prices, stock, supply,
    pumps, staff and ranks.
    Staff
  • Ranks per station with salary, delivery bonus and seven permissions. A freshly
    bought station starts with a manager and an employee rank.
  • Employees hired from the list of online players. An employee with at least one
    permission gets their own dashboard, showing only what their rank allows.
  • Salaries paid out of the company account every Config.Payroll.intervalMinutes
    to everyone online. A station that cannot cover its payroll skips it and tells
    the owner, instead of going into debt.
    Supply
  • NPC driver, unlocked once per station, for instant restocking at a surcharge,
    plus optional automatic restocking.
  • Delivery runs with three rigs (van 500 L, truck 1500 L, tanker 3000 L with a
    trailer and a bulk discount): pick up the rig, drive to a depot, load, come
    back. Crash damage spills up to 30 percent of the cargo.
  • Public delivery jobs at unowned stations, taken at the pump and paid per
    delivered liter out of the system. Enabled per station by the admin.
    Maintenance
  • Pumps wear out with use. A worn pump fuels slower, a broken one refuses to
    serve until it is repaired out of the company account. Pumps are never mapped:
    a pump enters the register the first time somebody fuels at it.
  • Mechanic on staff, unlocked once, repairs worn pumps automatically.
    Administration
  • In-game admin dashboard (/fueladmin, React + Vite + Tailwind, built into
    html/): station CRUD, stock and prices, market parameters, unowned-station
    settings, general settings with live theming, and a group permission matrix
    with nine rights.

Changed

  • msk_fuel:payFuelPrice carries the fuel type and the pump coordinates now.
    The server determines the station from them, charges the station price, takes
    the liters out of its tank and books the revenue. A tank that runs dry
    mid-refuel sells what is left instead of the full amount.
  • Buying and refilling a petrolcan takes petrol out of the station tank as well.
    Before, a can was an unlimited source of fuel that cost the station nothing.
  • The station zone radius replaces the global Config.FuelStationZoneDistance,
    and Config.Refill.price is now only a fallback for pumps that belong to no
    station.
  • The four fuel target options are built in a loop instead of being written out
    by hand eight times.
  • Server files are listed explicitly in fxmanifest.lua instead of being
    globbed, because the admin boot file has to load last.

Fixed

  • The custom fuel pumps from Config.CustomFuelStations only spawned when blips
    were enabled, which had nothing to do with each other.
  • The version checker crashed on any version carrying a pre-release tag: it
    split on . and ran tonumber over the pieces, so 1.2.0-beta.1 produced a
    comparison between nil and a number. Versions are now compared by SemVer
    rules, with a pre-release sorting before its own release.
  • Settings introduced by a later version never reached a server that was already
    seeded, so a new setting silently stayed on its config default.

Security

  • Every owner and admin action is checked against the station the player is
    actually STANDING at, resolved from the pump coordinates. A station id in a
    payload proves nothing.
  • The delivery flow is checked at every step, and the reported crash leak is
    clamped: the worst a manipulated client can do is deliver LESS than it paid
    for.
  • Handing out rank permissions and selling a station are owner-only, whatever a
    rank says, so a manager cannot promote themselves or sell the business out
    from under its owner.
  • Deposits take the money from the player before booking it, withdrawals book
    before paying out. Neither direction can create money if the other half fails.

Changed files

  • fxmanifest.lua, config.lua, translation.lua, .gitignore,
    .github/workflows/release.yml, .github/ISSUE_TEMPLATE/bug_report.yml
  • config.business.lua, config.stations.lua (new)
  • shared/perms.lua (new)
  • server/main.lua, server/functions.lua, server/versionchecker.lua
  • server/business/ (new): stations.lua, pricing.lua, stock.lua,
    account.lua, employees.lua, ownership.lua, payroll.lua, supply.lua,
    delivery.lua, maintenance.lua, owner_api.lua
  • server/admin/ (new): store.lua, permissions.lua, seed.lua, api.lua,
    command.lua, boot.lua
  • client/main.lua, client/target.lua, client/fuel.lua
  • client/business/ (new): sync.lua, dashboard.lua, delivery.lua
  • client/admin/ (new): main.lua, nui.lua
  • web/** (new NUI source), html/** (new build output)

v1.2.0-beta.1

v1.2.0-beta.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Aug 12:12
2770a17

Pre-release. This is the fuel business in full, but it has not been through a
season of live play yet. The mechanics work; the numbers behind them (prices,
wear rates, delivery pay) are first drafts and are meant to be tuned on your own
server. Run it on a test server before it touches a live one.
Fuel stations stop being blip coordinates and become businesses: they can be
bought, staffed, priced, supplied and worn out. Everything a player does with
one is checked against where they are actually standing, and the money and the
fuel are only ever moved by the server.

Requires

  • New dependency oxmysql. Nine tables are created and seeded automatically
    on first start, no SQL file to import.
  • Add this line to your server.cfg if it is not there already, so group
    permissions work (it covers every MSK script at once):
    add_ace resource.msk_core command.add_ace allow

Added

Stations as entities

  • All 30 map stations became named entities with a zone (center plus radius),
    their own stock and, once bought, an owner. The server resolves the station
    from the pump position, so no pump had to be re-mapped and this works on any
    map. Seed definitions live in config.stations.lua.
  • Blips are built from the station list and carry the station name, so renaming
    a station shows on the map right away.
    Economy
  • Stock per station per fuel type. An empty tank blocks that fuel type: the pump
    option greys out and the server refuses the sale.
  • Price per liter per station, either dynamic (rising as the tank empties and as
    demand goes up) or a fixed price, always clamped to the admin limits.
  • Market tick: the server-wide base price moves with total demand across all
    stations and eases back toward its anchor in quiet hours, which is what makes
    one busy station felt across the whole map.
  • Company account per station plus a full transaction log.
    Ownership
  • Buying a station at the pump, and selling it back for a configurable share of
    the purchase price plus whatever is on the company account.
  • Owner dashboard with eight tabs: overview, finance, prices, stock, supply,
    pumps, staff and ranks.
    Staff
  • Ranks per station with salary, delivery bonus and seven permissions. A freshly
    bought station starts with a manager and an employee rank.
  • Employees hired from the list of online players. An employee with at least one
    permission gets their own dashboard, showing only what their rank allows.
  • Salaries paid out of the company account every Config.Payroll.intervalMinutes
    to everyone online. A station that cannot cover its payroll skips it and tells
    the owner, instead of going into debt.
    Supply
  • NPC driver, unlocked once per station, for instant restocking at a surcharge,
    plus optional automatic restocking.
  • Delivery runs with three rigs (van 500 L, truck 1500 L, tanker 3000 L with a
    trailer and a bulk discount): pick up the rig, drive to a depot, load, come
    back. Crash damage spills up to 30 percent of the cargo.
  • Public delivery jobs at unowned stations, taken at the pump and paid per
    delivered liter out of the system. Enabled per station by the admin.
    Maintenance
  • Pumps wear out with use. A worn pump fuels slower, a broken one refuses to
    serve until it is repaired out of the company account. Pumps are never mapped:
    a pump enters the register the first time somebody fuels at it.
  • Mechanic on staff, unlocked once, repairs worn pumps automatically.
    Administration
  • In-game admin dashboard (/fueladmin, React + Vite + Tailwind, built into
    html/): station CRUD, stock and prices, market parameters, unowned-station
    settings, general settings with live theming, and a group permission matrix
    with nine rights.

Changed

  • msk_fuel:payFuelPrice carries the fuel type and the pump coordinates now.
    The server determines the station from them, charges the station price, takes
    the liters out of its tank and books the revenue. A tank that runs dry
    mid-refuel sells what is left instead of the full amount.
  • Buying and refilling a petrolcan takes petrol out of the station tank as well.
    Before, a can was an unlimited source of fuel that cost the station nothing.
  • The station zone radius replaces the global Config.FuelStationZoneDistance,
    and Config.Refill.price is now only a fallback for pumps that belong to no
    station.
  • The four fuel target options are built in a loop instead of being written out
    by hand eight times.
  • Server files are listed explicitly in fxmanifest.lua instead of being
    globbed, because the admin boot file has to load last.

Fixed

  • The custom fuel pumps from Config.CustomFuelStations only spawned when blips
    were enabled, which had nothing to do with each other.
  • The version checker crashed on any version carrying a pre-release tag: it
    split on . and ran tonumber over the pieces, so 1.2.0-beta.1 produced a
    comparison between nil and a number. Versions are now compared by SemVer
    rules, with a pre-release sorting before its own release.
  • Settings introduced by a later version never reached a server that was already
    seeded, so a new setting silently stayed on its config default.

Security

  • Every owner and admin action is checked against the station the player is
    actually STANDING at, resolved from the pump coordinates. A station id in a
    payload proves nothing.
  • The delivery flow is checked at every step, and the reported crash leak is
    clamped: the worst a manipulated client can do is deliver LESS than it paid
    for.
  • Handing out rank permissions and selling a station are owner-only, whatever a
    rank says, so a manager cannot promote themselves or sell the business out
    from under its owner.
  • Deposits take the money from the player before booking it, withdrawals book
    before paying out. Neither direction can create money if the other half fails.

Changed files

  • fxmanifest.lua, config.lua, translation.lua, .gitignore,
    .github/workflows/release.yml
  • config.business.lua, config.stations.lua (new)
  • shared/perms.lua (new)
  • server/main.lua, server/functions.lua, server/versionchecker.lua
  • server/business/ (new): stations.lua, pricing.lua, stock.lua,
    account.lua, employees.lua, ownership.lua, payroll.lua, supply.lua,
    delivery.lua, maintenance.lua, owner_api.lua
  • server/admin/ (new): store.lua, permissions.lua, seed.lua, api.lua,
    command.lua, boot.lua
  • client/main.lua, client/target.lua, client/fuel.lua
  • client/business/ (new): sync.lua, dashboard.lua, delivery.lua
  • client/admin/ (new): main.lua, nui.lua
  • web/** (new NUI source), html/** (new build output)

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 19 Jul 15:27

Security

  • Server-authoritative fuel: a StateBag change handler now tracks the authorized fuel value per vehicle and rolls back any illegitimate increase, so a client can no longer set arbitrary fuel levels.
  • GetVehicleFuel now falls back to 0.0 instead of 50.0, so a missing fuel state can no longer grant free fuel.
  • Added serverside rate limiting (500 ms) on the refillCan, payFuelPrice and updateFuelCan events.
  • Petrolcan buy and refill now verify serverside that the player is actually standing at a known fuel station, which blocks spoofed coordinates and remote triggering.

Added

  • Per vehicle type fueling distance via Config.MaxFuelingDistance (default, heli, plane) plus a serverside GetMaxFuelingDistance helper.
  • Serverside IsPlayerNearFuelStation check with new Config.MaxStationDistance and Config.FuelStationZoneDistance options.
  • Translation fallback: a missing key now falls back to English and then to the raw key instead of throwing an error.

Changed

  • Config.Debug now defaults to false.
  • Config.MaxFuelingDistance changed from a single number (100.0) to a per vehicle type table.
  • The refillCan event now sends the pump coordinates from the client so the server can verify the station.
  • Money handling in the petrolcan and refuel events is now unified on PayPrice.
  • Relicensed the resource to LGPL-3.0-or-later.

Fixed

  • Adjusted the wrong fuel engine failure threshold (now triggers below 500 engine health).
  • Clean up the authorized fuel and rate limit tables on entityRemoved and playerDropped.

Changed files

  • client/fuel.lua
  • client/functions.lua
  • client/main.lua
  • config.lua
  • server/functions.lua
  • server/main.lua
  • server/versionchecker.lua
  • translation.lua
  • fxmanifest.lua
  • LICENSE, GPL-3.0.txt, .gitignore

Update v1.1.0

Choose a tag to compare

@Musiker15 Musiker15 released this 04 Jun 15:27

Update v1.1.0

Fix security issues and bugs in fuel system

  • Server now calculates fuel/petrolcan prices serverside instead of trusting client-sent values (prevents free refueling exploit)
  • Validate added fuel against current/max fuel and petrolcan durability
  • Fix dead "tank full" check (fuelAmount >= maxFuel)
  • Translate the English locale block
  • Add missing translation key petrolcan_not_equipped
  • IsVehicle* now return proper booleans instead of array indices
  • Apply Config.DefaultFuelType fallback for unlisted vehicles
  • Guard against nil compare in SetEngineFailure

Harden refueling against exploits and fix consumption bugs

  • Add serverside proximity check (IsPlayerNearVehicle) to payFuelPrice and updateFuelCan so vehicles can only be fueled when the player is actually near them (prevents spoofed remote/foreign vehicle fueling)
  • Split fuel consumption config: per-vehicle fPetrolConsumptionRate now uses Config.PetrolConsumptionRate (2.0) instead of the global SetFuelConsumptionRateMultiplier value
  • Validate and clamp replicated fuel/maxFuel statebag values clientside
  • Stop the fueling loop correctly when the player runs out of money
  • Add re-entry guard to CalculateVehicleFuel to prevent duplicate consumption loops on the same vehicle
  • Round petrolcan durability to avoid float drift
  • Add Config.PetrolConsumptionRate and Config.MaxFuelingDistance

Update v1.0.0

Choose a tag to compare

@Musiker15 Musiker15 released this 19 Oct 08:26