Greetings developers, I’m Dani. My issue is I don’t really know how to DataStore, so if anyone knows what’s wrong with my script, it’d be nice if you could tell me… (lol). The main issue that I believe is saving the values (the PlayerRemoving portion of the script or maybe the SecData part). So to explain the script I’m taking items out of a folder and “converting” them into a bool value inside the player (the bool values being the child of a instance folder mentioned in the script called “PlayerOwn”) , throughout other scripts I’m simply setting a few values to true (dependent on the player and choices etc) but when the player rejoins the values don’t save, so my guess is that this saving script is the apparent reason to my problem (I also tested and 99% sure saving the data is the issue here) so if anyone notices any possible causes for the issue with saving please let me know!
local DataStoreService = game:GetService("DataStoreService")
local SecondDataStore = DataStoreService:GetDataStore("PlayerOwn")
local srvrss = game:GetService("ServerScriptService")
local ss = game:GetService("ServerStorage")
game.Players.PlayerAdded:Connect(function(Player)
local PlayerOwn = Instance.new("Folder")
PlayerOwn.Name = "PlayerOwn"
PlayerOwn.Parent = Player
for i, v in pairs(ss:WaitForChild("Props"):WaitForChild("Shop"):GetChildren()) do
if v.ClassName == "Tool" then
local new = Instance.new("BoolValue")
new.Name = v.Name
new.Value = false
new.Parent = PlayerOwn
print(new.Value)
end
end
local SecData
pcall(function()
SecData = SecondDataStore:GetAsync(Player.UserId)
end)
if type(SecData) ~= "table" then
SecData = nil
end
if SecData then
for i, v in pairs(Player:WaitForChild("PlayerOwn"):GetChildren()) do
if v.ClassName == "BoolValue" then
v.Value = SecData[v]
end
end
end
end)
game.Players.PlayerRemoving:Connect(function(Player)
for i, v in pairs(Player:WaitForChild("PlayerOwn"):GetChildren()) do
if v.ClassName == "BoolValue" then
SecondDataStore:SetAsync(Player.UserId, {
[v.Name] = Player.PlayerOwn[v].Value
})
end
end
end)
when the last player leaves the game the server starts to shutdown and it does not wait for you to save data into the datastore so you must use DataModel:BindToClose to stop the server from shutting down to give you enough time to save to the datastore
here is some code i made to help someone else and it covers almost everything i listed above so you can maybe use it to help you
local playerLoaded = {}
game.Players.PlayerAdded:Connect(function(player)
-- when the player enters the game try to load there data
local success, value = pcall(dataStore.GetAsync, dataStore, player.UserId)
if success == false then return end
-- if the value = nil then set value to a empty table
value = value or {}
-- clone the data folder inside this script with all its values
local folder = script.Data:Clone()
-- loop all values and set them to match what was last saved in the datastore
for i, child in ipairs(folder) do child.Value = value[child.Name] or child.Value end
-- place the folder into the player
folder.Parent = player
-- set the playerloaded to true so we can keep track if there are players loaded so that bind to close can wait
playerLoaded[player] = true
end)
game.Players.PlayerRemoving:Connect(function(Player)
-- if player loaded == nil meaning the player failed to load when they entered we simple exit because we dont want to overwrite the old data
if playerLoaded[player] == nil then return end
-- create a table and set the the values from there data folder
local playerData = {}
for i, child in ipairs(player.Data:GetChildren()) do
playerData[child.Name] = child.Value
end
-- now save this table to the datastore
local success, value = pcall(dataStore.SetAsync, dataStore, player.UserId, playerData)
-- now set playerLoaded to nil so that bindtoclose can stop looping and allow the server to close
playerLoaded[player] = nil
end)
-- while players are loaded dont close the server (only works upto 30 seconds)
game:BindToClose(function()
while next(playerLoaded) ~= nil do
task.wait()
end
end)