Basically I have a problem where it saves perfectly fine in studio and in game for me. However I am getting complaints from the players saying that there data isnt being saved properly. I have 2 datastore scripts (which I believe is the problem). One is the old datastore script which holds all the olds players values until it completely stopped working. Then the new one which transfers old data to the new datastore.
Im not sure what is causing the issue. But heres the sever side script:
local playerDataStore = DataStoreService:GetDataStore("Data_")
local ShopItems = require(game.ReplicatedStorage:WaitForChild("ShopItems"))
local BadgesMod = require(game.ReplicatedStorage:WaitForChild("Badges"))
game.Players.PlayerAdded:Connect(function(player)
local Gears = Instance.new("Folder",player)
Gears.Name = "Gears"
local Effects = Instance.new("Folder",player)
Effects.Name = "Effects"
local Transport = Instance.new("Folder",player)
Transport.Name = "Transport"
local InventoryItems = Instance.new("Folder",player)
InventoryItems.Name = "InventoryItems"
local Badges = Instance.new("Folder",player)
Badges.Name = "Badges"
local Nametags = Instance.new("Folder",player)
Nametags.Name = "Nametags"
for i,v in pairs(ShopItems["Gears"]) do
Instance.new("BoolValue", Gears).Name = tostring(i)
end
for i,v in pairs(ShopItems["Effects"]) do
Instance.new("BoolValue", Effects).Name = tostring(i)
end
for i,v in pairs(ShopItems["Transport"]) do
Instance.new("BoolValue", Transport).Name = tostring(i)
end
for i,v in pairs(ShopItems["Nametags"]) do
Instance.new("BoolValue", Nametags).Name = tostring(i)
end
for i,v in pairs(BadgesMod["Badges"]) do
Instance.new("BoolValue", Badges).Name = tostring(i)
end
local NewLeaderstats = Instance.new("Folder",player)
NewLeaderstats.Name = "leaderstats"
local Points = Instance.new("IntValue", NewLeaderstats)
Points.Name = "Points"
local Survivals = Instance.new("IntValue", NewLeaderstats)
Survivals.Name = "Survivals"
local Equip = Instance.new("Folder",player)
Equip.Name = "Equipped"
local GearEquip = Instance.new("Folder", Equip)
GearEquip.Name = "Gears"
local EffectEquip = Instance.new("StringValue", Equip)
EffectEquip.Name = "Effects"
local TransportEquip = Instance.new("Folder", Equip)
TransportEquip.Name = "Transport"
local Joined = Instance.new("BoolValue", player)
Joined.Name = "Joined"
-- NEW --
local Nametag = Instance.new("StringValue", Equip)
Nametag.Name = "Nametags"
wait(1)
local success, errormsg = pcall(function() -- a pcall will run even if the script has an error and you can check if it is an error with errormsg or success but the name doesn't matter
local data, Success, ErrorMsg
local Attempts = 4
repeat
Attempts -= 1
Success, ErrorMsg = pcall(function()
data = playerDataStore:GetAsync(player.UserId)
end)
if not Success then wait(1) end
until
Success or Attempts == 0 or not game.Players:GetPlayerByUserId(player.UserId)
if data ~= nil then
if data[1] ~= nil then
for i, dataval in pairs(data[1]) do
if dataval[4] == "Equip" or dataval[4] == "InventoryItems" then
local stat
if dataval[4] == "Equip" then
stat = player:WaitForChild("Equipped"):WaitForChild(dataval[5])
else
stat = player:WaitForChild("InventoryItems")
end
local instance = Instance.new(dataval[3])
if instance then
instance.Name = dataval[1]
instance.Parent = stat
local Tool = game.ServerStorage.ShopItems:FindFirstChild(dataval[1]):Clone()
Tool.Parent = player.Backpack
end
else
local stat = player:WaitForChild(dataval[4])
if stat:FindFirstChild(dataval[1]) then
print(dataval[4], dataval[1])
stat:FindFirstChild(dataval[1]).Value = dataval[2]
else
local instance = Instance.new(dataval[3])
if instance then
instance.Name = dataval[1]
instance.Value = dataval[2]
instance.Parent = stat
end
end
end
end
end
if data[2] ~= nil then
Points.Value = data[2]
end
if data[3] ~= nil then
Survivals.Value = data[3]
end
if data[4] ~= nil then
EffectEquip.Value = data[4]
end
if data[5] ~= nil then
Joined.Value = data[5]
end
if data[6] ~= nil then
Nametag.Value = data[6]
end
else
playerDataStore:SetAsync(player.UserId, {})
wait(6)
Points.Value = player.oldleaderstats.Points.Value
Survivals.Value = player.oldleaderstats.Survivals.Value
end
print("Loaded ["..player.Name.."] Data")
end)
if errormsg then
print(errormsg)
end
if EffectEquip.Value ~= "" then
local Tool = game.ServerStorage.ShopItems:FindFirstChild(EffectEquip.Value):Clone()
if Tool:IsA("ParticleEmitter") then
Tool.Parent = player.Character:FindFirstChild("HumanoidRootPart")
elseif Tool:IsA("Trail") then
local Attachment0
local Attachment1
if player.Character:FindFirstChild("Head"):FindFirstChild("TrailAttachment0") then
Attachment0 = player.Character:FindFirstChild("Head"):FindFirstChild("TrailAttachment0")
else
Attachment0 = Instance.new("Attachment", player.Character:FindFirstChild("Head"))
Attachment0.Name = "TrailAttachment0"
end
if player.Character:FindFirstChild("HumanoidRootPart"):FindFirstChild("TrailAttachment1") then
Attachment1 = player.Character:FindFirstChild("HumanoidRootPart"):FindFirstChild("TrailAttachment1")
else
Attachment1 = Instance.new("Attachment", player.Character:FindFirstChild("HumanoidRootPart"))
Attachment1.Name = "TrailAttachment1"
end
Tool.Attachment0 = Attachment0
Tool.Attachment1 = Attachment1
Tool.Parent = player.Character:FindFirstChild("Head")
end
end
if Nametag.Value ~= "" then
local nt = game.ServerStorage.ShopItems:FindFirstChild(Nametag.Value):Clone()
if nt then
nt.Parent = player.Character:FindFirstChild("Head")
nt.Adornee = player.Character:FindFirstChild("Head")
end
end
game.Players.PlayerRemoving:Connect(function(leavingPlayer)
if leavingPlayer.userId == player.UserId then -- Check if the leaving player is the same player that joined so we can save their data correctly
local Data = playerDataStore:GetAsync(player.UserId)
local objData = {}
for i, obj in pairs(Gears:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Gears"})
end
for i, obj in pairs(Effects:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Effects"})
end
for i, obj in pairs(Transport:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Transport"})
end
for i, obj in pairs(GearEquip:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Equip", "Gears"})
end
for i, obj in pairs(TransportEquip:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Equip", "Transport"})
end
for i, obj in pairs(InventoryItems:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "InventoryItems"})
end
for i, obj in pairs(Nametags:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Nametags"})
end
for i, obj in pairs(Badges:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Badges"})
end
if Data == nil then
playerDataStore:SetAsync(player.UserId, {
objData,
Points.Value,
Survivals.Value,
EffectEquip.Value,
Joined.Value,
Nametag.Value,
})
else
playerDataStore:UpdateAsync(player.UserId, function(oldValue)
oldValue = {objData,
Points.Value,
Survivals.Value,
EffectEquip.Value,
Joined.Value,
Nametag.Value,
}
return {objData,
Points.Value,
Survivals.Value,
EffectEquip.Value,
Joined.Value,
Nametag.Value,
}
end)
end
print("Saved ["..leavingPlayer.Name.."] Data")
end
end)
end)
game:BindToClose(function()
for i,plr in pairs(game.Players:GetPlayers()) do
local Data = playerDataStore:GetAsync(plr.UserId)
local objData = {}
for i, obj in pairs(plr.Gears:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Gears"})
end
for i, obj in pairs(plr.Effects:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Effects"})
end
for i, obj in pairs(plr.Transport:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Transport"})
end
for i, obj in pairs(plr.Equipped.Gears:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Equip", "Gears"})
end
for i, obj in pairs(plr.Equipped.Transport:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Equip", "Transport"})
end
for i, obj in pairs(plr.InventoryItems:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "InventoryItems"})
end
for i, obj in pairs(plr.Nametags:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Nametags"})
end
for i, obj in pairs(plr.Badges:GetChildren()) do
table.insert(objData, {obj.Name, obj.Value, obj.ClassName, "Badges"})
end
if Data == nil then
playerDataStore:SetAsync(plr.UserId, {
objData,
plr.leaderstats.Points.Value,
plr.leaderstats.Survivals.Value,
plr.Equipped.Effects.Value,
plr.Joined.Value,
plr.Equipped.Nametags.Value,
})
else
playerDataStore:UpdateAsync(plr.UserId, function(oldValue)
oldValue = {objData,
plr.leaderstats.Points.Value,
plr.leaderstats.Survivals.Value,
plr.Equipped.Effects.Value,
plr.Joined.Value,
plr.Equipped.Nametags.Value,
}
return {objData,
plr.leaderstats.Points.Value,
plr.leaderstats.Survivals.Value,
plr.Equipped.Effects.Value,
plr.Joined.Value,
plr.Equipped.Nametags.Value,
}
end)
end
end
end)
Ive researched as much as I can and made some tweaks to the script. Nothing much has changed though since it still inconsistently doesn’t save.
I need a solution or any help urgently since the game is public and has around 500 active players. Any help is appreciated