Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

What mistake have I made with this datastore saving script?

Asked by 8 years ago

Hello, I've been struggling with getting this script to work. Focusing on the saving side, the word "Test" prints, but doesn't print "Saved Value", neither does it print any error. I'd appreciate it if anyone could identify what I've done wrong. (There's a folder called PlayerData within the Player, and a SaveOther folder within the PlayerData folder, containing a few values)

game.Players.PlayerRemoving:connect(function(player)

    local datastore = game:GetService("DataStoreService"):GetDataStore(player.Name.."aStats")
local statstorage = player.PlayerData.SaveOther:GetChildren()
print (datastore)
    print (player.PlayerData.SaveOther)
for i =1, #statstorage do
    print "Test"
    datastore:SetAsync(statstorage[i].Name, statstorage[i].Value)
    print("Saved value "..i)

end
print("Stats successfully saved")   
end)
0
There's a possibility that statstorage has a length of 0 User#6546 35 — 8y
0
It appears that PlayerData gets removed before it's had a chance to save the data, although thanks for your help. aston322 25 — 8y

2 answers

Log in to vote
3
Answered by 8 years ago

Suggestion

As eLunate said, having the game close before saving the data to data store can be problematic, and using his example of the game.OnClose callback should be implemented. However, you have slightly bigger problems in this case.

How Data Store works?

Here is a simple manifestation of how data store works:

Global Data Store > Data Store File > Keys / Values

We could even demonstrate this example using Lua tables. In which case, it'd look something like this:

local GlobalDataStore = {
    DataStorage1 = {
        ["Kills"] = 10,
        ["Deaths"] = 0
    },
    DataStorage2 = {
        ["Kills"] = 12,
        ["Deaths"] = 1
    }
}

Where GlobalDataStore is the DataStoreService, DataStorage1 / DataStorage2 are the data files created with the GetDataStore method on the DataStoreService, and the Kills / Deaths are the Keys / Values associated with the created "data files".

What's the point of all that?

The reason I'm explaining this is because of the way you've created your data store system. The only thing that should change in the DataStoreService while the game is running, are the Keys / Values of a data file.

Instead of saving new keys / values to the data store, you're actually created entire new data files each time a player leaves the game (that GetDataStore method within your PlayerRemoving event is the one responsible for this)

Solution?

What you're gonna wanna do, is create your data file head-on at the beginning of your program, then use Get/Set/Update Async to modify that created file, in whatever system you have to manage that (in this case, your PlayerRemoving event).

Here's a revised version of the code you provided implementing the solution above:

-- Player service
local players = game:GetService("Players")

-- The Global Data Store
local datastore = game:GetService("DataStoreService")

-- A created data file named "PlayerStats"
local playerstats = datastore:GetDataStore("PlayerStats")

Players.PlayerRemoving:connect(function(player)
    -- Here is the loaded player data. I also recommend using the player's UserId, and not Name. That way if the player changed their username, their data will still be saved.
    local data = playerstats:GetAsync(player.UserId.."_stats")
    local statstorage = player.PlayerData.SaveOther:GetChildren()

    -- A variable that will return true if the player's past data doesn't exist. This way we can use UpdateAsync instead of SetAsync if necessary.
    local newplayer = data==nil

    -- Let's save the actual data as a table, so we don't need to create multiple keys for it.
    local saved = {}

    -- Store the physical representation of the player's data in the "saved" table
    for i =1, #statstorage do
        saved[i] = v
    end

    -- The final condition. "Stats" will be the name of the key.
    if newplayer then
        -- If it's the player's first time, use SetAsync.
        playerstats:SetAsync("Stats",saved)
    else
        -- If they have a history of previous data, Update it.
        -- "Old" is the argument that represents past data. Here, we're just overwriting all it's keys to everything in the "saved" table, the returning it to the update process.
        playerstats:UpdateAsync("Stats",function(Old)
            for i,v in next, saved do
                Old[i] = v
            end
            return Old
        end)
    end
end)

Hope that helped, let me know if you have any questions.

Ad
Log in to vote
1
Answered by 8 years ago

The simple one
Probably

You let the server close before you could save. Append this to your script.

game.OnClose = function() wait(10) end;
1
I hadn't thought about that as a possibility, but it still doesn't save the data. aston322 25 — 8y

Answer this question