Script not saving money into DataStore

Hello, i was making a game and got a script that saves the time, i added lines that supposed to save money too but it doesnt, it seems like code issue, not datastore itself, here is the code.

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStore")




-- Function to save player's money to DataStore
local function savePlayerMoney(playerId, moneyValue)
    local success, result = pcall(function()
        DataStore:SetAsync("Money_"..playerId, moneyValue)
    end)

    if success then
        print("Data saved for player with ID ".. playerId .. ", Money: ".. moneyValue)
    else
        warn("Failed to save data for player with ID ".. playerId .. ": ".. tostring(result))
    end
end

-- Function to handle player added event
local function onPlayerAdded(player)
    wait()

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "stats"
    leaderstats.Parent = player

    local minutes = Instance.new("IntValue")
    minutes.Name = "time"
    minutes.Parent = leaderstats

    local moneuh = Instance.new("IntValue")
    moneuh.Name = "money"
    moneuh.Parent = leaderstats
    moneuh.Value = 15000
    
    local success, result = pcall(function()
        return DataStore:GetAsync("Minutes_"..player.UserId) and DataStore:GetAsync("Money_"..player.UserId)
    end)

    if success then
        if result then
            minutes.Value = result
        end
    else
        warn("Failed to load data for player ".. player.Name.. ": ".. tostring(result))
    end

    task.spawn(function()
        while task.wait(1) do
            minutes.Value += 1
        end
    end)
end


-- Function to handle player removing event
local function onPlayerRemoving(player)
    local minutes = player:FindFirstChild("stats") and player.stats:FindFirstChild("time")
    local money = player:FindFirstChild("stats") and player.stats:FindFirstChild("money")

    if minutes then
        local success, result = pcall(function()
            DataStore:SetAsync("Minutes_"..player.UserId, minutes.Value)
        end)

        if success then
            print("Data saved for player ".. player.Name)
        else
            warn("Failed to save data for player ".. player.Name.. ": ".. tostring(result))
        end
    end
    if money then
        local success, result = pcall(function()
            DataStore:SetAsync("Money_"..player.UserId, money.Value)
        end)

        if success then
            print("Data saved for player ".. player.Name)
        else
            warn("Failed to save data for player ".. player.Name.. ": ".. tostring(result))
        end
    end
end

-- Function to save player data on game closure
local function saveDataOnGameClose()
    for _, player in pairs(Players:GetPlayers()) do
        local minutes = player:FindFirstChild("stats") and player.stats:FindFirstChild("time")

        if minutes then
            local success, errorMessage = pcall(function()
                DataStore:SetAsync("Minutes_"..player.UserId, minutes.Value)
            end)

            if success then
                print("Data saved for player ".. player.Name)
            else
                print("Error while saving data for player ".. player.Name)
                warn(errorMessage)
            end
        end

        -- Save money value
        local moneyValue = player:FindFirstChild("stats") and player.stats:FindFirstChild("money") -- Corrected lowercase "money"

        if moneyValue then
            savePlayerMoney(player.UserId, moneyValue.Value)
        end
    end
end

-- Connect events
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
game:BindToClose(saveDataOnGameClose)

-- Connect Save event to save player's money
--ReplicatedStorage.Save.OnServerEvent:Connect(function(player, moneyValue)
--    local playerId = player.UserId
--    savePlayerMoney(playerId, moneyValue)
--end)

Can someone tell me whats wrong here, help me out please?

the code

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStore")

-- Function to save player's money to DataStore
local function savePlayerMoney(playerId, moneyValue)
    local success, result = pcall(function()
        DataStore:SetAsync("Money_"..playerId, moneyValue)
    end)

    if success then
        print("Data saved for player with ID ".. playerId .. ", Money: ".. moneyValue)
    else
        warn("Failed to save data for player with ID ".. playerId .. ": ".. tostring(result))
    end
end

