I'm trying to make some kind of save file. Here's how I'm trying to do that: first I get 1 data store with a dictionary having the default values like money, then a 2nd data store to know if you already got the default one so it won't erase your progress. I have the dictionary data store go into a module (playerInfo) that I will modify and eventually save, only when you leave, so I don't use SetAsync or UpdateAsync too much. Once I enter, the default data store is successfully set and prints it in the output, but when I leave it doesn't set the new version of it. No errors in the output.
local Players = game:GetService("Players") local DataStoreService = game:GetService("DataStoreService") local playerSaveFile = DataStoreService:GetDataStore("playerSaveFile") local playerFirstJoined = DataStoreService:GetDataStore("playerFirstJoined") Players.PlayerAdded:Connect(function(player) playerFirstJoined:SetAsync(player.UserId, "new") end) local playerDefaultStatus = {nothing = "here", pls = "move on"} Players.PlayerAdded:Connect(function(player) if playerFirstJoined:GetAsync(player.UserId) == "new" then (here goes another part that doesn't affect in any way the next, it works so I won't include it pls no cancel) Players.PlayerRemoving:Connect(function(player) playerFirstJoined:SetAsync(player.UserId, "old") local success, err = pcall(function() playerSaveFile:UpdateAsync(player.UserId, function(oldValue) local playerInfo = require(workspace.playerInfo) local newValue = playerInfo.playerModuleSF or oldValue return newValue end) end) if success then print(player.Name.."'s save file was updated.") end end)
Modulescript:
local PlayerInfo = {} Players = game:GetService("Players") function PlayerInfo.playerModule (player) local playerModuleSF = game:GetService("DataStoreService"):GetDataStore("playerSaveFile"):GetAsync(player.UserId) return playerModuleSF end Players.PlayerAdded:Connect(PlayerInfo.playerModule) return PlayerInfo
The immediate problem is this code here, where you're saving the player as new (and then immediately checking if they're new, even though you've just assigned them to new.) I suspect you're overriding the player's data with the default data within there
Players.PlayerAdded:Connect(function(player) playerFirstJoined:SetAsync(player.UserId, "new") end) Players.PlayerAdded:Connect(function(player) if playerFirstJoined:GetAsync(player.UserId) == "new" then ... end end)
And the most immediate solution is to instead check if the data is nil
(since that's the default value if nothing's been saved) and to assign some other value once they're leaving.
Players.PlayerAdded:Connect(function(player) if playerFirstJoined:GetAsync(player.UserId) == nil then ... end end) Players.PlayerRemoving:Connect(function(player) playerFirstJoined:SetAsync(player.UserId, true) end)
Now I'm calling these immediate since they're the most direct solution, however, there's some bad design in your code
The problem is that you trust datastores a bit too much. They're prone to erroring if you make set/get requests fast, or just because it feels like it lol. Specifically, you're using another datastore to check if they're new when instead you should take advantage that all their data would be nil if they were new, and also you're making some unnecessary calls to the datastore. A solution would instead to cache the data in the module, which could be saved and retrieved very quickly without worrying about making too many calls to the datastore. Once the player leaves, the cached data can be saved
Players.PlayerAdded:Connect(function(player) local data local success, err = pcall(function() data = playerSaveFile:GetAsync(player.UserId) end) if not success then warn(err) end playerInfo.SaveData(player, data or defaultValue) --Taking advantage of how the or operator evaluates to the second operand if the first is nil (or false.) end) Players.PlayerRemoving:Connect(function(player) local success, err = pcall(function() playerSaveFile:UpdateAsync(player.UserId, function(oldValue) local newValue = playerInfo.GetData(player) or oldValue return newValue end) end) if success then print(player.Name.."'s save file was updated.") end end)
Module Script:
local PlayerInfo = {} local cachedData = {} --Holds player data instead of making calls to the datastore. You could use this to periodically save every players' data every few minutes or so function PlayerInfo.SaveData(player, data) cachedData[player] = data end function PlayerInfo.GetData(player) return cachedData[player] end Players.PlayerRemoving:Connect(function(player) --Cleanup cachedData[player] = nil end) return PlayerInfo