Help improve my datastore script

so, I’ve got a datastore script that I want to optimise but keep the extra security features (the extra functions)

PS

please don’t tell me to use any datastore modules, I want it to be my version

script in serverscriptservice:

function saveData(player)
    local ds = game:GetService("DataStoreService"):GetDataStore("Data", "Completed")
    local ds2 = game:GetService("DataStoreService"):GetDataStore("Data", "TimesPlayed")
    
    pcall(function()
        ds:UpdateAsync("Player_"..player.UserId, function()
            return player.leaderstats.Completed.Value
        end)
        
        ds2:UpdateAsync("Player_"..player.UserId, function()
            return player.PlayerData.TimesPlayed.Value
        end)
    end)
end

function retrieveData(player, data)
    local ds = game:GetService("DataStoreService"):GetDataStore("Data", data)
    local data
    pcall(function()
        data = ds:GetAsync("Player_"..player.UserId)
    end)
    return data or "Default"
end

function playerAdded(player)
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"

    local playerData = Instance.new("Folder")
    playerData.Name = "PlayerData"

    local completed = Instance.new("IntValue")
    completed.Name = "Completed"

    local timesPlayed = Instance.new("IntValue")
    timesPlayed.Name = "TimesPlayed"

    local completedData = retrieveData(player, "Completed")
    local timesPlayedData = retrieveData(player, "TimesPlayed")
    
    if completedData == "Default" then
        completed.Value = 0
    else
        completed.Value = completedData
    end
    
    if timesPlayedData == "Default" then
        timesPlayed.Value = 1
    else
        timesPlayed.Value = timesPlayedData + 1
    end

    timesPlayed.Parent = playerData
    playerData.Parent = player

    completed.Parent = leaderstats
    leaderstats.Parent = player
end

game:BindToClose(function()
    for _, player in game.Players:GetPlayers() do
        saveData(player)
    end
    task.wait(5)
end)

game.Players.PlayerAdded:Connect(playerAdded)
game.Players.PlayerRemoving:Connect(saveData)

it works completely fine, but I just want to know how to optimise it and keep the extra features, thank you

1 Like

First off, I’d permanently reference DataStoreService by doing the following:

local DataStoreService = game:GetService("DataStoreService")

instead of referencing it every time you want to use it.

I’d also change those functions to local functions if you’re not using them for something only a function can do.

You could add some type checking in there like:

function saveData(Player: Player): any -- change this to whatever instances `TimesPlayed` is

function retrieveData(Player: Player, data: any): Instance | string

I’d also change up the variable names for data since you’ve referenced it as a parameter and a variable in retrieveData but other than that, that’s about it! Well done.

like this?

local dss = game:GetService("DataStoreService")
local hs = game:GetService("HttpService")

local function saveData(player: Player): any
    local ds = dss:GetDataStore("Data", "Completed")
    local ds2 = dss:GetDataStore("Data", "TimesPlayed")
    local ds3 = dss:GetDataStore("Data", "Tutorials")

    pcall(function()
        ds:UpdateAsync("Player_"..player.UserId, function()
            return player.leaderstats.Completed.Value
        end)

        ds2:UpdateAsync("Player_"..player.UserId, function()
            return player.PlayerData.TimesPlayed.Value
        end)

        ds3:UpdateAsync("Player_"..player.UserId, function()
            return hs:JSONEncode(player.PlayerData.Tutorials:GetChildren())
        end)
    end)
end

local function retrieveData(player: Player, scope: string): any
    local ds = dss:GetDataStore("Data", scope)
    local data
    pcall(function()
        data = ds:GetAsync("Player_"..player.UserId)
    end)
    return data or "Default"
end

local function playerAdded(player)
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"

    local playerData = Instance.new("Folder")
    playerData.Name = "PlayerData"

    local tutorials = Instance.new("Folder")
    tutorials.Name = "Tutorials"

    local completed = Instance.new("IntValue")
    completed.Name = "Completed"

    local timesPlayed = Instance.new("IntValue")
    timesPlayed.Name = "TimesPlayed"

    local completedData = retrieveData(player, "Completed")
    local timesPlayedData = retrieveData(player, "TimesPlayed")
    local tutorialsData = retrieveData(player, "Tutorials")

    if completedData == "Default" then
        completed.Value = 0
    else
        completed.Value = completedData
    end

    if timesPlayedData == "Default" then
        timesPlayed.Value = 1
    else
        timesPlayed.Value = timesPlayedData + 1
    end

    if tutorialsData == "Default" then
        local tutorialsModule = require(game:GetService("ReplicatedStorage"):WaitForChild("Tutorials"))
        for tutorial, _ in tutorialsModule do
            local value = Instance.new("BoolValue")
            value.Name = tutorial
            value.Value = false
            value.Parent = tutorials
        end
    else
        local children = hs:JSONDecode(tutorialsData)
        for _, v in children do
            local value = Instance.new("BoolValue")
            value.Name = v.Name
            value.Value = v.Value
            value.Parent = tutorials
        end
    end

    timesPlayed.Parent = playerData
    tutorials.Parent = playerData
    playerData.Parent = player

    completed.Parent = leaderstats
    leaderstats.Parent = player
end

game:BindToClose(function()
    for _, player in game.Players:GetPlayers() do
        saveData(player)
    end
    task.wait(5)
end)

game.Players.PlayerAdded:Connect(playerAdded)
game.Players.PlayerRemoving:Connect(saveData)
1 Like

That’s it! The only thing you could really add now is more static type checking but there’s no real point in adding anymore type checking to that. Nice job!

1 Like

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