Hey there, so this is our current script that handles our datastore’s and most of our leaderstats + values:
local Players = game:GetService("Players")
local data = Instance.new("Folder",game.ServerStorage)
data.Name = "Data"
local saves = game:GetService("DataStoreService"):GetDataStore("newmoneyz2")
local jail = game:GetService("DataStoreService"):GetDataStore("jailstuff")
local ribbonsave2 = game:GetService("DataStoreService"):GetDataStore("ribbonz")
local experience = game:GetService("DataStoreService"):GetDataStore("experience2")
local medalsave = game:GetService("DataStoreService"):GetDataStore("medalz")
local DataStoreService = game:GetService("DataStoreService")
local function createLeaderStats(plr)
repeat wait() until plr
local leaderstat = Instance.new("Model")
leaderstat.Name = "leaderstats"
leaderstat.Parent = plr
local exp = Instance.new("IntValue")
exp.Name = "EXP"
exp.Parent = leaderstat
local jailtime = Instance.new("IntValue")
jailtime.Name = "Prison Time"
jailtime.Parent = leaderstat
local medals = Instance.new("IntValue")
medals.Name = "Medal"
medals.Parent = plr
local ribbon = Instance.new("Folder")
ribbon.Name = "Ribbons"
ribbon.Parent = plr
local honorableservice = Instance.new("BoolValue")
honorableservice.Name = "honorableservice"
honorableservice.Parent = ribbon
local loyalservice = Instance.new("BoolValue")
loyalservice.Name = "loyalservice"
loyalservice.Parent = ribbon
local adeptservice = Instance.new("BoolValue")
adeptservice.Name = "adeptservice"
adeptservice.Parent = ribbon
local outstandingservice = Instance.new("BoolValue")
outstandingservice.Name = "outstandingservice"
outstandingservice.Parent = ribbon
local commandservice = Instance.new("BoolValue")
commandservice.Name = "commandservice"
commandservice.Parent = ribbon
local fines = Instance.new("IntValue")
fines.Name = "fine"
fines.Parent = plr
local lastSave = 0
local cash = Instance.new("IntValue", data)
cash.Name = plr.Name.."Cash"
local money = Instance.new("IntValue", data)
money.Name = "money"
money.Parent = plr
local jt = jail:GetAsync(plr.userId.."PrisonTime")
if jt ~= nil and jt > 0 then
jailtime.Value = jt
end
wait()
local exp1 = experience:GetAsync(plr.userId)
if exp1 ~= nil and exp1 > 0 then
exp.Value = exp1
end
local med1 = medalsave:GetAsync(plr.userId)
if med1 ~= nil then
medals.Value = med1
end
wait()
local ribdata
local success, errormessage = pcall(function()
ribdata = ribbonsave2:GetAsync(plr.userId)
end)
if success and ribdata then
wait(2)
plr.Ribbons.honorableservice.Value = ribdata[1]
plr.Ribbons.loyalservice.Value = ribdata[2]
plr.Ribbons.adeptservice.Value = ribdata[3]
plr.Ribbons.commandservice.Value = ribdata[4]
plr.Ribbons.outstandingservice.Value = ribdata[5]
end
cash.Changed:connect(function()
wait()
money.Value = cash.Value
end)
if saves:GetAsync(plr.userId) ~= nil then
cash.Value = saves:GetAsync(plr.userId)
end
if plr:GetRankInGroup(4219097) > 50 then
local function enableExpSystem()
plr.PlayerGui:WaitForChild("expsystem").Enabled = true
end
plr.CharacterAdded:Connect(function()
enableExpSystem()
end)
enableExpSystem()
end
if plr:GetRankInGroup(4219097) >= 235 then
local function enablemedalribbons()
plr.PlayerGui:WaitForChild("medalsystem").Enabled = true
plr.PlayerGui:WaitForChild("ribbonssystem").Enabled = true
end
plr.CharacterAdded:Connect(function()
enablemedalribbons()
end)
enablemedalribbons()
end
while wait(60*3) do
if cash then
cash.Value = cash.Value + 125
end
if plr:IsInGroup(4219097) then
exp.Value = exp.Value + 3
end
end
end
local function savingribbons(plr)
local hs = plr.Ribbons.honorableservice.Value
local ls = plr.Ribbons.loyalservice.Value
local as = plr.Ribbons.adeptservice.Value
local cs = plr.Ribbons.commandservice.Value
local ous = plr.Ribbons.outstandingservice.Value
ribbonsave2:SetAsync(plr.userId, {
hs,
ls,
as,
cs,
ous
})
print("Data saved?")
end
Players.PlayerAdded:Connect(createLeaderStats)--for new players after script connection runs
for _,player in pairs(Players:GetPlayers()) do -- for players who already joined
spawn(function()createLeaderStats(player)end)
end
Players.PlayerRemoving:connect(function(plr)
local pt = plr.leaderstats["Prison Time"].Value
local ex = plr.leaderstats["EXP"].Value
savingribbons(plr)
wait()
medalsave:SetAsync(plr.userId, plr.Medal.Value)
wait()
if data and data[plr.Name.."Cash"] then
print(plr.Name.." Leaving")
saves:SetAsync(plr.userId,game.ServerStorage.Data[plr.Name.."Cash"].Value)
wait()
data[plr.Name.."Cash"]:Destroy()
end
wait()
if ex > 0 then
experience:SetAsync(plr.userId, ex)
end
if pt > 0 then
jail:SetAsync(plr.userId.."PrisonTime", pt)
jail:SetAsync(plr.userId.."InJail", true)
else
jail:SetAsync(plr.userId.."PrisonTime", 0)
jail:SetAsync(plr.userId.."InJail", false)
print("All data saved for"..plr.Name)
end
end)
However, as you can assume, most players data is not saved upon server shutdowns. (I was able to pin point all this from the print functions you can see.)
I am wondering if there is some sort of way to slow-down the shutdown process until all players data has saved first?
Players.PlayerRemoving:connect(function(plr)
local pt = plr.leaderstats["Prison Time"].Value
local ex = plr.leaderstats["EXP"].Value
savingribbons(plr)
wait()
medalsave:SetAsync(plr.userId, plr.Medal.Value)
wait()
if data and data[plr.Name.."Cash"] then
print(plr.Name.." Leaving")
saves:SetAsync(plr.userId,game.ServerStorage.Data[plr.Name.."Cash"].Value)
wait()
data[plr.Name.."Cash"]:Destroy()
end
wait()
if ex > 0 then
experience:SetAsync(plr.userId, ex)
end
if pt > 0 then
jail:SetAsync(plr.userId.."PrisonTime", pt)
jail:SetAsync(plr.userId.."InJail", true)
else
jail:SetAsync(plr.userId.."PrisonTime", 0)
jail:SetAsync(plr.userId.."InJail", false)
print("All data saved for"..plr.Name)
end
end)
It already does that, but will not save every players data if I have to shutdown for an update. I want to avoid players losing data during shutdowns.
Roblox Servers have a 30 (i think) second time limit after the last person leaves where all the serverscripts are able to finish up. Including all your datastorescripts. Wrap it in a PCall and if it fails repeat it. If you really want to enforce data then implement an autocorrect
Hey there, just wanted to run this by you and make sure that this would be the most efficient way of approaching the datasave upon server shutdown:
local Players = game:GetService("Players")
local data = Instance.new("Folder",game.ServerStorage)
data.Name = "Data"
local saves = game:GetService("DataStoreService"):GetDataStore("newmoneyz2")
local jail = game:GetService("DataStoreService"):GetDataStore("jailstuff")
local ribbonsave2 = game:GetService("DataStoreService"):GetDataStore("ribbonz")
local experience = game:GetService("DataStoreService"):GetDataStore("experience2")
local medalsave = game:GetService("DataStoreService"):GetDataStore("medalz")
local DataStoreService = game:GetService("DataStoreService")
local function createLeaderStats(plr)
repeat wait() until plr
local leaderstat = Instance.new("Model")
leaderstat.Name = "leaderstats"
leaderstat.Parent = plr
local exp = Instance.new("IntValue")
exp.Name = "EXP"
exp.Parent = leaderstat
local jailtime = Instance.new("IntValue")
jailtime.Name = "Prison Time"
jailtime.Parent = leaderstat
local medals = Instance.new("IntValue")
medals.Name = "Medal"
medals.Parent = plr
local ribbon = Instance.new("Folder")
ribbon.Name = "Ribbons"
ribbon.Parent = plr
local honorableservice = Instance.new("BoolValue")
honorableservice.Name = "honorableservice"
honorableservice.Parent = ribbon
local loyalservice = Instance.new("BoolValue")
loyalservice.Name = "loyalservice"
loyalservice.Parent = ribbon
local adeptservice = Instance.new("BoolValue")
adeptservice.Name = "adeptservice"
adeptservice.Parent = ribbon
local outstandingservice = Instance.new("BoolValue")
outstandingservice.Name = "outstandingservice"
outstandingservice.Parent = ribbon
local commandservice = Instance.new("BoolValue")
commandservice.Name = "commandservice"
commandservice.Parent = ribbon
local fines = Instance.new("IntValue")
fines.Name = "fine"
fines.Parent = plr
local lastSave = 0
local cash = Instance.new("IntValue", data)
cash.Name = plr.Name.."Cash"
local money = Instance.new("IntValue", data)
money.Name = "money"
money.Parent = plr
local jt = jail:GetAsync(plr.userId.."PrisonTime")
if jt ~= nil and jt > 0 then
jailtime.Value = jt
end
wait()
local exp1 = experience:GetAsync(plr.userId)
if exp1 ~= nil and exp1 > 0 then
exp.Value = exp1
end
local med1 = medalsave:GetAsync(plr.userId)
if med1 ~= nil then
medals.Value = med1
end
wait()
local ribdata
local success, errormessage = pcall(function()
ribdata = ribbonsave2:GetAsync(plr.userId)
end)
if success and ribdata then
wait(2)
plr.Ribbons.honorableservice.Value = ribdata[1]
plr.Ribbons.loyalservice.Value = ribdata[2]
plr.Ribbons.adeptservice.Value = ribdata[3]
plr.Ribbons.commandservice.Value = ribdata[4]
plr.Ribbons.outstandingservice.Value = ribdata[5]
end
cash.Changed:connect(function()
wait()
money.Value = cash.Value
end)
if saves:GetAsync(plr.userId) ~= nil then
cash.Value = saves:GetAsync(plr.userId)
end
if plr:GetRankInGroup(4219097) > 50 then
local function enableExpSystem()
plr.PlayerGui:WaitForChild("expsystem").Enabled = true
end
plr.CharacterAdded:Connect(function()
enableExpSystem()
end)
enableExpSystem()
end
if plr:GetRankInGroup(4219097) >= 235 then
local function enablemedalribbons()
plr.PlayerGui:WaitForChild("medalsystem").Enabled = true
plr.PlayerGui:WaitForChild("ribbonssystem").Enabled = true
end
plr.CharacterAdded:Connect(function()
enablemedalribbons()
end)
enablemedalribbons()
end
while wait(60*3) do
if cash then
cash.Value = cash.Value + 125
end
if plr:IsInGroup(4219097) then
exp.Value = exp.Value + 3
end
end
end
local function savedata(plr)
local hs = plr.Ribbons.honorableservice.Value
local ls = plr.Ribbons.loyalservice.Value
local as = plr.Ribbons.adeptservice.Value
local cs = plr.Ribbons.commandservice.Value
local ous = plr.Ribbons.outstandingservice.Value
local pt = plr.leaderstats["Prison Time"].Value
local ex = plr.leaderstats["EXP"].Value
ribbonsave2:SetAsync(plr.userId, {
hs,
ls,
as,
cs,
ous
})
wait()
medalsave:SetAsync(plr.userId, plr.Medal.Value)
wait()
if data and data[plr.Name.."Cash"] then
print(plr.Name.." Leaving")
saves:SetAsync(plr.userId,game.ServerStorage.Data[plr.Name.."Cash"].Value)
wait()
data[plr.Name.."Cash"]:Destroy()
end
wait()
if ex > 0 then
experience:SetAsync(plr.userId, ex)
end
if pt > 0 then
jail:SetAsync(plr.userId.."PrisonTime", pt)
jail:SetAsync(plr.userId.."InJail", true)
else
jail:SetAsync(plr.userId.."PrisonTime", 0)
jail:SetAsync(plr.userId.."InJail", false)
print("All data saved for"..plr.Name)
end
end
Players.PlayerAdded:Connect(createLeaderStats)--for new players after script connection runs
for _,player in pairs(Players:GetPlayers()) do -- for players who already joined
spawn(function()createLeaderStats(player)end)
end
Players.PlayerRemoving:connect(function(plr)
savedata(plr)
end)
game:BindToClose(function()
for _, player in pairs(Players:GetPlayers()) do
savedata(player)
end
end)
Yes, that perfect! But one thing I’d say is wrapping all the GetAsyncs and SetAsyncs in a pcall because if Roblox’s data stores are down, it’ll break the script