Интеграция на Собствен Фреймуърк
This is a guide designed to lead you through the successful framework integration process of the script. Please follow the steps and do not deviate from the instructions.
Custom
Don't run QBCore, Qbox, or ESX? inn-laundry never calls a framework's own API directly — every part of the script only ever calls six functions on a Framework table, defined once per framework under bridge/framework/. Implementing a custom framework means filling in those six functions yourself.
Most frameworks expose their functionality via exports['your-framework']:FunctionName(...) — Qbox (qbx_core) works exactly this way (see the reference implementation below). Some, like QBCore and ESX, instead expose a single "core object" via one export (GetCoreObject()/getSharedObject()) and put everything else as methods on that object — check your framework's own docs to see which pattern it uses.
Open the custom framework template
Open inn-laundry/bridge/framework/custom.lua. It already contains every function signature you need, each currently just raising an error so you can't accidentally ship it unfinished.
Implement each function
| Function | Returns | Purpose |
|---|---|---|
Framework.GetPlayer(src) | opaque player object, or nil if offline | Looked up once and reused — the shape of this object is entirely up to you, nothing outside your own bridge file reads it directly. |
Framework.GetIdentifier(src) | string identifier, or nil | Stored as the owner on zones/machines — must be stable across sessions (e.g. a license or citizenid), not the temporary server id. |
Framework.GetJob(src) | { name, grade, isboss }, or nil | isboss marks the player as the automatic owner of a job-locked zone on that job. |
Framework.AddMoney(src, amount, reason, moneyType) | boolean success | moneyType is 'cash' or 'bank', falling back to Config.Payout.moneyType when not given. |
Framework.RemoveMoney(src, amount, reason, moneyType) | boolean success | Must fail (return false) and remove nothing if the player doesn't have enough. |
Framework.GetPlayersOnJob(job) | number[] of source ids | Used to find every online player to notify for a job (e.g. police during a raid). |
Framework.HasPermission(src) also exists on the Framework table, but it's implemented once in bridge/framework/init.lua using FiveM's native ace permissions (IsPlayerAceAllowed) — it's the same for every framework, so you don't need to (and shouldn't) implement it yourself.
Point the config at your bridge
Open config/config.lua and set:
Config.Framework = 'custom'
Reference implementation
Every function above is implemented for Qbox in bridge/framework/qbox.lua — a clean example of the pure-export pattern, since qbx_core exposes everything as a direct export call with no core object to fetch first:
function Framework.GetPlayer(src)
return exports.qbx_core:GetPlayer(src)
end
function Framework.GetIdentifier(src)
local Player = exports.qbx_core:GetPlayer(src)
return Player and Player.PlayerData.citizenid or nil
end
function Framework.GetJob(src)
local Player = exports.qbx_core:GetPlayer(src)
if not Player then return nil end
return {
name = Player.PlayerData.job.name,
grade = Player.PlayerData.job.grade.level,
isboss = Player.PlayerData.job.isboss or false,
}
end
function Framework.AddMoney(src, amount, reason, moneyType)
return exports.qbx_core:AddMoney(src, moneyType or Config.Payout.moneyType, amount, reason or 'inn-laundry')
end
If your framework instead uses the "one core object" pattern (QBCore and ESX both do), fetch it once at the top of your file and call its methods from there — bridge/framework/qb.lua:
local QBCore = exports['qb-core']:GetCoreObject()
function Framework.GetPlayer(src)
return QBCore.Functions.GetPlayer(src)
end
function Framework.AddMoney(src, amount, reason, moneyType)
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return false end
return Player.Functions.AddMoney(moneyType or Config.Payout.moneyType, amount, reason or 'inn-laundry')
end
ESX has no built-in "boss" concept the way QBCore/Qbox do. If your custom framework is ESX-like, don't hardcode isboss = false — inn-laundry falls back to Config.ESXBossGrades (in config/config.lua) to decide the automatic owner grade per job in that case. Match that same pattern in your custom bridge, or every job-locked zone will start with no automatic owner at all.
