Data doesn't save when I rejoin too fast

This is a code redeeming script, it works perfectly fine until I leave the game right after I redeem a code… Some people told me to turn them into JSON and some told me to use BindToClose, which one should I use?

local data = game:GetService("DataStoreService"):GetDataStore("savedcodes")
    local ss = game:GetService("ServerStorage")
    local activated = {}
    game.Players.PlayerAdded:Connect(function(player)
        local key = "codes-"..player.userId
        local folder = Instance.new("Folder",player)
        folder.Name = "Codes"
        local save = data:GetAsync(key)
        if save then
        for i = 1, #save do
            local temp = Instance.new("BoolValue",folder)
            temp.Name = save[1]
            end
        end
    end)
    game.ReplicatedStorage.Remote.Redeem.OnServerEvent:Connect(function(player,code)
        local reward = player:FindFirstChild("leaderstats")
        local r = reward.Coins
        local key = "codes-"..player.userId
    player.PlayerGui:WaitForChild("MainGui"):WaitForChild("Code")

        if code == "Code1"  then
        if player.Codes:FindFirstChild(code) == nil then
        local bool = Instance.new("BoolValue")
        bool.Parent = player:FindFirstChild("Codes")
        bool.Name = code
        r.Value = r.Value + 300
    player.PlayerGui:FindFirstChild("MainGui").Code.TextBox.Text = "Redeemed!"
    wait(2)
    player.PlayerGui:FindFirstChild("MainGui").Code.TextBox.Text = ""
        else
        player.PlayerGui:FindFirstChild("MainGui").Code.TextBox.Text = "Already Redeemed!"
        wait(1)
        player.PlayerGui:FindFirstChild("MainGui").Code.TextBox.Text = ""
    end
    end

        for i,v in pairs(player.Codes:GetChildren()) do
            if v:isA("BoolValue") then
                table.insert(activated, v.Name)
                data:SetAsync(key,activated)
                wait(60)
            end
        end
    end)

    game.Players.PlayerRemoving:Connect(function(plr)
        data:SetAsync("codes-"..plr.userId, activated)
    end)

Instead of waiting 60 seconds for each code, why don’t you just wrap them all in a table and save it one single time?

1 Like

You should have a BindToClose which saves (when server/game shuts down). But that isn’t related to your current issue.

First off, @rokec123 is right, you should be using tables. In general, when saving player data, it should be a table.

Secondly, don’t have yields before a save. (The wait(1) and wait(2) etc). Guis should be scripted with localscripts. Maybe have a RemoteEvent (usually placed in ReplicatedStorage) that’s fired by the script, then a localscript can do the text changing when the event is fired.

Whoever tells you to use JSON without a reason why (such as using it as a basis for compression), don’t accept that advice, because it’s bad. Information passed to a DataStore is converted into a JSON format under the hood, so you would be double encoding and bloating the size of your key’s value.

As for rejoining too quickly, it depends how fast “too fast” is. DataStores have a 6 second blocker between subsequent writes and a value from a get request will cache for 4. The only suggestion I have for you is to rid of the SetAsync and use better localising/caching strategies - the activated table applies for all players so another user might have someone else’s data and thus be unable to redeem codes.

At the heart of it all: your code doesn’t look bugged and it supposedly isn’t either, it’s just that you appear to be running into edge cases, limitations and small implementation misunderstandings.

2 Likes