Hello,
Problem: My DataStore is not saving the Leaderstats or the Tools once a player leaves/returns to the Game.
Information: When a player makes a purchase, the RemoteEvent fires up, enabling the BoolValues for the Tools to be True. The BoolValues are located inside a Folder named "Inventory" inside the player's Backpack. And there's a script thats set to clone the Tools into the StarterGear and Backpack. That part all seems to work perfectly. Its when the player leaves a game and returns, that the data is not being saved. There's no Output showing that the DataStore has failed, and I made sure the API Services were enabled.
The DataStore script is a Module Script inside ServerScriptService.
Any idea how to fix this to function properly?
My Module Script is below:
local module = {} local DataStoreService = game:GetService("DataStoreService") local InventoryItems = DataStoreService:GetDataStore("TEST") AUTOSAVE_INTERVAL = 120 game.Players.PlayerAdded:Connect(function(Player) local Key = "PlayerIdNum-"..Player.UserId.."_ToolItems" --leaderstats local inew = Instance.new local ls = inew("Folder") ls.Name = "leaderstats" ls.Parent = Player local points = inew("IntValue") points.Name = "Points" points.Value = 0 points.Parent = ls local experience = inew("IntValue") experience.Name = "Experience" experience.Value = 0 experience.Parent = ls local level = inew("IntValue") level.Name = "Level" level.Value = 1 level.Parent = ls --Inventory local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory") local HasGun = InvData:WaitForChild("HasGun") --Saving Data local StoreToSet = {} local DataToGet = InventoryItems:GetAsync(Key) if DataToGet ~= nil then if #DataToGet >= 1 then if DataToGet[1] ~= nil then HasGun.Value = DataToGet[1] table.insert(StoreToSet, DataToGet[1]) else DataToGet[1] = HasGun.Value HasGun.Value = false table.insert(StoreToSet, DataToGet[1]) end end else DataToGet = {} DataToGet[1] = HasGun.Value HasGun.Value = false table.insert(StoreToSet, DataToGet[1]) print("New Data") end InventoryItems:SetAsync(Key, StoreToSet) repeat wait() until Player.Character if Player.Character and Player.Character:FindFirstChild("Humanoid") then Player.Character.Humanoid.MaxHealth = 100 + (level.Value*10) end level.Changed:Connect(function(value) if Player.Character and Player.Character:FindFirstChild("Humanoid") then Player.Character.Humanoid.MaxHealth = 100 + (level.Value*10) end end) Player.CharacterAdded:Connect(function(character) character:WaitForChild("Humanoid").MaxHealth = 100 + (level.Value*10) end) local required = (level.Value*70) experience.Changed:Connect(function() if experience.Value >= required then level.Value=level.Value+1 experience.Value = experience.Value-required end end) end) -- PLAYER REMOVING game.Players.PlayerRemoving:Connect(function(Player) local Key = "PlayerIdNum-"..Player.UserId.."_ToolItems" local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory") local ls = Player:WaitForChild("leaderstats") local HasGun = InvData:WaitForChild("HasGun") local points = ls:WaitForChild("Points") local exp = ls:WaitForChild("Experience") local level = ls:WaitForChild("Level") local DataToSave = { HasGun.Value, points.Value, exp.Value, level.Value, } InventoryItems:SetAsync(Key, DataToSave) end) spawn(function() while wait(AUTOSAVE_INTERVAL) do for i, Player in pairs (game:GetService("Players"):GetChildren()) do --for every player in the game, save print("Auto-saving " .. Player.Name .. "'s Data") local Key = "PlayerIdNum-"..Player.UserId.."_ToolItems" local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory") local ls = Player:WaitForChild("leaderstats") local HasGun = InvData:WaitForChild("HasGun") local points = ls:WaitForChild("Points") local exp = ls:WaitForChild("Experience") local level = ls:WaitForChild("Level") local DataToSave = { HasGun.Value, points.Value, exp.Value, level.Value, } InventoryItems:SetAsync(Key, DataToSave) print("Successfully Auto-saved " .. Player.Name .. "'s Data") end end end) return module
It's awfully disturbing to read code without indentation and general lack of formality, but what you seek is usage of BindToClose() which simply tells the server to stay open up to 30 seconds for you to do whatever needs to be done when the last player in the server leaves it.
game:BindToClose(function() --the code that stalls the ending of the server goes here end)
--personally I don't use this example but it's a start lol local canCloseServer game.Players.PlayerRemoving:Connect(function(plr) saveStats(plr) if game.Players.NumPlayers < 1 then canCloseServer = true end end) game:BindToClose(function() repeat wait(1) until canCloseServer end)
http://wiki.roblox.com/index.php?title=API:Class/DataModel/BindToClose