ESX

CreateThread(function()
    if Config.framework ~= 'ESX' then return end
    
    ESX = exports['es_extended']:getSharedObject()

    local function IsOxInventory()
        return GetResourceState('ox_inventory') == 'started'
    end
    
    -- GetPlayer
    function GetPlayer(source)
        return ESX.GetPlayerFromId(source)
    end
    
    -- CreateUseableItem
    function CreateUseableItem(itemName, callback)
        ESX.RegisterUsableItem(itemName, function(source, item)
            local usableItem = item
            if type(item) ~= 'table' and IsOxInventory() then
                local slots = exports.ox_inventory:Search(source, 'slots', itemName) or {}
                local first = slots[1]
                if first then
                    usableItem = {
                        name = first.name or itemName,
                        count = first.count or 0,
                        label = first.label,
                        slot = first.slot,
                        info = first.metadata or {},
                        metadata = first.metadata or {}
                    }
                end
            end
            callback(source, usableItem)
        end)
    end
    
    -- GetPlayerJobName
    function GetPlayerJobName(source)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            local job = xPlayer.getJob()
            if job and job.name then
                return job.name
            end
        end
        return nil
    end
    
    -- GetPlayerJobGrade
    function GetPlayerJobGrade(source)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            local job = xPlayer.getJob()
            if job and job.grade then
                return job.grade
            end
        end
        return nil
    end
    
    -- AddItem
    function AddItem(source, itemName, amount, info)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            if IsOxInventory() then
                local result = exports.ox_inventory:AddItem(source, itemName, amount, info)
                if result == false then
                    return false
                end
                return true
            end
            if info then
                xPlayer.addInventoryItem(itemName, amount, info)
            else
                xPlayer.addInventoryItem(itemName, amount)
            end
            return true
        end
        return false
    end
    
    -- RemoveItem
    function RemoveItem(source, itemName, amount, slot)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            if IsOxInventory() then
                exports.ox_inventory:RemoveItem(source, itemName, amount, nil, slot)
                -- ox_inventory returns nil even on success, so we always return true
                return true
            end
            xPlayer.removeInventoryItem(itemName, amount)
            return true
        end
        return false
    end

    -- SetItemMetadata
    function SetItemMetadata(source, itemName, slot, info)
        if IsOxInventory() then
            local targetSlot = slot
            if not targetSlot then
                local slots = exports.ox_inventory:Search(source, 'slots', itemName) or {}
                if slots[1] then
                    targetSlot = slots[1].slot
                end
            end
            if targetSlot then
                local existing = exports.ox_inventory:Search(source, 'slots', itemName) or {}
                local current = {}
                for _, item in ipairs(existing) do
                    if item.slot == targetSlot then
                        current = item.metadata or {}
                        break
                    end
                end
                local merged = {}
                for k, v in pairs(current) do merged[k] = v end
                for k, v in pairs(info or {}) do merged[k] = v end
                return exports.ox_inventory:SetMetadata(source, targetSlot, merged)
            end
            return false
        end

        if RemoveItem(source, itemName, 1, slot) then
            return AddItem(source, itemName, 1, info)
        end
        return false
    end
    
    -- GetItemByName
    function GetItemByName(source, itemName)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            if IsOxInventory() then
                local items = exports.ox_inventory:Search(source, 'slots', itemName) or {}
                local first = items[1]
                if first then
                    return {
                        name = first.name or itemName,
                        count = first.count or 0,
                        label = first.label,
                        slot = first.slot,
                        info = first.metadata or {}
                    }
                end
                return nil
            end
            return xPlayer.getInventoryItem(itemName)
        end
        return nil
    end
    
    -- GetItemsByName (ESX - returns array of items with metadata)
    function GetItemsByName(source, itemName)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            if IsOxInventory() then
                local items = {}
                local slots = exports.ox_inventory:Search(source, 'slots', itemName) or {}
                for _, item in ipairs(slots) do
                    table.insert(items, {
                        name = item.name or itemName,
                        count = item.count or 0,
                        label = item.label,
                        slot = item.slot,
                        info = item.metadata or {}
                    })
                end
                return items
            end
            local items = {}
            local inventory = xPlayer.getInventory()
            for i = 1, #inventory do
                if inventory[i].name == itemName then
                    table.insert(items, {
                        name = inventory[i].name,
                        count = inventory[i].count,
                        label = inventory[i].label,
                        slot = i,
                        info = inventory[i].metadata or {}
                    })
                end
            end
            return items
        end
        return {}
    end
    
    -- GetPlayerData for metadata access
    function GetPlayerData(source)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            return {
                identifier = xPlayer.identifier,
                citizenid = xPlayer.identifier,
                source = source
            }
        end
        return nil
    end
    
    -- AddMoney
    function AddMoney(source, moneyType, amount)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            local typeToUse = moneyType or Config.MoneyType or 'cash'
            if typeToUse == 'cash' then
                if xPlayer.addMoney then
                    xPlayer.addMoney(amount)
                else
                    xPlayer.addAccountMoney('money', amount)
                end
            elseif typeToUse == 'bank' then
                xPlayer.addAccountMoney('bank', amount)
            elseif typeToUse == 'money' then
                xPlayer.addAccountMoney('money', amount)
            end
            return true
        end
        return false
    end
    
    -- RemoveMoney
    function RemoveMoney(source, moneyType, amount)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            local typeToUse = moneyType or Config.MoneyType or 'cash'
            if typeToUse == 'cash' then
                if xPlayer.removeMoney then
                    xPlayer.removeMoney(amount)
                else
                    xPlayer.removeAccountMoney('money', amount)
                end
            elseif typeToUse == 'bank' then
                xPlayer.removeAccountMoney('bank', amount)
            elseif typeToUse == 'money' then
                xPlayer.removeAccountMoney('money', amount)
            end
            return true
        end
        return false
    end

    -- AddJobMoney
    function AddJobMoney(accountName, amount)
        if not accountName or accountName == '' then
            return false
        end
        TriggerEvent('esx_addonaccount:getSharedAccount', accountName, function(account)
            if account then
                account.addMoney(amount)
            else
                print('No shared account found: ' .. tostring(accountName))
            end
        end)
        return true
    end
    
    -- GetSharedItem
    function GetSharedItem(itemName)
        if ESX.GetItemLabel then
            return { label = ESX.GetItemLabel(itemName) }
        end
        return nil
    end
    
    -- Notify
    function Notify(source, message, theme, duration)
        TriggerClientEvent('esx:showNotification', source, message)
    end

    -- GetPlayerPermission
    function GetPlayerPermission(player)
        local xPlayer = ESX.GetPlayerFromId(player)
        if xPlayer then
            local group = xPlayer.getGroup()
            if group == 'admin' or group == 'god' or group == 'mod' then
                return true
            end
        end
        return false
    end
    
    -- GetPlayerMoney
    function GetPlayerMoney(source, moneyType)
        local xPlayer = GetPlayer(source)
        if xPlayer then
            local typeToUse = moneyType or Config.MoneyType or 'cash'
            local accounts = xPlayer.getAccounts()
            if type(accounts) == 'table' then
                for _, account in ipairs(accounts) do
                    if typeToUse == 'cash' and (account.name == 'money' or account.name == 'cash') then
                        return account.money or 0
                    elseif typeToUse == 'bank' and account.name == 'bank' then
                        return account.money or 0
                    elseif typeToUse == 'money' and account.name == 'money' then
                        return account.money or 0
                    end
                end
            end
        end
        return 0
    end
    
    -- Server event to retrieve player character info (firstname and lastname)
    RegisterServerEvent('peace-treasure:GetPlayerCharInfo')
    AddEventHandler('peace-treasure:GetPlayerCharInfo', function(identifier)
        local source = source
        MySQL.Async.fetchAll('SELECT * FROM users WHERE identifier = @identifier', {
            ['@identifier'] = identifier
        }, function(result)
            if result and #result > 0 then
                local firstname = result[1].firstname
                local lastname = result[1].lastname
                TriggerClientEvent('peace-treasure:ReceivePlayerCharInfo', source, { firstname = firstname, lastname = lastname })
            else
                TriggerClientEvent('peace-treasure:ReceivePlayerCharInfo', source, nil)
            end
        end)
    end)
end)

Last updated