Yo, my game has been experience data loss issues. Usually when the data loss occurs, they get rolled back to when they last ate a devil fruit (which is when the game autosaves). This can happen (but not exclusively) when the game shutsdown.
Heres the datastore script:
--|| Services ||--
local DatastoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Marketplaceservice = game:GetService("MarketplaceService")
--|| Variables ||--
local Data = DatastoreService:GetDataStore("DataTest99")
--|| Modules ||--
local Rarity = require(script.Rarity)
local RNG = require(ServerScriptService.Modules.Misc.RNG)
local Moderation = require(ServerScriptService.Modules.Moderation:WaitForChild("Moderation"))
local Weebhookmodule = require(game.ServerScriptService.Modules.Misc:WaitForChild("Webhook"))
--|| Script ||--
function getSaveableColor3(color)
return {r = color.r, g = color.g, b = color.b}
end
function loadColorFromDataStore(t)
return Color3.new(t.r, t.g, t.b)
end
function AddFolder(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Bounty = Instance.new("IntValue")
Bounty.Name = "Bounty"
Bounty.Parent = leaderstats
local PlayerFolder = Instance.new("Folder")
PlayerFolder.Name = "Stats"
PlayerFolder.Parent = player
local Banned = Instance.new("BoolValue")
Banned.Name = "Banned"
Banned.Value = false
Banned.Parent = PlayerFolder
local Party = Instance.new("Folder")
Party.Name = "Party"
Party.Parent = player
local Settings = Instance.new("Folder")
Settings.Name = "Settings"
Settings.Parent = player
local PartyInvites = Instance.new("BoolValue")
PartyInvites.Value = true
PartyInvites.Name = "PartyInvites"
PartyInvites.Parent = Settings
local MusicToggle = Instance.new("BoolValue")
MusicToggle.Value = true
MusicToggle.Name = "Music"
MusicToggle.Parent = Settings
local Shake = Instance.new("BoolValue")
Shake.Value = true
Shake.Name = "Shake"
Shake.Parent = Settings
end
function DataLoad(player)
local leaderstats = player:FindFirstChild("leaderstats")
local PlayerData = player:FindFirstChild("Stats")
local ID = player.UserId
local data
local success, errormessage = pcall(function()
data = Data:GetAsync(ID)
end)
if success then
if data == nil then
for i,v in pairs(script.Template:GetChildren())do
local Clone = v:Clone()
Clone.Parent = PlayerData
end
PlayerData.Race.Value = RNG(Rarity)
PlayerData.BusoColor.Value = Color3.new(math.random(1,255)/255, math.random(1,255)/255, math.random(1,255)/255)
else
for i,v in pairs(script.Template:GetChildren()) do
local Clone = v:Clone()
Clone.Parent = PlayerData
if data[Clone.Name] then
if Clone:IsA("Color3Value") then
Clone.Value = loadColorFromDataStore(data[Clone.Name])
else
Clone.Value = data[Clone.Name]
end
end
end
leaderstats.Bounty.Value = data.Bounty
PlayerData.Banned.Value = data.Banned
end
else
local DataFail = Instance.new("Folder")
DataFail.Parent = player
player:Kick("Data didn't load properly")
end
end
function save(player)
if player:FindFirstChild("DataFail") then return end
if player:FindFirstChild("Saving") then return end
local Saving = Instance.new("Folder")
Saving.Name = "Saving"
Saving.Parent = player
game.Debris:AddItem(Saving, 7)
local leaderstats = player:FindFirstChild("leaderstats")
local PlayerData = player:FindFirstChild("Stats")
local ID = player.UserId
local data = {}
for i,v in pairs(PlayerData:GetChildren()) do
if v:IsA("Color3Value") then
data[v.Name] = getSaveableColor3(v.Value)
else
data[v.Name] = v.Value
end
end
data.Banned = PlayerData.Banned.Value
data.Bounty = leaderstats.Bounty.Value
local success, errormessage = pcall(function()
Data:SetAsync(ID, data)
end)
if success then
print("Saved "..player.Name.."s Data")
else
warn("Data Failure")
end
end
game.Players.PlayerAdded:Connect(function(player)
AddFolder(player)
DataLoad(player)
player.Stats:WaitForChild("Quests").Value = 0
local PlayerData = player:WaitForChild("Stats")
PlayerData.DevilFruit.Changed:Connect(function()
save(player)
end)
end)
game.Players.PlayerRemoving:Connect(function(player)
save(player)
end)
game:BindToClose(function()
for i,v in pairs(game.Players:GetChildren()) do
save(v)
end
end)
Add a wait statement at the end of the BindToClose function. Make the wait statement wait about 5-10 seconds, depending on how much data is needed to save.
Data loss still occurs after a shutdown. Heres the updated code:
--|| Services ||--
local DatastoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Marketplaceservice = game:GetService("MarketplaceService")
--|| Variables ||--
local Data = DatastoreService:GetDataStore("DataTest99")
--|| Modules ||--
local Rarity = require(script.Rarity)
local RNG = require(ServerScriptService.Modules.Misc.RNG)
local Moderation = require(ServerScriptService.Modules.Moderation:WaitForChild("Moderation"))
local Weebhookmodule = require(game.ServerScriptService.Modules.Misc:WaitForChild("Webhook"))
--|| Script ||--
function getSaveableColor3(color)
return {r = color.r, g = color.g, b = color.b}
end
function loadColorFromDataStore(t)
return Color3.new(t.r, t.g, t.b)
end
function AddFolder(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Bounty = Instance.new("IntValue")
Bounty.Name = "Bounty"
Bounty.Parent = leaderstats
local PlayerFolder = Instance.new("Folder")
PlayerFolder.Name = "StatsLoading"
PlayerFolder.Parent = player
local Banned = Instance.new("BoolValue")
Banned.Name = "Banned"
Banned.Value = false
Banned.Parent = PlayerFolder
local Party = Instance.new("Folder")
Party.Name = "Party"
Party.Parent = player
local Settings = Instance.new("Folder")
Settings.Name = "Settings"
Settings.Parent = player
local PartyInvites = Instance.new("BoolValue")
PartyInvites.Value = true
PartyInvites.Name = "PartyInvites"
PartyInvites.Parent = Settings
local MusicToggle = Instance.new("BoolValue")
MusicToggle.Value = true
MusicToggle.Name = "Music"
MusicToggle.Parent = Settings
local Shake = Instance.new("BoolValue")
Shake.Value = true
Shake.Name = "Shake"
Shake.Parent = Settings
end
function DataLoad(player)
local leaderstats = player:FindFirstChild("leaderstats")
local PlayerData = player:FindFirstChild("StatsLoading")
local ID = player.UserId
local data
local success, errormessage = pcall(function()
data = Data:GetAsync(ID)
end)
if success then
if data == nil then
for i,v in pairs(script.Template:GetChildren())do
local Clone = v:Clone()
Clone.Parent = PlayerData
end
PlayerData.Race.Value = RNG(Rarity)
PlayerData.BusoColor.Value = Color3.new(math.random(1,255)/255, math.random(1,255)/255, math.random(1,255)/255)
else
for i,v in pairs(script.Template:GetChildren()) do
local Clone = v:Clone()
if data[Clone.Name] then
if Clone:IsA("Color3Value") then
Clone.Value = loadColorFromDataStore(data[Clone.Name])
else
Clone.Value = data[Clone.Name]
end
end
Clone.Parent = PlayerData
end
leaderstats.Bounty.Value = data.Bounty
PlayerData.Banned.Value = data.Banned
end
else
local DataFail = Instance.new("Folder")
DataFail.Parent = player
player:Kick("Data didn't load properly")
end
PlayerData.Name = "Stats"
end
function save(player)
if player:FindFirstChild("DataFail") then return end
if player:FindFirstChild("Saving") then return end
local Saving = Instance.new("Folder")
Saving.Parent = player
game.Debris:AddItem(Saving, 7)
local leaderstats = player:FindFirstChild("leaderstats")
local PlayerData = player:FindFirstChild("Stats")
local ID = player.UserId
local data = {}
for i,v in pairs(PlayerData:GetChildren()) do
if v:IsA("Color3Value") then
data[v.Name] = getSaveableColor3(v.Value)
else
data[v.Name] = v.Value
end
end
data.Banned = PlayerData.Banned.Value
data.Bounty = leaderstats.Bounty.Value
local success, errormessage = pcall(function()
--Data:SetAsync(ID, data)
if data then
Data:UpdateAsync(ID, function(oldValue)
local previousData = oldValue or {DataId = 0}
if data.DataId == previousData.DataId then
data.DataId = data.DataId + 1
return data
else
return nil
end
end)
end
end)
if success then
print("Saved "..player.Name.."s Data")
else
warn("Data Failure")
end
end
game.Players.PlayerAdded:Connect(function(player)
AddFolder(player)
DataLoad(player)
player.Stats:WaitForChild("Quests").Value = 0
local PlayerData = player:WaitForChild("Stats")
PlayerData.DevilFruit.Changed:Connect(function()
save(player)
end)
end)
game.Players.PlayerRemoving:Connect(function(player)
save(player)
end)
game:BindToClose(function()
local TimeToWait = 10
for i,v in pairs(game.Players:GetChildren()) do
save(v)
TimeToWait = TimeToWait + 1
end
if game["Run Service"]:IsStudio() then
else
task.wait(TimeToWait)
end
end)
game:BindToClose(function()
for i,v in pairs(game.Players:GetChildren()) do
save(v)
end
end
to this:
game:BindToClose(function()
if game:GetService("RunService"):IsStudio() then
wait(2)
else
for _, player in pairs(game.Players:GetPlayers()) do
local finished = Instance.new("BindableEvent")
save(player)
finished.Event:Wait()
end
end
end)