Resource Integration

A guide to help customers understand how to make cd_garage compatible with other resources.

Compatible Resources

Compatibility Type

There is multiple ways another resource can be considered compatible with cd_garage. Some are easier for the customer than others.

Built-in (recommended) - This means the resource's creator has already made the changes to their resource to make it compatible with cd_garage, so you don’t have to.

Creator Docs - This means the creator provides documentation for the required changes you need to make to make their resource compatible with cd_garage.

ESX Resources

Keys

To use our built-in vehicle keys feature with official ESX resources, these are the only modifications required because most ESX resources usually call these functions to spawn in vehicles.

Still don't recieve keys? If you don't receive keys to a vehicle, most likely, one of your resources does not use any of the ESX spawn vehicle functions, so you will need to refer to #VehicleKeys and add the event to that resource.

Click this link to view the code on GitHub: ex_extended/server/onesync.lua

Add the 2 line's of code exactly as seen in the screenshot below.
Wait(100)
TriggerClientEvent('cd_garage:AddKeys', xPlayer.id, GetVehicleNumberPlateText(createdVehicle))

Job Garages

To use our built-in job garage feature with official ESX resources, these are the only modifications required.

Click this link to view the code on GitHub: esx_policejob/server/main.lua

REPLACE the line of code exactly as seen in the screenshot below.
MySQL.insert('INSERT INTO owned_vehicles (owner, vehicle, plate, type, job_personalowned, `stored`) VALUES (?, ?, ?, ?, ?, ?)', { xPlayer.identifier, json.encode(vehicleProps), vehicleProps.plate, type, xPlayer.job.name, true},

Boat & Air Garages

To use our built-in boat & air garages feature with official ESX resources, these are the only modifications required.

Click this link to view the code on GitHub: esx_boat/client/main.lua

Add the line of code exactly as seen in the screenshot below.
TriggerEvent('cd_garage:UpdateGarageType')

Persistent Vehicle

To use our built-in persistent vehicle feature with official ESX resources, these are the only modifications required.

Vehicles still respawn when deleting them? If vehicles still respawn when deleting them, most likely, one of your resources does not use the ESX delete vehicle function, so you will need to refer to #PersistentVehicles and add the event to that resource.

Click this link to view the code on GitHub: es_extended/client/functions.lua

Add the line of code exactly as seen in the screenshot below.
TriggerServerEvent('cd_garage:RemovePersistentVehicles', exports['cd_garage']:GetPlate(vehicle))

QBCore Resources

Keys

To use our built-in vehicle keys feature with official QBCore resources, these are the only modifications required.

This process is much simpler on QBCore compared to ESX because we have added event handlers for the default QBCore qb-vehiclekeys resource into cd_garage, meaning its mostly pre-configured.

Click this link to view the code on GitHub: qb-core/client/events.lua

REPLACE the line’s of code exactly as seen in the screenshot below.
if GetResourceState('cd_garage') == 'started' and plate then
    hasKeys = exports['cd_garage']:DoesPlayerHaveKeys(plate)
end

Boat & Air Garages

To use our built-in boat & air garages feature with official QBCore resources, these are the only modifications required.

Click this link to view the code on GitHub: qb-vehicleshop/client/main.lua

Add the line of code exactly as seen in the screenshot below.
TriggerEvent('cd_garage:UpdateGarageType')

Persistent Vehicle

To use our built-in persistent vehicle feature with official QBCore resources, these are the only modifications required.

Vehicles still respawn when deleting them? If vehicles still respawn when deleting them, most likely, one of your resources does not use the QBCore delete vehicle function, so you will need to refer to #PersistentVehicles and add the event to that resource.

Click this link to view the code on GitHub: qb-core/client/functions.lua

Add the line of code exactly as seen in the screenshot below.
TriggerServerEvent('cd_garage:RemovePersistentVehicles', exports['cd_garage']:GetPlate(vehicle))

Garage Phone Apps

To make your phones garage app compatible with cd_garage, these are the only modifications required. If you use a phone thats not listed below, these changes may not work for you.

Click this link to view the code on GitHub: qb-phone/server/main.lua

Replace this whole function.
QBCore.Functions.CreateCallback('qb-phone:server:GetPhoneData', function(source, cb)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if Player ~= nil then
        local PhoneData = {
            Applications = {},
            PlayerContacts = {},
            MentionedTweets = {},
            Chats = {},
            Hashtags = {},
            Invoices = {},
            Garage = {},
            Mails = {},
            Adverts = {},
            CryptoTransactions = {},
            Tweets = {},
            Images = {},
            InstalledApps = Player.PlayerData.metadata["phonedata"].InstalledApps
        }
        PhoneData.Adverts = Adverts

        local result = MySQL.query.await('SELECT * FROM player_contacts WHERE citizenid = ? ORDER BY name ASC', {Player.PlayerData.citizenid})
        if result[1] ~= nil then
            for _, v in pairs(result) do
                v.status = GetOnlineStatus(v.number)
            end

            PhoneData.PlayerContacts = result
        end

        local invoices = MySQL.query.await('SELECT * FROM phone_invoices WHERE citizenid = ?', {Player.PlayerData.citizenid})
        if invoices[1] ~= nil then
            for _, v in pairs(invoices) do
                local Ply = QBCore.Functions.GetPlayerByCitizenId(v.sender)
                if Ply ~= nil then
                    v.number = Ply.PlayerData.charinfo.phone
                else
                    local res = MySQL.query.await('SELECT * FROM players WHERE citizenid = ?', {v.sender})
                    if res[1] ~= nil then
                        res[1].charinfo = json.decode(res[1].charinfo)
                        v.number = res[1].charinfo.phone
                    else
                        v.number = nil
                    end
                end
            end
            PhoneData.Invoices = invoices
        end

        local garageresult = MySQL.query.await('SELECT * FROM player_vehicles WHERE citizenid = ?', {Player.PlayerData.citizenid})
        if garageresult[1] ~= nil then
            for _, v in pairs(garageresult) do
                local vehicleModel = v.vehicle
                if QBCore.Shared.Vehicles[vehicleModel] then
                    v.garage = v.garage_id
                    v.vehicle = QBCore.Shared.Vehicles[vehicleModel].name
                    v.brand = QBCore.Shared.Vehicles[vehicleModel].brand
                end

            end
            PhoneData.Garage = garageresult
        end

        local messages = MySQL.query.await('SELECT * FROM phone_messages WHERE citizenid = ?', {Player.PlayerData.citizenid})
        if messages ~= nil and next(messages) ~= nil then
            PhoneData.Chats = messages
        end

        if AppAlerts[Player.PlayerData.citizenid] ~= nil then
            PhoneData.Applications = AppAlerts[Player.PlayerData.citizenid]
        end

        if MentionedTweets[Player.PlayerData.citizenid] ~= nil then
            PhoneData.MentionedTweets = MentionedTweets[Player.PlayerData.citizenid]
        end

        if Hashtags ~= nil and next(Hashtags) ~= nil then
            PhoneData.Hashtags = Hashtags
        end

        local Tweets = MySQL.query.await('SELECT * FROM phone_tweets WHERE `date` > NOW() - INTERVAL ? hour', {Config.TweetDuration})

        if Tweets ~= nil and next(Tweets) ~= nil then
            PhoneData.Tweets = Tweets
            TWData = Tweets
        end

        local mails = MySQL.query.await('SELECT * FROM player_mails WHERE citizenid = ? ORDER BY `date` ASC', {Player.PlayerData.citizenid})
        if mails[1] ~= nil then
            for k, _ in pairs(mails) do
                if mails[k].button ~= nil then
                    mails[k].button = json.decode(mails[k].button)
                end
            end
            PhoneData.Mails = mails
        end

        local transactions = MySQL.query.await('SELECT * FROM crypto_transactions WHERE citizenid = ? ORDER BY `date` ASC', {Player.PlayerData.citizenid})
        if transactions[1] ~= nil then
            for _, v in pairs(transactions) do
                PhoneData.CryptoTransactions[#PhoneData.CryptoTransactions+1] = {
                    TransactionTitle = v.title,
                    TransactionMessage = v.message
                }
            end
        end
        local images = MySQL.query.await('SELECT * FROM phone_gallery WHERE citizenid = ? ORDER BY `date` DESC',{Player.PlayerData.citizenid})
        if images ~= nil and next(images) ~= nil then
            PhoneData.Images = images
        end
        cb(PhoneData)
    end
end)

Keys

You can find this event in [okok-vehicleshop/sv_utils.lua] (approx; line 72).

Add the line of code exactly as seen in the screenshot below.
TriggerClientEvent('cd_garage:AddKeys', _source, vehicleProps.plate:match( "^%s*(.-)%s*$" ))

Boat & Air Garages

You can find this event in [okok-vehicleshop/sv_utils.lua] (approx; line 68).

Add the line of code exactly as seen in the screenshot below.
TriggerClientEvent('cd_garage:UpdateGarageType', source)

Garage Phone Apps

To make your phones garage app compatible with cd_garage, these are the only modifications required.

lb-phone comes pre-configured to work with cd_garage, so no modifications are required.

Last updated