I dont know why but when the players game crashes it doesnt save even though the character is removed… Also occasionally it wont save certain characters…?
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("PlayerData_1.2")
local yenLeaderboard = dss:GetOrderedDataStore("YenLeaderboard2.0")
local PlayerLoaded = {}
local function GetData(Key, MaxRetries)
local Retries = 0
while true do
local Success, Result = pcall(function()
return ds:GetAsync(Key)
end)
if Success then
return true, Result
else
warn("[GetData]: "..Result)
Retries += 1
if Retries > MaxRetries then -- Give up :(
return false, nil
end
-- Exponential backoff (increases the wait, to alleviate the load on roblox's servers if they go down)
task.wait(2^Retries)
continue
end
end
end
local function savedata(plr,MaxRetries)
if not PlayerLoaded[plr.UserId] then return end
local retries = 0
PlayerLoaded[plr.UserId] = nil
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)
pcall(function()
yenLeaderboard:SetAsync(plr.UserId, math.round(plr.Data.Yen.Value))
end)
for i=1,MaxRetries do
print("took "..i.." try(s) to save data")
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
if success then
break
end
end
end
local function LoadData(plr,plot,items,timeleft)
local Success, Result = GetData(plr.UserId,5)
if not Success then
warn("Datastore Error: "..Result) -- In case of an error, Result is the error message
return
end
PlayerLoaded[plr.UserId] = true
if Result then -- If there are no errors, Result is the data
print(Result)
print("got savedata")
local savedValues = Result[1]
local savedItems = Result[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
end
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()
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)
local data = Instance.new("Folder",plr)
data.Name = "Data"
local bannedbool = Instance.new("BoolValue")
bannedbool.Parent = data
bannedbool.Name = "Banned"
bannedbool.Value = false
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 ownsfloor2 = Instance.new("BoolValue",data)
ownsfloor2.Name = "OwnsFloor2"
ownsfloor2.Changed:Connect(function()
local floor2 = plot.Floor2Val.Value
floor2.Parent = plot
floor2.Character11.Parent = plot.Spots
floor2.Character12.Parent = plot.Spots
floor2.Character13.Parent = plot.Spots
floor2.Character14.Parent = plot.Spots
floor2.Character15.Parent = plot.Spots
end)
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
local function setupcharacterval(i)
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:WaitForChild(character.Name)
characterbody.PrimaryPart.CFrame = game.Workspace.Plots:FindFirstChild(plr.Name).Spots:WaitForChild(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 rarity == "Celestial" and mutation.Value ~= "" then
mutation.Value = ""
end
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
elseif mutationtype == "Molten" then
local oldincome
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v.Name == characterbody.Name then
oldincome = v:GetAttribute("Income")
end
end
label.BillboardGui.Mutations.TextColor3 = Color3.new(1, 0.364706, 0.113725)
characterbody:SetAttribute("Income",oldincome*10)
label.BillboardGui.Income.Text = (characterbody:GetAttribute("Income")).."/s"
local moltenrocks = game.ReplicatedStorage.MoltenRocks:Clone()
moltenrocks.Parent = characterbody
moltenrocks.CFrame = characterbody.HumanoidRootPart.CFrame
local wc = Instance.new("WeldConstraint")
wc.Parent = moltenrocks
wc.Part0 = characterbody.HumanoidRootPart
wc.Part1 = moltenrocks
for _,v in pairs(game.ReplicatedStorage.MoltenMutation:GetChildren()) do
for __,vv in pairs(characterbody:GetChildren()) do
if vv:IsA("BasePart") then
v:Clone().Parent = vv
end
end
end
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.470588, 0.164706)
end
end
elseif mutationtype == "Scorched" then
local oldincome
for _,v in pairs(game.ReplicatedStorage.Characters:GetDescendants()) do
if v.Name == characterbody.Name then
oldincome = v:GetAttribute("Income")
end
end
label.BillboardGui.Mutations.TextColor3 = Color3.new(0.239216, 0.207843, 0.172549)
characterbody:SetAttribute("Income",oldincome*2)
label.BillboardGui.Income.Text = (characterbody:GetAttribute("Income")).."/s"
for _,v in pairs(game.ReplicatedStorage.ScorchedMutation:GetChildren()) do
for __,vv in pairs(characterbody:GetChildren()) do
if vv:IsA("BasePart") then
v:Clone().Parent = vv
end
end
end
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.219608, 0.196078, 0.184314)
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
for i=1,15 do
setupcharacterval(i)
end
pcall(function()
yenLeaderboard:SetAsync(plr.UserId, math.round(plr.Data.Yen.Value))
end)
if yen.Value > 50000000000000 then
bannedbool.Value = true
end
yen.Changed:Connect(function(val)
yenleaderstat.Value = val
end)
rebirths.Changed:Connect(function(val)
rebirthsleaderstat.Value = val
if val >= 3 then
plr.Data.OwnsFloor2.Value = true
end
end)
if bannedbool.Value == true then
plr:Kick("You've been banned")
end
bannedbool.Changed:Connect(function()
if bannedbool.Value == true then
plr:Kick("You've been banned")
end
end)
LoadData(plr,plot,items,timeleft)
while task.wait(120) do
if plr then
savedata(plr,1)
end
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
local plot = game.Workspace.Plots:FindFirstChild(plr.Name)
for _,v in pairs(plot.Spots:GetChildren()) do
if v:FindFirstChildWhichIsA("Model") then
v:FindFirstChildWhichIsA("Model"):Destroy()
v.Claim.BillboardGui.TextLabel.Text = ""
end
end
if plot:FindFirstChild("Floor2") then
local floor2 = plot.Floor2Val.Value
floor2.Parent = game.ReplicatedStorage
plot.Spots.Character11.Parent = floor2
plot.Spots.Character12.Parent = floor2
plot.Spots.Character13.Parent = floor2
plot.Spots.Character14.Parent = floor2
plot.Spots.Character15.Parent = floor2
end
plot.Lasers.Block.CanCollide = false
for _,v in pairs(plot.Lasers:GetChildren()) do
if v.Name == "Part" then
v.Transparency = 1
end
end
plot.Name = "Unclaimed"
plot.NameTag.BillboardGui.TextLabel.Text = "Empty Base"
savedata(plr,3)
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,4)
end)
if not success then
warn("Failed to save data for "..plr.Name..": "..err)
end
end
-- Give time for datastore requests to complete
wait(4)
end)