some players in my discord server are reporting their entire data wiping, everything, obviously this is bad… not sure what’s going on and why it saves about 99% of the time, but is there anything wrong with my datastore?
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("PlayerData_1.2")
local yenLeaderboard = dss:GetOrderedDataStore("YenLeaderboard")
game.Players.PlayerAdded:Connect(function(plr)
local plot = game.Workspace.Plots:FindFirstChild("Unclaimed")
plot.Name = plr.Name
plot.NameTag.BillboardGui.TextLabel.Text = plr.Name.."'s Base"
plr.CharacterAdded:Connect(function()
coroutine.wrap(function()
print("pivoted character")
plr.Character:PivotTo(plot.Lasers.Block.CFrame*CFrame.new(0,0,-10))
for _,v in pairs(plr.Data:WaitForChild("ToolPasses"):GetChildren()) do
if v.Value == true then
local tool = game.ReplicatedStorage.ToolGamepasses[v.Name]:Clone()
tool.Parent = plr.Backpack
end
v.Changed:Connect(function()
if v.Value == true then
local tool = game.ReplicatedStorage.ToolGamepasses[v.Name]:Clone()
tool.Parent = plr.Backpack
end
end)
end
end)()
end)
local data = Instance.new("Folder",plr)
data.Name = "Data"
local bannedbool = Instance.new("BoolValue")
bannedbool.Parent = data
bannedbool.Name = "Banned"
local codes = Instance.new("Folder",data)
codes.Name = "Codes"
for _,v in pairs(game.ReplicatedStorage.Codes:GetChildren()) do
local codebool = Instance.new("BoolValue",codes)
codebool.Parent = codes
codebool.Name = v.Name
end
local leaderstats = Instance.new("Folder")
leaderstats.Parent = plr
leaderstats.Name = "leaderstats"
local yenleaderstat = Instance.new("NumberValue")
yenleaderstat.Parent = leaderstats
yenleaderstat.Name = "Yen"
local rebirthsleaderstat = Instance.new("NumberValue")
rebirthsleaderstat.Parent = leaderstats
rebirthsleaderstat.Name = "Rebirths"
local yen = Instance.new("NumberValue",data)
yen.Name = "Yen"
yen.Value = 50
yenleaderstat.Value = 50
local timeleft = Instance.new("NumberValue",data)
timeleft.Name = "TimeLeft"
local rebirths = Instance.new("NumberValue",data)
rebirths.Name = "Rebirths"
local ownedcharacters = Instance.new("Folder",data)
ownedcharacters.Name = "Characters"
local items = Instance.new("Folder",data)
items.Name = "Items"
local yenmulti = Instance.new("NumberValue",data)
yenmulti.Name = "YenMultiplier"
yenmulti.Value = 1
local quests = Instance.new("Folder",data)
quests.Name = "Quests"
local toolgamepasses = Instance.new("Folder",data)
toolgamepasses.Name = "ToolPasses"
for _,v in pairs(game.ReplicatedStorage.ToolGamepasses:GetChildren()) do
local toolbool = Instance.new("BoolValue",toolgamepasses)
toolbool.Name = v.Name
end
for _,v in pairs(game.ReplicatedStorage.Quests:GetChildren()) do
local questbool = Instance.new("BoolValue",quests)
questbool.Name = v.Name
questbool.Value = false
local claimed = Instance.new("BoolValue",questbool)
claimed.Name = "Claimed"..v.Name
claimed.Value = false
end
local statsfolder = Instance.new("Folder",data)
statsfolder.Name = "Stats"
local CharactersSold = Instance.new("NumberValue",statsfolder) CharactersSold.Name = "CharactersSold"
local Steals = Instance.new("NumberValue",statsfolder) Steals.Name = "Steals"
local index = Instance.new("Folder",data)
index.Name = "Index"
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v:IsA("Model") then
local indexed = Instance.new("BoolValue",index)
indexed.Name = v.Name
end
end
for i=1,10 do
local character = Instance.new("StringValue",ownedcharacters)
character.Name = "Character"..i
local amounttoclaim = Instance.new("NumberValue",character)
amounttoclaim.Name = "CashGenerated".."Character"..i
local mutation = Instance.new("StringValue",character)
mutation.Name = "Mutation".."Character"..i
--ignore this its just to load the characters when they're changed
character.Changed:Connect(function(val)
if val == "" then
if workspace.Plots:FindFirstChild(plr.Name).Spots:FindFirstChild(character.Name):FindFirstChildWhichIsA("Model") then
workspace.Plots:FindFirstChild(plr.Name).Spots:FindFirstChild(character.Name):FindFirstChildWhichIsA("Model"):Destroy()
end
mutation.Value = ""
amounttoclaim.Value = 0
else
index:FindFirstChild(val).Value = true
local characterbody
local rarity
local raritycolor
local mutationtype
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v.Name == val then
characterbody = v:Clone()
rarity = v.Parent.Name
end
end
if rarity == "Secret" then
raritycolor = Color3.new(0, 1, 0.584314)
elseif rarity == "Godly" then
raritycolor = Color3.new(0.533333, 0, 1)
elseif rarity == "Mythic" then
raritycolor = Color3.new(1, 0.0980392, 0.85098)
elseif rarity == "Legendary" then
raritycolor = Color3.new(1, 0.745098, 0.0941176)
elseif rarity == "Rare" then
raritycolor = Color3.new(0.0901961, 0.486275, 1)
elseif rarity == "Common" then
raritycolor = Color3.new(0.6, 0.6, 0.6)
end
characterbody.HumanoidRootPart.Anchored = true
characterbody.Parent = game.Workspace.Plots:FindFirstChild(plr.Name).Spots:FindFirstChild(character.Name)
characterbody.PrimaryPart.CFrame = game.Workspace.Plots:FindFirstChild(plr.Name).Spots:FindFirstChild(character.Name).CFrame*CFrame.new(0,3,0)
local idle = characterbody.Humanoid.Animator:LoadAnimation(characterbody.Idle)
idle:Play()
local label = game.ReplicatedStorage.CharacterLabel:Clone()
label.Parent = characterbody
label.Position = characterbody.Head.Position
label.BillboardGui.CharName.Text = characterbody.Name
label.BillboardGui.Rarity.Text = rarity
if raritycolor then
label.BillboardGui.Rarity.TextColor3 = raritycolor
else
label.BillboardGui.Rarity.TextColor3 = Color3.new(1,1,1)
local gradient = game.ReplicatedStorage.CelestialGradient:Clone()
gradient.Parent = label.BillboardGui.Rarity
end
label.BillboardGui.Income.Text = characterbody:GetAttribute("Income").."/s"
label.BillboardGui.Price.Text = "¥"..characterbody:GetAttribute("Price")
if mutation.Value ~= "" then
mutationtype = mutation.Value
label.BillboardGui.Mutations.Text = mutationtype
characterbody:FindFirstChildWhichIsA("Shirt"):Destroy()
characterbody:FindFirstChildWhichIsA("Pants"):Destroy()
local mutationinstance = Instance.new("StringValue",characterbody)
mutationinstance.Value = mutationtype
mutationinstance.Name = "Mutation"
end
if mutationtype == "Golden" then
local oldincome
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v.Name == characterbody.Name then
oldincome = v:GetAttribute("Income")
end
end
characterbody:SetAttribute("Income",oldincome*3)
label.BillboardGui.Income.Text = (characterbody:GetAttribute("Income")).."/s"
local particles = game.ReplicatedStorage.GemMutation:Clone()
particles.Parent = characterbody.Torso
particles.Stars.Color = ColorSequence.new(Color3.new(1, 0.737255, 0.0745098))
particles.Cross.Color = ColorSequence.new(Color3.new(1, 0.737255, 0.0745098))
label.BillboardGui.Mutations.TextColor3 = Color3.new(1, 0.737255, 0.0745098)
for _,v in pairs(characterbody:GetDescendants()) do
if v:IsA("SpecialMesh") then
v.TextureId = ""
end
if v:IsA("BasePart") then
v.Color = Color3.new(1, 0.737255, 0.0745098)
end
end
elseif mutationtype == "Diamond" then
local oldincome
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v.Name == characterbody.Name then
oldincome = v:GetAttribute("Income")
end
end
characterbody:SetAttribute("Income",oldincome*5)
label.BillboardGui.Income.Text = (characterbody:GetAttribute("Income")).."/s"
local particles = game.ReplicatedStorage.GemMutation:Clone()
particles.Parent = characterbody.Torso
particles.Stars.Color = ColorSequence.new(Color3.new(0.101961, 0.654902, 1))
particles.Cross.Color = ColorSequence.new(Color3.new(0.101961, 0.654902, 1))
label.BillboardGui.Mutations.TextColor3 = Color3.new(0.101961, 0.654902, 1)
for _,v in pairs(characterbody:GetDescendants()) do
if v:IsA("SpecialMesh") then
v.TextureId = ""
end
if v:IsA("BasePart") then
v.Color = Color3.new(0.101961, 0.654902, 1)
end
end
elseif mutationtype == "Emerald" then
local oldincome
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v.Name == characterbody.Name then
oldincome = v:GetAttribute("Income")
end
end
characterbody:SetAttribute("Income",oldincome*7)
label.BillboardGui.Income.Text = (characterbody:GetAttribute("Income")).."/s"
local particles = game.ReplicatedStorage.GemMutation:Clone()
particles.Parent = characterbody.Torso
particles.Stars.Color = ColorSequence.new(Color3.new(0.0980392, 1, 0.231373))
particles.Cross.Color = ColorSequence.new(Color3.new(0.0980392, 1, 0.231373))
label.BillboardGui.Mutations.TextColor3 = Color3.new(0.0980392, 1, 0.231373)
for _,v in pairs(characterbody:GetDescendants()) do
if v:IsA("SpecialMesh") then
v.TextureId = ""
end
if v:IsA("BasePart") then
v.Color = Color3.new(0.0980392, 1, 0.231373)
end
end
end
local wc = Instance.new("WeldConstraint",label)
wc.Part0 = characterbody.Head
wc.Part1 = label
local stealpromptpart = Instance.new("Part")
stealpromptpart.CanCollide = false
stealpromptpart.Size = Vector3.new(0.1, 0.1, 0.1)
stealpromptpart.Anchored = true
stealpromptpart.CFrame = characterbody.HumanoidRootPart.CFrame*CFrame.new(0,3.5,0)
stealpromptpart.Transparency = 1
stealpromptpart.Name = "StealPrompt"
stealpromptpart.Parent = characterbody
local stealprompt = game.ReplicatedStorage.StealPrompt:Clone()
stealprompt.Parent = stealpromptpart
stealprompt.Triggered:Connect(function(plr)
if not plr.Character:FindFirstChild("Stealing") then
game.ReplicatedStorage.Notify:FireClient(plr,"Someone is stealing your "..val)
game.ReplicatedStorage.StealingFrom:FireClient(plr)
end
end)
wait(1)
game.ReplicatedStorage.ChangeToSell:FireClient(plr,characterbody)
print("changed to sell")
end
end)
end
pcall(function()
yenLeaderboard:SetAsync(plr.UserId, math.round(plr.Data.Yen.Value))
end)
yen.Changed:Connect(function(val)
yenleaderstat.Value = val
pcall(function()
yenLeaderboard:SetAsync(plr.UserId, math.round(plr.Data.Yen.Value))
end)
end)
rebirths.Changed:Connect(function(val)
rebirthsleaderstat.Value = val
end)
local data = ds:GetAsync(plr.UserId)
if data then
print("got savedata")
local savedValues = data[1]
local savedItems = data[2]
-- Cache Data descendants by name for fast lookup
local dataDescendants = {}
for _, valObj in pairs(plr.Data:GetDescendants()) do
dataDescendants[valObj.Name] = valObj
end
-- Apply saved values using the cache
for _, savedVal in pairs(savedValues) do
local name = savedVal[1]
local value = savedVal[2]
local valObj = dataDescendants[name]
if valObj then
valObj.Value = value
end
end
-- Recreate saved items
for _, itemName in pairs(savedItems) do
local item = Instance.new("StringValue")
item.Name = itemName
item.Parent = items
end
wait(1)
for _,v in pairs(plot.Spots:GetChildren()) do
if v:FindFirstChildWhichIsA("Model") then
local income = v:FindFirstChildWhichIsA("Model"):GetAttribute("Income")
local secondsgone = os.time() - timeleft.Value
local profit = math.round((income*secondsgone)/2)
plr.Data.Characters[v.Name]["CashGenerated"..v.Name].Value+=profit
end
end
end
if bannedbool.Value == true then
plr:Kick("You are banned from the game.")
end
bannedbool.Changed:Connect(function(val)
if val == true then
plr:Kick("You are banned from the game.")
end
end)
end)
local function savedata(plr)
plr.Data.TimeLeft.Value = os.time()
local savedata = {}
local basevalues = {}
for _,v in pairs(plr.Data:GetDescendants()) do
if v:IsA("ValueBase") and v.Parent.Name ~= "Items" then
table.insert(basevalues,{v.Name,v.Value})
end
end
table.insert(savedata,basevalues)
local items = {}
for _,v in pairs(plr.Data.Items:GetChildren()) do
table.insert(items,v.Name)
end
table.insert(savedata,items)
print("set savedata")
pcall(function()
yenLeaderboard:SetAsync(plr.UserId, math.round(plr.Data.Yen.Value))
end)
local success, err = pcall(function()
ds:SetAsync(plr.UserId, savedata)
end)
if not success then
warn("Failed to save data for "..plr.Name..": "..err)
end
end
game.Players.PlayerRemoving:Connect(function(plr)
local plot = game.Workspace.Plots:FindFirstChild(plr.Name)
plot.Name = "Unclaimed"
plot.NameTag.BillboardGui.TextLabel.Text = "Empty Base"
for _,v in pairs(plot.Spots:GetChildren()) do
if v:FindFirstChildWhichIsA("Model") then
v:FindFirstChildWhichIsA("Model"):Destroy()
v.Claim.BillboardGui.TextLabel.Text = ""
end
end
savedata(plr)
end)
game:BindToClose(function()
-- Wait for all PlayerRemoving connections to finish
for _, plr in pairs(game.Players:GetPlayers()) do
-- Save data for all players still in game
local success, err = pcall(function()
savedata(plr)
end)
if not success then
warn("Failed to save data for "..plr.Name..": "..err)
end
end
-- Give time for datastore requests to complete
wait(2)
end)