I am making a datastore in which values will be saved in a table and put in a datastore’s scope.
It worked fine when I had only loops to create and store values for “images”, but adding the sound saving messed it in a weird way. It saves all values and loads back the same number of them, but they are all copies of the “Dog” value as seen here:
Before leaving
After rejoining
Before anyone mentions I am in server test mode!
Sometimes when I try changing anything it doesn’t even load anything.
This is the script, I don’t know if I’m doing it wrong or missing something that may affect this behavior:
local DataStoreService = game:GetService("DataStoreService")
local ImageStore = DataStoreService:GetDataStore("FOS_Data", "Images")
local SoundStore = DataStoreService:GetDataStore("FOS_Data", "Sounds")
local DocsStore = DataStoreService:GetDataStore("FOS_Data", "Docs")
local ProgramStore = DataStoreService:GetDataStore("FOS_Data", "Programs")
local function onPlayerJoin(player)
local FileDrive = Instance.new("Folder")
FileDrive.Name = "FOS_DRIVE"
FileDrive.Parent = player
local ImagePart = Instance.new("Folder")
ImagePart.Name = "FOS_Images"
ImagePart.Parent = FileDrive
local SoundPart = Instance.new("Folder")
SoundPart.Name = "FOS_Sounds"
SoundPart.Parent = FileDrive
local playerUserId = "Player_" .. player.UserId
local ImageData = ImageStore:GetAsync(playerUserId)
local SoundData = SoundStore:GetAsync(playerUserId)
if ImageData then
for i, v in pairs(ImageData) do
local DataPiece = Instance.new("StringValue")
DataPiece.Name = v["Name"]
DataPiece.Value = v["ID"]
DataPiece:SetAttribute("CreationDate", v["CreationDate"])
DataPiece:SetAttribute("Path", v["Path"])
DataPiece.Parent = ImagePart
end
end
if SoundData then
for i, v in pairs(ImageData) do
local DataPiece = Instance.new("StringValue")
DataPiece.Name = v["Name"]
DataPiece.Value = v["ID"]
DataPiece:SetAttribute("CreationDate", v["CreationDate"])
DataPiece:SetAttribute("Path", v["Path"])
DataPiece.Parent = SoundPart
end
end
end
local function onPlayerExit(player)
local success, err = pcall(function()
local FileDrive = player.FOS_DRIVE
local playerUserId = "Player_" .. player.UserId
local Images = {}
for i, v in pairs(FileDrive.FOS_Images:GetChildren()) do
local Image = {
["Name"] = v.Name,
["ID"] = v.Value,
["CreationDate"] = v:GetAttribute("CreationDate"),
["Path"] = v:GetAttribute("Path")
}
table.insert(Images, Image)
end
local Sounds = {}
for i, v in pairs(FileDrive.FOS_Sounds:GetChildren()) do
local Sound = {
["Name"] = v.Name,
["ID"] = v.Value,
["CreationDate"] = v:GetAttribute("CreationDate"),
["Path"] = v:GetAttribute("Path")
}
table.insert(Sounds, Sound)
end
ImageStore:SetAsync(playerUserId, Images)
SoundStore:SetAsync(playerUserId, Sounds)
end)
if not success then
warn('Error saving data:')
print(err)
end
end
game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
The values aren’t currently affected by any other scripts.
in this line, are you supposed to be going through the same loop as above?
I believe your problem is you are not looking through SoundData. Try changing ImageData to SoundData in the loop that checks for SoundData.
I didn’t even notice it, thanks! But the values still don’t act as they should. If I place a “Dog” value into images, then restart, it places a “Dog” value into sounds. Even if I do anything else, same result. The problem now is most likely saving data, but it also doesn’t print any errors, which is odd. Could any loop maybe break anything?
Edit 1 2 and 3: I never used the scope parameter, so at first I thought that you were using the scope field wrong. However, it looks like it should work. Though I’m not sure why it’s not working, I think the below could still possibly fix it. Instead of using scope parameter, just combine it to the datastore name and only use the first parameter.
Example:
local ImageStore = DataStoreService:GetDataStore("FOS_Data" .. "Images")
local SoundStore = DataStoreService:GetDataStore("FOS_Data" .. "Sounds")
local DocsStore = DataStoreService:GetDataStore("FOS_Data" .. "Docs")
local ProgramStore = DataStoreService:GetDataStore("FOS_Data" .. "Programs")
If you’re still having issues, I’ll look into it more when I have the time.
bind a function to game:BindToClose(func) that’ll iterate over all the players to save their data, roblox wont shutdown the game as long as the function is yielding or has exceeded a exhaust and when you shutdown within studio it’ll only call bindtoclose and not playerremoving.
Your suggestion worked for the first time, but failed to save any attempt later. What you suggested is pretty much making 4 different datastores, but the scopes behave in the same way anyways.
Like here:
First two lines describe values being transferred into tables for storage, and the third just tells the code is at the :SetAsync lines here:
print(start val saving)
ImageStore:SetAsync(playerUserId, Images)
print(Image vals saved)
SoundStore:SetAsync(playerUserId, Sounds)
print(Saved all vals)
As seen it only prints it came to those lines, just not executed them.
Is there a bug or it’s acting normal, just not in my favor?
Now I’ve made an extra function like you suggested, to detect if you’re in studio and wait some time so that datastores have time to save all the data. Simply just this:
game:BindToClose(function()
if game:GetService("RunService"):IsStudio() then
wait(3)
end
end)
Studio does detect a PlayerRemoving, it just closes so fast datastores can’t catch up.
That and @kaorukoSE notice about the error in the code solved all the problems. Thanks to anyone that replied with a suggestion.