Developers
The meth crafting server and client exports, the open functions you can change in client/functions.lua and server/functions.lua, and the record shapes they return.
Every export is called on exports.lation_meth. Server exports that act on a player take their server id as source; client exports work on the local player and ask the server, so call them from a thread. A player's identifier is the ESX identifier on ESX and the citizenid on Qbox and QBCore. A lab's id is its index in Config.Warehouses.
Server exports
| Export | Returns |
|---|---|
GetPlayerData(source, type?) | A player's record, or one field of it |
AddPlayerData(source, dataType, amount) | Nothing |
GetTableData(id) | A placed table, or nil |
GetWarehouseData(id) | An owned lab, or nil |
GetPlayerWarehouses(source) | The labs a player owns |
IsWarehouseOwner(source, id) | boolean |
IsAuthorizedUser(source, id) | boolean |
IsWarehouseAvailable(id) | boolean |
IsUpgradeActive(id) | false, or the upgrade on its way |
GetPlayersInWarehouse(id) | The server ids inside, or nil |
GetPlayerData
Server export
exports.lation_meth:GetPlayerData(source, type)Parameters
sourcenumber- The player's server id
typestringoptionaldefaultnil- One field:
level,exp,total_produced,total_supply_runs,inside. The whole record when left out.
Returns
table | any | nil- The record (below), or the value of
type.nilwhen the player isn't loaded in your framework.
The first time a player is looked up, a record is created at level 1 with a random recipe. The record is the cached one, so treat it as read-only and change it with AddPlayerData.
{
identifier = 'ABC12345',
ammonia = 63, -- the player's recipe for 100% purity
iodine = 18,
acetone = 91,
inside = 0, -- the lab they're in, 0 for none
level = 3,
exp = 1250, -- total XP
total_produced = 42, -- bags of meth produced
total_supply_runs = 12,
}local level = exports.lation_meth:GetPlayerData(source, 'level')
if level and level >= 5 then
-- unlock something
endAddPlayerData
Server export
exports.lation_meth:AddPlayerData(source, dataType, amount)Parameters
sourcenumber- The player's server id
dataTypestringexp,total_producedortotal_supply_runsamountnumber- How much to add. Anything 0 or below does nothing.
Returns
- Nothing
Adding exp moves the player up past every level they cross, with no notice. Nothing is written straight away: the record is saved when the player leaves, when the resource stops and when txAdmin shuts the server down.
exports.lation_meth:AddPlayerData(source, 'exp', 250)GetTableData
Shared export
local data = exports.lation_meth:GetTableData(id)Parameters
idnumber- The table's id
Returns
table | nil- The table (below)
The same export exists on the client, where it asks the server.
{
id = 1873420117,
x = 1391.82, y = 3605.11, z = 38.94,
heading = 112.5,
stage = 2, -- steps done: 0 to 5
heating = true, -- step 3 is running
cooling = false, -- step 5 is running
remaining = 2410000, -- ms left on the running step
purity = 88,
bucket = 0, -- routing bucket it was placed in
owner = 'ABC12345',
}GetWarehouseData
Shared export
local lab = exports.lation_meth:GetWarehouseData(id)Parameters
idnumber- The lab's id
Returns
table | nil- The lab (below), or
nilwhen nobody owns it
The same export exists on the client, where it asks the server.
{
id = 2,
owner = 'ABC12345',
style = 'basic', -- 'empty', 'basic' or 'upgrade'
security = 'upgrade', -- 'none' or 'upgrade'
pin = 4821, -- the stash passcode, or nil
locked = 'locked', -- 'locked' or 'unlocked'
remaining = 0, -- an upgrade's minutes as last loaded; use IsUpgradeActive
upgrade = '', -- an upgrade's type as last loaded; use IsUpgradeActive
ammonia = 40, iodine = 75, acetone = 90, -- tank levels
stage = 3, -- 0 idle, 1 to 5 cooking
purity = 92,
duration = 1260000, -- ms left in this stage
efficiency = 11, -- of the player who powered it on
inputs = { ammonia = 63, iodine = 18, acetone = 91, temp = 192 },
users = { { identifier = 'DEF67890', name = 'Jane Doe' } },
}GetPlayerWarehouses
Server export
local labs = exports.lation_meth:GetPlayerWarehouses(source)Parameters
sourcenumber- The player's server id
Returns
table- A list of the labs they own, each shaped like
GetWarehouseData's
IsWarehouseOwner
Shared export
local owner = exports.lation_meth:IsWarehouseOwner(source, id)Parameters
sourcenumber- The player's server id. Left out on the client:
IsWarehouseOwner(id). idnumber- The lab's id
Returns
boolean
IsAuthorizedUser
Shared export
local authorized = exports.lation_meth:IsAuthorizedUser(source, id)Parameters
sourcenumber- The player's server id. Left out on the client:
IsAuthorizedUser(id). idnumber- The lab's id
Returns
booleantruewhen the owner has added the player under Authorized Users
IsWarehouseAvailable
Server export
local forSale = exports.lation_meth:IsWarehouseAvailable(id)Parameters
idnumber- The lab's id
Returns
booleantruewhen nobody owns it
IsUpgradeActive
Server export
local pending = exports.lation_meth:IsUpgradeActive(id)Parameters
idnumber- The lab's id
Returns
false | tablefalse, or the upgrade on its way:{ owner, id, style, security, remaining, upgradeType }, withremainingin minutes andupgradeTypeone oforderEquipment,upgradeEquipment,orderSecurity
GetPlayersInWarehouse
Server export
local players = exports.lation_meth:GetPlayersInWarehouse(id)Parameters
idnumber- The lab's id
Returns
table | nil- A list of server ids, or
nilwhen nobody has been inside
for _, playerId in ipairs(exports.lation_meth:GetPlayersInWarehouse(2) or {}) do
TriggerClientEvent('chat:addMessage', playerId, { args = { 'The lights go out.' } })
endClient exports
| Export | Returns |
|---|---|
GetPlayerData(type?) | The local player's record, or one field of it |
IsInsideWarehouse() | boolean, number? |
IsViewingCamera() | boolean |
WarehouseShop() | Nothing |
GetTableData(id), GetWarehouseData(id), IsWarehouseOwner(id), IsAuthorizedUser(id) | As on the server, for the local player |
GetPlayerData (client)
Client export
exports.lation_meth:GetPlayerData(type)Parameters
typestringoptionaldefaultnil- One field; the whole record when left out
Returns
table | any- The local player's record, shaped like the server export's, or the value of
type
CreateThread(function()
local data = exports.lation_meth:GetPlayerData()
print(('Level %s, %s bags produced'):format(data.level, data.total_produced))
end)IsInsideWarehouse
Client export
local inside, id = exports.lation_meth:IsInsideWarehouse()Returns
boolean, number- Whether the local player is in a lab, and which one (
nilwhen not)
IsViewingCamera
Client export
local watching = exports.lation_meth:IsViewingCamera()Returns
booleantruewhile the local player watches a lab's front door camera
Useful to hide a HUD or block other scripts while the camera is up.
WarehouseShop
Client export
exports.lation_meth:WarehouseShop()Returns
- Nothing
Opens Warehouse Availability wherever the player is, with the level check Benjamin makes. Use it with shop.enable off to sell labs from a laptop, a phone app or another ped.
RegisterCommand('labs', function()
exports.lation_meth:WarehouseShop()
end, false)Client functions
client/functions.lua ships open. These functions are called by the script; change their bodies to add your own checks.
| Function | Called | Return |
|---|---|---|
CanObtainTable() | Before James hands out a table | false to refuse |
CanCookOnTable(id) | Before the table menu opens | false to refuse |
CanStartSupplyRun() | Before William starts runs | false to refuse |
CanEnterWarehouse(id) | Before a player enters a lab | false to refuse |
EnteredWarehouse(id), ExitedWarehouse(id) | After a player enters or leaves a lab | |
StartedCameraView(), StoppedCameraView() | As the front door camera opens and closes. By default they lock and unlock the inventory. | |
StartPlayingAnim(), StopPlayingAnim() | Around the long lab scenes. By default they lock and unlock the inventory. | |
CanUseMeth() | Before a bag is used. By default it refuses a dead player, with an example for a handcuffs check. | false to refuse |
-- Police can't cook
function CanCookOnTable(id)
local job = GetPlayerData().job
return not job or job.name ~= 'police'
endThe same file holds the adapters for every system picked in Config.Setup, each with a custom slot: ShowNotification, ShowTextUI and HideTextUI, ProgressBar, RegisterMenu and ShowMenu, ShowAlert, ShowInput, SkillCheck, PoliceDispatch, and the target functions. OpenStash opens a lab's stash on each inventory.
Server functions
server/functions.lua ships open too.
| Function | Called | Return |
|---|---|---|
CanPlaceTable(source) | Before a table is placed. Holds the table limit, the police requirement and the blocked areas. | false to refuse |
CanBuyWarehouse(warehouseId) | Before a lab is bought | false to refuse |
It also holds RegisterStash and ClearStash (a lab's stashes on each inventory), GetMetadata and SetMetadata (the chemicals' fill level and the meth's purity), the ox_inventory hook that pours two bottles together, what using a bag of meth does, and how logs reach Fivemanage, Fivemerr and Discord.
Open files
| Path | What it's for |
|---|---|
bridge/client.lua, bridge/server.lua | Framework and inventory support, with slots for a custom framework or inventory |
client/functions.lua | The client functions and UI adapters above |
server/functions.lua | The server functions above |
config.lua | Every option, see configuration |
logs.lua | Logging |
strings.lua | Every line of text |
strains.lua | The 100 strain names |
Still stuck? Ask in our Discord: the people who write the scripts answer.
Last updated