Hey there! So i tried my best. I tried my best to not post a dev forum post but dang it i have been stressing out on how to fix this bug.
Let’s say i have a hoverboard system and everytime someone leaves the game it saves for the player.
Well it doesn’t work. I can’t even explain it, im just out of words.
local Players = game:GetService("Players")
local DataStore = game:GetService("DataStoreService"):GetDataStore("hov3rboard")
local ServerStorage = game:GetService("ServerStorage")
local Storage = ServerStorage:WaitForChild("Storage")
-- >>: Server Communation
local ServerComms = Storage:WaitForChild("ServerComms")
local UnlockedEvent = ServerComms:WaitForChild("UnlockedHoverboard")
Players.PlayerAdded:Connect(function(plr)
local PlayerFolder = ServerStorage:WaitForChild(plr.Name)
local PlayerGui = plr:WaitForChild("PlayerGui")
local Hoverboards = PlayerGui:WaitForChild("Hoverboards")
repeat
task.wait()
warn("Player folder not found")
until PlayerFolder
local data = DataStore:GetAsync(tostring(plr.UserId).."_p3e37a")
for _, v in pairs(Hoverboards:GetDescendants()) do
if v:FindFirstChild("Unlocked") then
if data then
for _, v1 in pairs(data) do
if v1.Name == v.Name then
v.Unlocked.Value = v1.Unlocked
end
end
end
end
end
end)
local function saveData(plr)
print("saving data for: "..plr.Name)
local pF = game:GetService("ServerStorage")[plr.Name]
local inventory = {}
local PlayerGui = plr:WaitForChild("PlayerGui")
local Hoverboards = PlayerGui:WaitForChild("Hoverboards")
for _, v in pairs(Hoverboards:GetDescendants()) do
if v:FindFirstChild("Unlocked") then
inventory[#inventory + 1] = {
Name = v.Name,
Unlocked = v.Unlocked.Value
}
end
end
local success, errorMessage = pcall(function()
DataStore:SetAsync(tostring(plr.UserId).."_p3e37a",inventory)
end)
if success then
print("Hoverboard Data saved " .. plr.Name)
else
warn(plr.Name .. " :Error: " ..errorMessage)
end
end
UnlockedEvent.Event:Connect(function(plr,hoverboard)
print("sent: "..hoverboard)
local PlayerGui = plr:WaitForChild("PlayerGui")
local Hoverboards = PlayerGui:WaitForChild("Hoverboards")
local areaval = Hoverboards:GetDescendants()
if not areaval then return end
for _, v in pairs(areaval) do
if v:FindFirstChild("Unlocked") and v.Name == hoverboard then
v.Unlocked.Value = true
end
end
saveData(plr)
end)
Players.PlayerRemoving:Connect(function(plr)
saveData(plr)
end)
game:BindToClose(function()
for _, player in pairs(game:GetService("Players"):GetPlayers()) do
saveData(player)
end
end)
DataStoreService can sometimes cause data loss, you should repeat the saving and loading until it saves and loads or use DataStore2, its very reliable and safe
I dont think it will, it works for the first hoverboard then when i changed the datastore name and changed the first hoverboard’s value to true it still said false
I change the hoverboard value, i save without leaving and i rejoin and it doesn’t save, its still false even tho i saved it after i set the value to true.
Use this to save the Data (just put the rest (load data, etc. above it):
--Vars and Services
local DataStore = game:GetService("DataStoreService"):GetDataStore("MainDatastore")
--Functions
function formatData(player)
local data = {}
local PlayerGui = player:WaitForChild("PlayerGui")
local Hoverboards = PlayerGui:WaitForChild("Hoverboards")
local inventory = {}
for i,piece in pairs(Hoverboards:GetDescendants()) do
if piece:FindFirstChild("Unlocked") then
table.insert(inventory, piece.Name, piece.Unlocked.Value)
end
end
table.insert(data, inventory)
return data
end
function saveData(player)
local Key = "Player_"..player.UserId
local stuffToSave = formatData(player)
local succes, err = pcall(function()
if stuffToSave then
DataStore:SetAsync(Key, stuffToSave)
end
end)
if err then
warn('WARNING: COULD NOT SAVE PLAYER DATA: '..err)
end
end
function onServerShutdown()
if game:GetService("RunService"):IsStudio() then
wait(2)
else
for _, player in pairs(game.Players:GetPlayers()) do
local finished = Instance.new("BindableEvent")
saveData(player) --It's easier to use the previous saveData function on each player than it is to write new code
finished.Event:Wait()
end
end
end
--Binding Events
game:BindToClose(onServerShutdown)
game.Players.PlayerRemoving:Connect(saveData)
EDIT: forgot to say, you have to modify the “loadData” function so it properly loads the data to the game
Edit: didn’t work, Its weird because it prints “saving data for: WhatDid_HeDo” which prints when the function gets called but “Hoverboard Data saved WhatDid_HeDo” doesn’t print.
Seems to work when i try the “test” menu. Maybe the “Stop” button in studio is just inconsistent with bindtoclose? Im still curious on why this happens tho
It perfectly works 5 times a row when i used the “test” menu instead of the “play” button. For some reason bindtoclose is inconsistent when using the “stop” button for me.
Whenever i press “cleanup” it disconnects the client and studio doesn’t respond for a second. I rejoin and it saves.
Does not work in actual roblox severs…
Works in game when there is another player and the sever doesn’t shut down, its def bindtoclose…