qbcore-framework / qb-core

FiveM RP Framework Core :muscle:
GNU General Public License v3.0
561 stars 966 forks source link

[BUG] Existing players cant have new money accounts #1110

Open avilchiis opened 1 month ago

avilchiis commented 1 month ago

Summary

If you register a new money account, all existing players won't have it only new characters

Reproduction

1 - Register a new money account in qb-core/config.lua > QBConfig.Money.MoneyTypes and QBConfig.Money.DontAllowMinus, name it however you want, in my case I used "cosmo".

2 - Add the following command to any server.lua (ofc make sure to load QBCore object first)

RegisterCommand("test", function(source,args)
    local Player = QBCore.Functions.GetPlayer(source)
    local account = args[1]
    print("account: "..account, "amount: ", Player.PlayerData.money[account])
end)

3 - Use the command /test [account name] and it should print your current balance, it prints 0 if the account exists and it'll print nil if the account doesn't exist in the player data.

4 - Logout and create a new character

5 - Use the command with the new character, cosmo will be printed with a 0 instead of nil.

6 - Verify the players table and the old character doesn't have the new accounts, the new one does have it.

image

Expected behavior

Print 0 because money account exists but balance is 0, this is the behavior in previous versions of qb-core, I'm currently running one from April which works ok, all new accounts are added to existing and new players but the most recent version of qb-core is not adding them.

Actual behavior

It prints nil meaning the account doesn't exist and is not adding the account to the player money table in database

Additional context

No clue how to solve it tbh, I think is has something to do with the applyDefaults function

Last Updated

today

Custom Resources

None

Resource Rename

qb-core

avilchiis commented 1 month ago

I found a solution for this, needs to modify the applyDefaults function in qb-core/server/player.lua line 80 with this:

local function applyDefaults(playerData, defaults)
    for key, value in pairs(defaults) do
        if type(value) == 'function' then
            if key == "money" then
                local moneyTypes = value()
                if not playerData[key] then
                    playerData[key] = moneyTypes
                else
                    for account, balance in pairs(moneyTypes) do
                        playerData[key][account] = playerData[key][account] or balance
                    end
                end
            else
                playerData[key] = playerData[key] or value()
            end
        elseif type(value) == 'table' then
            playerData[key] = playerData[key] or {}
            applyDefaults(playerData[key], value)
        else
            playerData[key] = playerData[key] or value
        end
    end
end

Don't kill me I don't know how to do a pull request 😆, I test this with an existing character and with a new one, works fine with both, 0 errors found 👀

t0r3tto commented 1 month ago

Can you test if the following code works for your test cases?

local function applyDefaults(playerData, defaults)
    for key, value in pairs(defaults) do
        playerData[key] = type(value) == 'function' and
            (key == "money" and playerData[key] or value()) or
            type(value) == 'table' and applyDefaults(playerData[key] or {}, value) or
            playerData[key] or value
    end
    return playerData
end
avilchiis commented 1 month ago

Can you test if the following code works for your test cases?

local function applyDefaults(playerData, defaults)
    for key, value in pairs(defaults) do
        playerData[key] = type(value) == 'function' and
            (key == "money" and playerData[key] or value()) or
            type(value) == 'table' and applyDefaults(playerData[key] or {}, value) or
            playerData[key] or value
    end
    return playerData
end

No it doesn't work and for some reason your code duplicates the character in database but with a different citizenid

t0r3tto commented 1 month ago

both worked for me, the code I provided follows the same logic as in the previous code, still; there must be an easier and simpler way