How Integrations Work#
Lumberjack Job talks to your framework and your inventory through small bridge files, and asks every other resource whether it is running before it uses it. The framework and the inventory are detected; the target is set by hand; the rest is used when present.
Layer | Supported | Without it |
|---|---|---|
Framework |
| Required. Another core needs its own bridge — see the end of this page. |
Inventory |
| Required — wood, planks and axes are items. |
Target |
| A keypress near the foreman and the stumps, with a floating prompt. |
Clothing |
| Turn |
Party |
| Crews are built by invitation from the panel. |
3D prompts |
| The script draws its own floating text. |
Payouts |
| Mission pay goes straight to the player's cash. |
Quests |
| No inventory quests; the job's own achievements still work. |
Notifications | Built in, or any resource through one function | — |
Logs | Discord webhooks | Off by default. |
Database |
| Required. |
Every optional integration stands down quietly. A missing resource switches its feature off rather than throwing an error — so when something does not appear, first check that the resource is started, and started before
qs-lumberjack.
Frameworks#
The framework is read from the resources running when the script loads. Qbox is served by the QBCore bridge through its own compatibility layer.
-- config/config.lua
local frameworks = {
['es_extended'] = 'esx',
['qb-core'] = 'qb',
['qbx_core'] = 'qb'
}Area | ESX | QBCore / Qbox |
|---|---|---|
Player key |
|
|
Money | The |
|
The job | Registered in the database automatically | Added to |
Usable axes |
|
|
The job is always read from the framework, never from the player's client. Losing the job in the middle of a mission abandons it, and a player who no longer holds it is not paid for it.
Inventories#
Every item that goes in or out is routed to the inventory that is actually running, checked in this order:
ox_inventory— also the only one that keeps each axe's durability in its own metadata.qs-inventory— counted and changed through its own exports, so ESX servers on qs-inventory receive the items in the bag the player actually sees.The framework's own inventory —
qb-inventorythrough QBCore, or the default ESX inventory.
If both ox_inventory and qs-inventory are running, Config.InventoryAxeScript ("ox" or "qs") breaks the tie; it is not used for anything else. Config.InventoryAxe decides whether axes are items at all — see Inventory Items.
Before an item is handed over, the script asks the inventory whether that item exists. A missing item and a full bag are told apart: the first names the item to the player and the console, the second says the inventory is full.
Target and Prompts#
The default. Standing next to the foreman or a stump shows a hint, and Config.Keys.InteractKey (E) interacts. Config.Drawtext adds a floating prompt, drawn by qs-textui when it is running and by the script otherwise.
Config.Target = false
Config.Drawtext = true
Config.Keys = { InteractKey = "E" }The foreman gets a Start Working option and every stump a Use chopping block option, both within 4 metres.
Config.Target = true
Config.TargetScript = "ox" -- or "qb"The Work Outfit#
With Config.Clothing = true, starting a mission dresses the player in the outfit at the top of config/clothing.lua, and finishing or abandoning it puts their own clothes back. There is one outfit for male characters and one for female; comment out a line to leave that piece alone.
male = {
["arms"] = 65,
["tshirt_1"] = 59, ["tshirt_2"] = 1,
["torso_1"] = 5, ["torso_2"] = 2,
["pants_1"] = 9, ["pants_2"] = 4,
["shoes_1"] = 0, ["shoes_2"] = 0,
["helmet_1"] = 145, ["helmet_2"] = 1,
},Framework | Dressed with | Restored with |
|---|---|---|
ESX |
| The skin saved by |
QBCore |
|
|
Clothing resources that answer the same events as qb-clothing — illenium-appearance, for example — work the same way. On qs-inventory, Config.QuasarInventory = true locks the inventory's clothing slots for the moment the outfit changes.
Quasar Add-ons#
qs-party — crews from your party
When qs-party is running, opening the foreman's panel fills the crew with the members of the player's party, led by the party leader. A party larger than Config.MaxPartyMembers is refused with a message. Members still have to hold the job and meet the mission's level.
qs-job-management — where mission pay goes
When qs-job-management is running, mission pay is handed to it for the lumberjack job instead of going straight into the player's cash. Leaderboard earnings count it the same either way.
qs-textui — floating prompts
When qs-textui is running and Config.Drawtext is on, the prompts at the foreman and the stumps are drawn by it, matching the rest of your Quasar resources.
qs-inventory — quests
With Config.QuasarInventoryQuests = true, every player who loads in gets four quests in qs-inventory's quest system, and the job reports progress to them:
Quest | Reward | Progresses when |
|---|---|---|
Lumberjack Progress · | 300 | +5 per job level gained |
Lumberjack Crew · | 200 | Someone accepts your crew invitation |
Chopping trees · | 200 | +1 per piece of wood collected |
Finish lumberjack quests · | 100 | +20 per mission completed |
Leave it off if you do not run qs-inventory, or do not want its quests. It is a different switch from Config.QuasarInventory, which only handles the outfit change.
Notifications#
With Config.DefaultNotifications = true the script shows its own notifications, coloured by type with an icon and a sound. Set it to false and every message goes to SendTextMessage in config/config.lua instead, where you call your own resource:
function SendTextMessage(msg, type) -- type: 'info', 'error' or 'success'
if type == 'info' then
exports['okokNotify']:Alert('Lumberjack', msg, 5000, 'info')
end
if type == 'error' then
exports['okokNotify']:Alert('Lumberjack', msg, 5000, 'error')
end
if type == 'success' then
exports['okokNotify']:Alert('Lumberjack', msg, 5000, 'success')
end
endThe on-screen key hints and help lines are part of the interface and are shown either way.
Discord Logs#
Off by default. Paste a webhook into Url, set Enabled to true, and choose the events. Each event takes true (the shared URL), false (not sent) or a URL of its own — so money can go to a staff channel while missions go somewhere public.
Config.Webhooks = {
Enabled = true,
Url = 'https://discord.com/api/webhooks/...',
Name = 'qs-lumberjack',
Avatar = '',
Timestamp = true,
Events = {
MissionStarted = true,
MissionFinished = true,
MissionAbandoned = true,
MoneyPaid = 'https://discord.com/api/webhooks/...', -- a channel of its own
ExperienceGiven = false,
RichGrove = true,
Tournament = true,
ConfigChanged = true,
},
}Event | Sent when |
|---|---|
| A crew takes a mission — what it asks for, the crew, the pay. |
| A mission completes, with each member's share. |
| A member leaves from the panel or disconnects. |
| Mission pay and achievement rewards. |
| Every grant of experience, with the level before and after. Busy — one per tree. |
| A rich grove opens, with the wood and its length. |
| A tournament finishes, with both winners and the entrant count. |
| A setting is saved or reset in the admin panel, with who did it. |
Languages#
Eleven translations ship in config/translations.lua: English (en), Italian (it), Spanish (es), French (fr), Portuguese (pt), German (de), Russian (ru), Turkish (tr), Dutch (nl), Simplified Chinese (cn) and Traditional Chinese (zh-tw).
Config.Language = "es"To add a language, copy the whole ['en'] block under a new code, translate the text between the quotes, and set Config.Language to it — it also appears in the admin panel's language list. The currency symbol is the CURRENCY_TYPE line of each language.
Bridging Your Own Framework#
The framework bridges are open files: server/framework/esx.lua, server/framework/qb.lua, server/framework/inventory.lua and their client twins in client/framework/. Nothing else in the resource refers to a framework by name.
Copy the closest bridge
Copy
esx.luaorqb.luain both folders and change the guard on the first line to your framework's name:lua if Config.Framework ~= "mycore" then return endFill in the server functions
Each is a few lines calling your core:
Function
Returns
GetPlayeridentifier(src)The player's permanent key, the same one your players table uses.
GetPlayerId(src)·GetPlayerFromIdentifier(id)The player object, and the server id for a key (nil when offline).
GetPlayerJobName(src)The job the player holds right now.
GetMoney·AddMoney·RemoveMoneyCash in and out.
GetItemCountFromInventory·ItemExistsHow many of an item a player holds, and whether the item is registered.
AddInventoryItem·RemoveInventoryItemtrue when it happened;
falseplus'full'or'unknown_item'when it was refused.RegisterUsableItems()Makes every axe usable, sending
qs-lumberjack:toggleAxeto the player.GetPlayers()Every loaded player's server id.
Fill in the client side
The client bridge sets
PlayerDataandCanInteract(whether the player holds a lumberjack job), rebuilds the foreman and blips when a character loads, and callsUpdateTargetOptions()when the job changes. The outfit lives inToggleJobClothes()inconfig/clothing.lua.Register it for detection
Add your core to the
frameworkstable at the top ofconfig/config.lua:lua local frameworks = { ['es_extended'] = 'esx', ['qb-core'] = 'qb', ['qbx_core'] = 'qb', ['my-core'] = 'mycore', }
A different inventory is added in server/framework/inventory.lua the same way: detect it in DetectInventory, then answer InventoryCount, InventoryAdd, InventoryRemove and InventoryKnows with its exports.