-- Function to handle player added event
local function onPlayerAdded(player)
    wait()

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "stats"
    leaderstats.Parent = player

    local minutes = Instance.new("IntValue")
    minutes.Name = "time"
    minutes.Parent = leaderstats

    local money = Instance.new("IntValue")  -- Fixed variable name to "money" instead of "moneuh"
    money.Name = "money"
    money.Parent = leaderstats
    money.Value = 15000
    
    local success, result = pcall(function()
        return DataStore:GetAsync("Minutes_"..player.UserId), DataStore:GetAsync("Money_"..player.UserId)
    end)

    if success then
        if result then
            minutes.Value = result[1] or 0
            money.Value = result[2] or 0
        end
    else
        warn("Failed to load data for player ".. player.Name.. ": ".. tostring(result))
    end

    task.spawn(function()
        while task.wait(1) do
            minutes.Value += 1
        end
    end)
end

-- Function to handle player removing event
local function onPlayerRemoving(player)
    local minutes = player:FindFirstChild("stats") and player.stats:FindFirstChild("time")
    local money = player:FindFirstChild("stats") and player.stats:FindFirstChild("money")

    if minutes then
        local success, result = pcall(function()
            DataStore:SetAsync("Minutes_"..player.UserId, minutes.Value)
        end)

        if not success then
            warn("Failed to save data for player ".. player.Name.. ": ".. tostring(result))
        end
    end

    if money then
        local success, result = pcall(function()
            DataStore:SetAsync("Money_"..player.UserId, money.Value)
        end)

        if not success then
            warn("Failed to save data for player ".. player.Name.. ": ".. tostring(result))
        end
    end
end

-- Function to save player data on game closure
local function saveDataOnGameClose()
    for _, player in pairs(Players:GetPlayers()) do
        local minutes = player:FindFirstChild("stats") and player.stats:FindFirstChild("time")

        if minutes then
            local success, errorMessage = pcall(function()
                DataStore:SetAsync("Minutes_"..player.UserId, minutes.Value)
            end)

            if not success then
                print("Error while saving data for player ".. player.Name)
                warn(errorMessage)
            end
        end

        -- Save money value
        local moneyValue = player:FindFirstChild("stats") and player.stats:FindFirstChild("money")

        if moneyValue then
            savePlayerMoney(player.UserId, moneyValue.Value)
        end
    end
end

-- Connect events
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
game:BindToClose(saveDataOnGameClose)

I think that if you’d investigate with a datastore browser, you’d find that your money is saving.

You simply aren’t loading your money from the datastores properly, and thus when the player leaves the game, the value (which has not been influenced by the previous) gets written, and the cycle repeats.

When you’re first loading data, you and two numbers together. I doubt this is intentional, as the and is a comparison and you will get a boolean returned, although if it doesn’t error then I’m not sure what exactly is being returned, although it is definitely not what you want.
Try setting variables from the outside scope in your pcall
i.e.

local minutes
local money
local success = pcall(function()
    minutes = DataStore:GetAsync("Minutes_"..playerId)
    money = DataStore:GetAsync("Money_"..playerId)
end)

then checking success as you would and setting the values from there. This should definitely make the code a lot cleaner (as you don’t have multiple ambiguous “result or error” variables as returned from pcall)
When working with pcall, I would recommend not returning data from that function. I would use pcall with local success, err = pcall(...), as when success == false, err accurately describes what the issue is, and when success == true, err is nil. Personal preference mostly, adapt to your needs as necessary.

Just as I notice it, you enter a loop of task.wait(1) and incrementing the value. You should check if the player actually still exists, as if that player leaves you may have undefined behaviour, and if it doesn’t error then you have an additional thread wasting CPU time, which nobody likes.

Overall, your code is OK. I would recommend making some more abstraction functions as I see a lot of repeated sections (esp. the portions where you check if the datastore returned success)

Welcome to Roblox development, have fun programming, and if you have any questions, don’t feel reserved on asking!

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.