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

Why does this data saving script not work at all?

Asked by 5 years ago

This script is supposed to create and save a subset of player stats that is supposed to be saved and loaded upon the player joining and leaving respectively.

When I increase/change one of the data points and leave and rejoin, the data does not load. This script is currently being tested on a private game, if that matters at all.

What is the issue with it? Output gave me nothing to work with.

local DataStores = game:GetService("DataStoreService")
local PlayersDataStore = DataStores:GetDataStore("Players")
local FindValues = {
"Rank","XP","Prestige","Heists";
--Add any new variable!
}
local TypeValues = {
    Rank = "IntValue"; --Or int whatever is fine...
    XP = "IntValue";
    Prestige = "IntValue";
    Heists = "IntValue";
}

function SetupPlayer(Player)
local LeaderStats = Instance.new("Folder",Player)
LeaderStats.Name = "perm"
local ValueObjects = {}
for i,v in pairs(FindValues)do
    local VALUE = Instance.new(TypeValues[v] or "StringValue",LeaderStats)
    VALUE.Name = v
    ValueObjects[i] = VALUE
end

local LeaderTable = {}
local PlayerDS = PlayersDataStore:GetAsync(Player.UserId)

if not PlayerDS then --For new players!
    local SetTable = {}
    for i,v in pairs(ValueObjects)do
        SetTable[FindValues[i]] = v.Value
    end
    PlayersDataStore:SetAsync(Player.UserId,SetTable)
    PlayerDS = PlayersDataStore:GetAsync(Player.UserId)
end

for i,v in pairs(ValueObjects)do
    v.Value = LeaderTable[FindValues[i]]
end

PlayersDataStore:SetAsync(Player.UserId,PlayerDS)

spawn(function()
    while wait(10)do --Autosave
        for i,v in pairs(ValueObjects)do
        PlayerDS[FindValues[i]] = v.Value
    end
    PlayersDataStore:SetAsync(Player.UserId,PlayerDS)
    end
    end)
end

game.Players.PlayerAdded:connect(SetupPlayer)

1 answer

Log in to vote
2
Answered by 5 years ago
Edited 5 years ago

There are a few issues with your script:

1) It is difficult to read, create separate functions for each task so it can be more organized (save and load data function).

2) The tables are unnecessary and it was hard to understand it. I suggest to create a variable for each value. It'll be more organized and efficient.

3) 'connect' is deprecated, use 'Connect' instead.

4) DO NOT set the parent in the Instance.new parameters. It's a faster way but it was proved that it can slow down the script.

local Players = game:GetService("Players")
local DataStores = game:GetService("DataStoreService")
local PlayersDataStore = DataStores:GetDataStore("Players")

local function SavePlayerData(Player)
    if Player then 
        local Leaderstats = Player:FindFirstChild("perm")
        if Leaderstats then 
            local XPValue, RankValue, HeistsValue, PrestigeValue
            XPValue = Leaderstats:FindFirstChild("XP")
            RankValue = Leaderstats:FindFirstChild("Rank")
            HeistsValue = Leaderstats:FindFirstChild("Heists")
            PrestigeValue = Leaderstats:FindFirstChild("Prestige")
            if XPValue and RankValue and HeistsValue and PrestigeValue then 
                local PlayerDS = PlayersDataStore:GetAsync(Player.UserId)
                if PlayerDS then 
                    local SavingTable = {
                        ["XP"] = XPValue.Value,
                        ["Rank"] = RankValue.Value,
                        ["Heists"] = HeistsValue.Value,
                        ["Prestige"] = PrestigeValue.Value
                    }
                    print("saved " .. Player.Name .. "'s leaderstats")
                    PlayerDataStore:SetAsync(Player.UserId, SavingTable)
                end
            end
        end
    end
end

local function LoadPlayerData(Player, XPValue, RankValue, HeistsValue, PrestigeValue)
    if Player then 
        local PlayerDS = PlayersDataStore:GetAsync(Player.UserId) -- this will return the 'SavingTable'
        if PlayerDS then 
            XPValue.Value = PlayerDS.XP
            RankValue.Value = PlayerDS.Rank
            HeistsValue.Value = PlayerDS.Heists
            PrestigeValue.Value = PlayerDS.Prestige
            print("loaded " .. Player.Name .. "'s leaderstats")
        else
            print("new player")
            PlayerDataStore:SetAsync(Player.UserId, nil)
        end
    end
end

local function SetupPlayer(Player)
    --create leaderstats folder
    local Leaderstats = Instance.new("Folder")
    Leaderstats.Name = "perm"
    Leaderstats.Parent = Player

    --create value function
    local function createNewValue(valueName)
        local newValue = Instance.new("IntValue")
        newValue.Name = valueName
        newValue.Parent = Leaderstats
        return newValue
    end

    --create values
    local XPValue, RankValue, HeistsValue, PrestigeValue

    XPValue = createNewValue("XP")
    RankValue = createNewValue("Rank")
    HeistsValue = createNewValue("Heists")
    PrestigeValue = createNewValue("Prestige")

    --load data
    LoadPlayerData(Player, XPValue, RankValue, HeistsValue, PrestigeValue)

    --autosaving
    spawn(function()
        while Player do 
            wait(10)
            if Player then 
                SavePlayerData(Player)
            end
        end
    end)
end

Players.PlayerAdded:Connect(SetupPlayer)
0
Don't forget to add a PlayerRemoving event so you can save players data when they leave the game. awesomeipod 607 — 5y
0
Make sure studio access to API services is enabled as well awesomeipod 607 — 5y
0
PlayerDataStore:SetAsync(Player.UserId, SavingTable) is undefined in the script? CoolJohnnyboy 121 — 5y
0
They're in lines 24 42 awesomeipod 607 — 5y
View all comments (2 more)
0
Instead of SetAsync to update a player's data who already has data and isn't new, shouldn't you use UpdateAsync? ScrubSadmir 200 — 5y
0
Yes but they both have the same function awesomeipod 607 — 5y
Ad

Answer this question