> For the complete documentation index, see [llms.txt](https://docs.poisoncode.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.poisoncode.com/group-1/copy-of-pc_collections/editable-files-preview.md).

# Editable files preview

Config and bridge files preview, these files are ignored by the escrow system and can be modified.

{% hint style="success" %}
This script is customizable, you can preview files you have access to below.
{% endhint %}

## Main files

{% hint style="info" %}
These are the main files you can edit to customize this resource
{% endhint %}

<details>

<summary>client/cl_editable.lua</summary>

```lua
---------------------------------------------------------------------------------
--   _____       _                    _____          _                         --
--  |  __ \     (_)                  / ____|        | |                        --
--  | |__) |__   _  ___   ___   _ __ | |      ___   __| |  ___                 --
--  |  ___/ _ \ | |/ __| / _ \ | '_ \| |     / _ \ / _` | / _ \                --
--  | |  | (_) || |\__ \| (_) || | | | |____| (_) | (_| ||  __/                --
--  |_|   \___/ |_||___/ \___/ |_| |_|\_____|\___/ \__,_| \___|                --
--                                                                             --
--  © PoisonCode                                                               --
---------------------------------------------------------------------------------
--  Discord:       https://discord.gg/rNJ8cHXCsN                               --
--  Tebex:         https://tebex.poisoncode.com                                --
--  Docs:          https://docs.poisoncode.com                                 --
---------------------------------------------------------------------------------


RegisterCommand("collections", function(source, args)
    showUI(not IsUiDisplayed)
end)


exports('openCollections', function()
    showUI(not IsUiDisplayed)
end)


RegisterNetEvent('pc_collections:client:openCollections', function()
    showUI(not IsUiDisplayed)
end)
```

</details>

<details>

<summary>server/sv_editable.lua</summary>

```lua
COLLECTIONS_CACHE = {}
Database = {}

---------------------------------------------------------------------------------
--   _____       _                    _____          _                         --
--  |  __ \     (_)                  / ____|        | |                        --
--  | |__) |__   _  ___   ___   _ __ | |      ___   __| |  ___                 --
--  |  ___/ _ \ | |/ __| / _ \ | '_ \| |     / _ \ / _` | / _ \                --
--  | |  | (_) || |\__ \| (_) || | | | |____| (_) | (_| ||  __/                --
--  |_|   \___/ |_||___/ \___/ |_| |_|\_____|\___/ \__,_| \___|                --
--                                                                             --
--  © PoisonCode                                                               --
---------------------------------------------------------------------------------
--  Discord:       https://discord.gg/rNJ8cHXCsN                               --
--  Tebex:         https://tebex.poisoncode.com                                --
--  Docs:          https://docs.poisoncode.com                                 --
---------------------------------------------------------------------------------

-- ====================================================================================================== --
-- ------------------------------------------- DATABASE ------------------------------------------------- --
-- ====================================================================================================== --

function Database.Init()
    if Config.Database == "oxmysql" and GetResourceState('oxmysql') ~= 'started' then
        print("^1[ERROR] oxmysql defined in config but not started. Switching to JSON.^0")
        Config.Database = "json"
    end

    if Config.Database == "json" then
        local loadFile = LoadResourceFile(GetCurrentResourceName(), "./server/data.json")
        if loadFile then
            COLLECTIONS_CACHE = json.decode(loadFile)
        else
            COLLECTIONS_CACHE = {}
        end
    end
end


---@param PID string Player Unique Identifier
---@param collectionName string|nil Collection name to get count for
---@return number|table 
function Database.GetLimitCounts(PID, collectionName)
    if Config.Database == "oxmysql" then
        if not collectionName then
            local result = {}
            local response = MySQL.prepare.await('SELECT collection, count FROM `collections` WHERE `player_id` = ?', {PID})
            if response then
                if #response == 0 and response.collection then response = {response} end
                for _, row in ipairs(response) do
                    result[row.collection] = row.count
                end
            end
            return result
        else
            return MySQL.prepare.await('SELECT count FROM `collections` WHERE `player_id` = ? AND `collection` = ?', {PID, collectionName}) or 0
        end
    else
        if not COLLECTIONS_CACHE[PID] then return (collectionName and 0 or {}) end
        if collectionName then
            return COLLECTIONS_CACHE[PID][collectionName] or 0
        else
            return COLLECTIONS_CACHE[PID]
        end
    end
end


---@param PID string Player Unique Identifier
---@param collectionName string
function Database.IncrementLimit(PID, collectionName)
    if Config.Database == "oxmysql" then
        MySQL.prepare.await('INSERT INTO collections (player_id, collection, count) VALUES (?,?,1) ON DUPLICATE KEY UPDATE count = count + 1', {PID, collectionName})
    else
        if not COLLECTIONS_CACHE[PID] then COLLECTIONS_CACHE[PID] = {} end
        COLLECTIONS_CACHE[PID][collectionName] = (COLLECTIONS_CACHE[PID][collectionName] or 0) + 1
        SaveResourceFile(GetCurrentResourceName(), "./server/source/data.json", json.encode(COLLECTIONS_CACHE), -1)
    end
end

-- ====================================================================================================== --
-- --------------------------------------------- OTHER -------------------------------------------------- --
-- ====================================================================================================== --

---@param player player Player source id
---@return string Unique Player identifier
function GetPlayerUID(player)
    if Config.Framework == "ESX" then
        return Bridge.GetPlayer(player).identifier
    elseif Config.Framework == "QBCore" or Config.Framework == "QBox" then
        return Bridge.GetPlayer(player).PlayerData.citizenid
    elseif Config.Framework == "ox_core" then
        return Bridge.GetPlayer(player).charId
    end
end


RegisterNetEvent('pc_collections:server:openCollections', function(target)
    TriggerClientEvent('pc_collections:client:openCollections', target)
end)


exports('openCollections', function(target)
    TriggerClientEvent('pc_collections:client:openCollections', target)
end)
```

</details>

<details>

<summary>config.lua</summary>

```lua
Config = {}
Locales = {}
Bridge = {}
---------------------------------------------------------------------------------
--   _____       _                    _____          _                         --
--  |  __ \     (_)                  / ____|        | |                        --
--  | |__) |__   _  ___   ___   _ __ | |      ___   __| |  ___                 --
--  |  ___/ _ \ | |/ __| / _ \ | '_ \| |     / _ \ / _` | / _ \                --
--  | |  | (_) || |\__ \| (_) || | | | |____| (_) | (_| ||  __/                --
--  |_|   \___/ |_||___/ \___/ |_| |_|\_____|\___/ \__,_| \___|                --
--                                                                             --
--  © PoisonCode                                                               --
---------------------------------------------------------------------------------
--  Discord:       https://discord.gg/rNJ8cHXCsN                               --
--  Tebex:         https://tebex.poisoncode.com                                --
--  Docs:          https://docs.poisoncode.com                                 --
---------------------------------------------------------------------------------

-- ====================================================================================================== --
-- ---------------------------------------- BRIDGE SETTINGS --------------------------------------------- --
-- ====================================================================================================== --

Config.Framework = "ESX" -- "ESX" / "QBCore" / "QBox" / "ox_core"
Config.InventorySystem = "ox_inventory" -- "ox_inventory" / "ESX" / "QBCore" / "QBox" (ox_core has to use ox_inventory)
Config.Database = "oxmysql" -- "oxmysql" / "json" -- we recommend using oxmysql, you have to setup the database table using the provided SQL file.
Config.Notifications = "pc_notifications" -- pc_notifications / "custom"

-- ====================================================================================================== --
-- -------------------------------------------- GENERAL ------------------------------------------------- --
-- ====================================================================================================== --

Config.Locale = "en" -- Set your language here -- available languages: en 

Config.Debug = false -- Enable debug messages

Config.ShowClaimLimits = true -- Show claim limits in the UI
Config.ShowRewardIcons = true -- Show reward icons in the UI, if disabled only names will be shown

-- ====================================================================================================== --
-- -------------------------------------------- SKILLS -------------------------------------------------- --
-- ====================================================================================================== --
--   For this section to work, you need pc_skills resource: https://tebex.poisoncode.com/scripts/skills   --
-- ====================================================================================================== --

Config.UseSkillSystem = true -- Enable skill system integration
Config.SkillName = "skill1" -- Skill name from the skill system 

-- ====================================================================================================== --
-- ------------------------------------------ COLLECTIONS ----------------------------------------------- --
-- ====================================================================================================== --

Config.Collections = {

    ["collection1"] = { -- Collection name
        order = 1, -- Order in the list
        label = "Example collection 1", -- Collection name
        limit = false, -- Limit how many times player can complete this collection, set to false for unlimited
        items = { -- Items required to complete this collection
            {name = "bread", label = "Bread", count = 2},
        },
        reward = { -- Items rewarded for completing this collection
            {name = "money", label = "Cash", count = 500},
        },
        -- pc_skills integration, this will only work if Config.pc_skills.enabled is set to true
        lvl = 1, -- Level required to unlock this collection, only works if Config.pc_skills.enabled is set to true
        rewardXP = 200, -- Experience points rewarded for completing this collection, only works if Config.pc_skills.enabled is set to true
    },

    ["collection2"] = {
        order = 2,
        label = "Example collection 2",
        limit = 1,
        items = {
            {name = "weed", label = "Weed", count = 5},
            {name = "glove", label = "Gloves", count = 2},
            {name = "mask1", label = "Mask", count = 1},
        },
        reward = {
            {name = "armour", label = "Bulletproof vest", count = 1},
            {name = "weapon_pistol", label = "Pistol", count = 1},
        },
        lvl = 1,
        rewardXP = 10,
    },

    ["collection3"] = {
        order = 3,
        label = "Example collection 3",
        limit = 1,
        items = {
            {name = "carrot", label = "Carrot", count = 1},
            {name = "eggplant", label = "Eggplant", count = 1},
            {name = "Pepper", label = "Pepper", count = 1},
        },
        reward = {
            {name = "money", label = "Cash", count = 20000},
        },
        lvl = 5,
        rewardXP = 20,
    },

    ["collection4"] = {
        order = 4,
        label = "Example collection 4",
        limit = 2,
        items = {
            {name = "bread", label = "Bread", count = 1},
            {name = "bread", label = "Bread", count = 1},
            {name = "bread", label = "Bread", count = 1},
            {name = "bread", label = "Bread", count = 1},
            {name = "bread", label = "Bread", count = 1},
            {name = "water", label = "Water", count = 1},
            {name = "water", label = "Water", count = 1},
            {name = "water", label = "Water", count = 1},
            {name = "water", label = "Water", count = 1},
            {name = "water", label = "Water", count = 1},
        },
        reward = {
            {name = "usb_black", label = "USB stick", count = 2},
        },
        lvl = 3,
        rewardXP = 20,
    },

        ["collection5"] = {
        order = 5,
        label = "Example collection 5",
        limit = 3,
        items = {
            {name = "advancedkit", label = "Repair kit", count = 1},
            {name = "ziptie", label = "Ziptie", count = 5},
        },
        reward = {
            {name = "internals", label = "Parts", count = 2},
        },
        lvl = 3,
        rewardXP = 100,
    },
    
}
```

</details>

## Bridge module

{% hint style="info" %}
Bridge module is used to provide compatibility with different frameworks, inventory systems and much more, you can see which system are supported and if you have sufficient knowledge - add a new one.
{% endhint %}

<details>

<summary>server/framework.lua</summary>

```lua
if Config.Framework ~= "ESX" or Framework then return end

Framework = exports["es_extended"]:getSharedObject() or nil
if not Framework then
  TriggerEvent('esx:getSharedObject', function(library) 
    Framework = library or nil
  end)
end

Bridge.GetPlayer = Framework.GetPlayerFromId

if Framework and Bridge.GetPlayer then
  print("Loaded ESX framework")
end
```

</details>

<details>

<summary>server/inventory.lua</summary>

```lua
if Config.Framework ~= "ox_core" or Framework then return end

if not Ox then
    print("Ox_Core framework not found, make sure it's uncommented in fxmanifest.")
end

Bridge.GetPlayer = Ox.GetPlayerFromUserId

if not Config.InventorySystem == "ox_inventory" then
    print("You cannot use ox_core framework without ox_inventory, please check your Configuration.")
    Config.InventorySystem = "ox_inventory"
end

if Ox and Bridge.GetPlayer and Config.InventorySystem == "ox_inventory" then
    print("Loaded ox_core framework")
end

```

</details>

<details>

<summary>server/notifications.lua</summary>

```lua
if Config.Framework ~= "QBCore" or Framework then return end

Framework = exports["qb-core"]:GetCoreObject() or nil

Bridge.GetPlayer = Framework.Functions.GetPlayer

if Framework and Bridge.GetPlayer then
    print("Loaded QBCore framework")
end
```

</details>

{% hint style="info" %}
If you encounter any problems during configuration, you can create a support ticket on our discord.
{% endhint %}
