framework.lua
-- ============================================================
-- EXIT FRAGMENTATION β Framework Bridge (shared/framework.lua)
-- Desteklenen: QBCore | QBox | ESX | Standalone
-- ============================================================
-- NOT: Bu dosya hem client hem server tarafΔ±nda Γ§alΔ±ΕΔ±r.
-- IsDuplicityVersion() β true = sunucu, false = istemci
ExitFramework = {}
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Framework AlgΔ±lama
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
local _fw = nil -- Γnbellek
function ExitFramework.GetType()
if _fw then return _fw end
-- Γncelik sΔ±rasΔ±: Config varsa ΓΆnce ona bak
if Config and Config.Framework and Config.Framework ~= 'auto' then
_fw = Config.Framework
return _fw
end
-- Otomatik algΔ±lama
if GetResourceState('qb-core') == 'started' then
_fw = 'qb'
elseif GetResourceState('qbx_core') == 'started' then
_fw = 'qbox'
elseif GetResourceState('es_extended') == 'started' then
_fw = 'esx'
else
_fw = 'standalone'
end
return _fw
end
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Core Object (Lazy-loaded)
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
local _core = nil
function ExitFramework.GetCore()
if _core then return _core end
local fw = ExitFramework.GetType()
local ok, result = false, nil
if fw == 'qb' then
ok, result = pcall(function() return exports['qb-core']:GetCoreObject() end)
elseif fw == 'qbox' then
ok, result = pcall(function() return exports['qbx_core']:GetCoreObject() end)
elseif fw == 'esx' then
ok, result = pcall(function() return exports['es_extended']:getSharedObject() end)
else
ok, result = true, {}
end
if ok and result then
_core = result
else
-- Hata logla ve boΕ fallback dΓΆndΓΌr (crash ΓΆnle)
print(string.format('[EXIT-FRAMEWORK] UYARI: "%s" framework core nesnesi alΔ±namadΔ±!', fw))
print('[EXIT-FRAMEWORK] Config.Framework ayarΔ±nΔ± kontrol edin.')
_core = { Functions = {} } -- Minimum boΕ tablo
end
return _core
end
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- SERVER TARAFI YARDIMCI FONKSΔ°YONLARI
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
if IsDuplicityVersion() then
-- βββ Δ°Γ§ yardΔ±mcΔ±: ESX/Standalone player'Δ± QB formatΔ±na sar ββ
local function WrapESXPlayer(raw, fw)
if not raw then return nil end
-- QBCore/QBox zaten QB formatΔ±nda, dokunma
if fw == 'qb' or fw == 'qbox' then return raw end
-- ESX β QB-uyumlu wrapper
if fw == 'esx' then
local identifier = raw.identifier or tostring(raw.source or 0)
local name = (type(raw.getName) == 'function' and raw.getName()) or ''
local firstName = name:match('^(%S+)') or name
local lastName = name:match('%s(.+)$') or ''
local job = raw.job or {}
return {
PlayerData = {
citizenid = identifier,
source = raw.source,
charinfo = { firstname = firstName, lastname = lastName },
job = {
name = job.name or '',
grade = { level = job.grade or 0 },
onduty = true
},
money = { cash = 0, bank = 0 }
},
Functions = {
GetItemByName = function(item)
local ok, inv = pcall(function() return raw.getInventoryItem(item) end)
if ok and inv and (inv.count or 0) > 0 then
return { name = item, amount = inv.count }
end
return nil
end,
AddItem = function(item, amount)
pcall(function() raw.addInventoryItem(item, amount or 1) end)
return true
end,
RemoveItem = function(item, amount)
pcall(function() raw.removeInventoryItem(item, amount or 1) end)
return true
end,
AddMoney = function(account, amount)
local acc = account == 'cash' and 'money' or account
pcall(function() raw.addAccountMoney(acc, amount) end)
end,
RemoveMoney = function(account, amount)
local acc = account == 'cash' and 'money' or account
pcall(function() raw.removeAccountMoney(acc, amount) end)
return true
end,
HasPermission = function(level)
local ok2, g = pcall(function() return raw.getGroup() end)
return ok2 and g == 'admin'
end,
}
}
end
-- Standalone minimum
local src = raw.source or 0
return {
PlayerData = {
citizenid = tostring(src),
source = src,
charinfo = { firstname = 'Unknown', lastname = '' },
job = { name = '', grade = { level = 0 }, onduty = false },
money = { cash = 0, bank = 0 }
},
Functions = {
GetItemByName = function() return nil end,
AddItem = function() return false end,
RemoveItem = function() return false end,
AddMoney = function() end,
RemoveMoney = function() return false end,
HasPermission = function() return false end,
}
}
end
--- Oyuncu nesnesini QB-uyumlu wrapper olarak dΓΆndΓΌrΓΌr
function ExitFramework.GetPlayer(src)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
local raw = nil
if fw == 'qb' or fw == 'qbox' then
raw = core.Functions and core.Functions.GetPlayer(src)
elseif fw == 'esx' then
if core and type(core.GetPlayerFromId) == 'function' then
raw = core.GetPlayerFromId(src)
if raw then raw.source = src end
end
else
raw = { source = src }
end
return WrapESXPlayer(raw, fw)
end
--- CitizenID / identifier al
function ExitFramework.GetIdentifier(src)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return nil end
if fw == 'qb' or fw == 'qbox' then
return player.PlayerData.citizenid
elseif fw == 'esx' then
return player.identifier
else
return tostring(src)
end
end
--- Karakter adΔ± al
function ExitFramework.GetPlayerName(src)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return GetPlayerName(src) end
if fw == 'qb' or fw == 'qbox' then
local ci = player.PlayerData.charinfo
return (ci.firstname or '') .. ' ' .. (ci.lastname or '')
elseif fw == 'esx' then
return player.getName()
else
return GetPlayerName(src)
end
end
--- Item ekle (dΓΆnem dΓΆnemlik callback'siz basit versiyon)
function ExitFramework.AddItem(src, item, amount)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return false end
amount = amount or 1
if fw == 'qb' or fw == 'qbox' then
return player.Functions.AddItem(item, amount)
elseif fw == 'esx' then
player.addInventoryItem(item, amount)
return true
elseif GetResourceState('ox_inventory') == 'started' then
return exports.ox_inventory:AddItem(src, item, amount)
else
print('[EXIT] Standalone: AddItem Γ§aΔrΔ±ldΔ± ama envanter sistemi bulunamadΔ±.')
return false
end
end
--- Item Γ§Δ±kar
function ExitFramework.RemoveItem(src, item, amount)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return false end
amount = amount or 1
if fw == 'qb' or fw == 'qbox' then
return player.Functions.RemoveItem(item, amount)
elseif fw == 'esx' then
player.removeInventoryItem(item, amount)
return true
elseif GetResourceState('ox_inventory') == 'started' then
return exports.ox_inventory:RemoveItem(src, item, amount)
else
return false
end
end
--- Item kontrolΓΌ
function ExitFramework.GetItem(src, item)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return nil end
if fw == 'qb' or fw == 'qbox' then
return player.Functions.GetItemByName(item)
elseif fw == 'esx' then
local inv = player.getInventoryItem(item)
return inv and {name = item, amount = inv.count} or nil
elseif GetResourceState('ox_inventory') == 'started' then
local count = exports.ox_inventory:Search(src, 'count', item)
return count and count > 0 and {name = item, amount = count} or nil
else
return nil
end
end
--- Para ver
function ExitFramework.AddMoney(src, account, amount)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return end
if fw == 'qb' or fw == 'qbox' then
player.Functions.AddMoney(account, amount)
elseif fw == 'esx' then
-- ESX account mapping: 'cash' β 'money', 'bank' β 'bank'
local esxAccount = account == 'cash' and 'money' or account
player.addAccountMoney(esxAccount, amount)
else
print('[EXIT] Standalone: AddMoney Γ§aΔrΔ±ldΔ±. Para: ' .. amount)
end
end
--- Para al
function ExitFramework.RemoveMoney(src, account, amount)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return false end
if fw == 'qb' or fw == 'qbox' then
return player.Functions.RemoveMoney(account, amount)
elseif fw == 'esx' then
local esxAccount = account == 'cash' and 'money' or account
player.removeAccountMoney(esxAccount, amount)
return true
else
return false
end
end
--- Meslek/iΕ kontrolΓΌ
function ExitFramework.GetJob(src)
local fw = ExitFramework.GetType()
local player = ExitFramework.GetPlayer(src)
if not player then return {name='', duty=false} end
if fw == 'qb' or fw == 'qbox' then
return {
name = player.PlayerData.job.name,
grade = player.PlayerData.job.grade.level,
duty = player.PlayerData.job.onduty
}
elseif fw == 'esx' then
return {
name = player.job.name,
grade = player.job.grade,
duty = true -- ESX duty sistemi farklΔ±, true varsay
}
else
return {name='', grade=0, duty=false}
end
end
--- Sunucu tarafΔ± bildirim (client event ΓΌzerinden)
function ExitFramework.ServerNotify(src, msg, ntype, duration)
TriggerClientEvent('exit-fragmentation:client:showToast', src, msg, ntype, duration)
end
--- TΓΌm polisleri say
function ExitFramework.CountPolice()
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
local count = 0
if fw == 'qb' or fw == 'qbox' then
local players = core.Functions.GetPlayers()
for _, v in pairs(players) do
local p = core.Functions.GetPlayer(v)
if p and p.PlayerData.job.name == 'police' and p.PlayerData.job.onduty then
count = count + 1
end
end
elseif fw == 'esx' then
local players = core.GetPlayers()
for _, v in pairs(players) do
local p = core.GetPlayerFromId(v)
if p and p.job.name == 'police' then
count = count + 1
end
end
else
count = 0
end
return count
end
--- Δ°zin/yetki kontrolΓΌ
function ExitFramework.HasPermission(src, level)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
return core.Functions.HasPermission(src, level)
elseif fw == 'esx' then
local player = ExitFramework.GetPlayer(src)
if level == 'admin' or level == 'god' then
return player and player.getGroup() == 'admin'
end
return false
else
return false
end
end
--- TΓΌm oyuncular
function ExitFramework.GetPlayers()
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
return core.Functions.GetPlayers()
elseif fw == 'esx' then
return core.GetPlayers()
else
return GetPlayers()
end
end
--- AraΓ§ plakasΔ± al (server'da mevcut deΔil, client-side)
function ExitFramework.CleanPlate(plate)
-- TutarlΔ± format (boΕluk trim)
if plate then
return plate:gsub('%s+', ''):upper()
end
return ''
end
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- CLIENT TARAFI YARDIMCI FONKSΔ°YONLARI
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
else
--- Oyuncu verisini al
function ExitFramework.GetPlayerData()
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
return core.Functions.GetPlayerData()
elseif fw == 'esx' then
local data = core.GetPlayerData()
-- QB formatΔ±na normalize et
return {
citizenid = data and data.identifier or '',
charinfo = {
firstname = data and data.firstName or '',
lastname = data and data.lastName or ''
},
job = {
name = data and data.job and data.job.name or '',
onduty = true
},
items = data and data.inventory or {}
}
else
return {}
end
end
--- Δ°tem kontrolΓΌ (client side)
function ExitFramework.HasItem(item)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
local pData = core.Functions.GetPlayerData()
if pData and pData.items then
for _, v in pairs(pData.items) do
if v.name == item and v.amount > 0 then return true end
end
end
return false
elseif fw == 'esx' then
-- ESX client-side item check
local pData = core.GetPlayerData()
if pData and pData.inventory then
for _, v in pairs(pData.inventory) do
if v.name == item and v.count > 0 then return true end
end
end
return false
elseif GetResourceState('ox_inventory') == 'started' then
return (exports.ox_inventory:Search('count', item) or 0) > 0
else
return false
end
end
--- AraΓ§ plakasΔ± al (client side)
function ExitFramework.GetPlate(veh)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
return core.Functions.GetPlate(veh)
elseif fw == 'esx' then
return GetVehicleNumberPlateText(veh):gsub('%s+', ''):upper()
else
return GetVehicleNumberPlateText(veh):gsub('%s+', ''):upper()
end
end
--- AraΓ§ spawn et
function ExitFramework.SpawnVehicle(model, cb, coords, warp)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
core.Functions.SpawnVehicle(model, cb, coords, warp)
elseif fw == 'esx' then
-- ESX native spawn
local hash = type(model) == 'string' and GetHashKey(model) or model
RequestModel(hash)
local t = 0
while not HasModelLoaded(hash) and t < 200 do Wait(10); t = t + 1 end
if HasModelLoaded(hash) then
local veh = CreateVehicle(hash, coords.x, coords.y, coords.z, coords.w or 0.0, true, false)
SetModelAsNoLongerNeeded(hash)
if warp then
SetPedIntoVehicle(PlayerPedId(), veh, -1)
end
if cb then cb(veh) end
end
else
-- Standalone basic spawn
local hash = type(model) == 'string' and GetHashKey(model) or model
RequestModel(hash)
local t = 0
while not HasModelLoaded(hash) and t < 200 do Wait(10); t = t + 1 end
local veh = CreateVehicle(hash, coords.x, coords.y, coords.z, coords.w or 0.0, true, false)
SetModelAsNoLongerNeeded(hash)
if cb then cb(veh) end
end
end
--- AraΓ§ sil
function ExitFramework.DeleteVehicle(veh)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
core.Functions.DeleteVehicle(veh)
else
if DoesEntityExist(veh) then
SetEntityAsMissionEntity(veh, true, true)
DeleteEntity(veh)
end
end
end
--- AraΓ§ ΓΆzellikleri al (QBCore ΓΆzelliΔi, diΔerleri iΓ§in temel versiyon)
function ExitFramework.GetVehicleProperties(veh)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
return core.Functions.GetVehicleProperties(veh)
else
return {
model = GetEntityModel(veh),
plate = GetVehicleNumberPlateText(veh)
}
end
end
--- Progressbar
function ExitFramework.Progressbar(label, duration, opts, cbDone, cbCancel)
local fw = ExitFramework.GetType()
local core = ExitFramework.GetCore()
if fw == 'qb' or fw == 'qbox' then
if core.Functions and core.Functions.Progressbar then
core.Functions.Progressbar(
'exit_frag_action', label, duration, false, true,
opts or {disableMovement=true, disableCarMovement=true, disableMouse=false, disableCombat=true},
{}, {}, {}, cbDone, cbCancel
)
return
end
end
-- ox_lib progressBar (exports ile β 'lib' global'i kullanma)
if GetResourceState('ox_lib') == 'started' then
local ok = pcall(function()
exports['ox_lib']:progressBar({
duration = duration,
label = label,
useWhileDead = false,
canCancel = true,
disable = {
move = opts and opts.disableMovement,
car = opts and opts.disableCarMovement,
combat = opts and opts.disableCombat
}
}, cbDone, cbCancel)
end)
if ok then return end
end
-- qb-skillbar fallback
if GetResourceState('qb-skillbar') == 'started' then
local ok = pcall(function()
exports['qb-skillbar']:Start(
{ duration = duration, pos = 50, width = 20 },
function() if cbDone then cbDone() end end,
function() if cbCancel then cbCancel() end end
)
end)
if ok then return end
end
-- Son Γ§are: Timer tabanlΔ± sahte progress
CreateThread(function()
local startT = GetGameTimer()
while GetGameTimer() - startT < duration do Wait(100) end
if cbDone then cbDone() end
end)
end
-- βββ AraΓ§ PlakasΔ±nΔ± Getir ββββββββββββββββββββββββββββββββ
function ExitFramework.GetPlate(vehicle)
if not vehicle or vehicle == 0 then return nil end
local fw = ExitFramework.GetType()
if fw == 'qb' or fw == 'qbox' then
local core = ExitFramework.GetCore()
if core and core.Functions and core.Functions.GetPlate then
return core.Functions.GetPlate(vehicle)
end
end
return GetVehicleNumberPlateText(vehicle)
end
end -- IsDuplicityVersion()