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
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.
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)
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!