What's wrong with this DataStore?

Hello! I’ve tried my best the past couple of days in saving a player’s inventory, for some reason, no matter what I try, Roblox just decides to not save it sometimes (not all of the time).
Could anyone help?

local DataStore = game:GetService("DataStoreService"):GetDataStore("PlayerSave3")
local mps = game:GetService("MarketplaceService")
local http = game:GetService("HttpService")
local debounce = true


game.Players.PlayerAdded:Connect(function(plr) 
	
	task.wait(5)
	
	local inventory = {}

	local leaderstats = Instance.new('Folder') 
	leaderstats.Name = "leaderstats" 
	leaderstats.Parent = plr 
	
	local gems = Instance.new("NumberValue") 
	gems.Name = "Dollars" 
	gems.Parent = leaderstats 
	
	local itemFolder = Instance.new('Folder')
	itemFolder.Name = "ItemFolder"
	itemFolder.Parent = plr
	
	local gemsData 
	
	local success,errormessage = pcall(function()   
		gemsData = DataStore:GetAsync("Dollars"..plr.UserId) 
		inventory = http:JSONDecode(DataStore:GetAsync("Inventory"..plr.UserId))
		print("Printing "..plr.Name.."'s inventory!")
		for i, v in pairs(inventory) do       -- this sometimes doesn't print, meaning it either didn't save or didn't load
			print(v)   
		end
	end)
	
	if success then  
		if gemsData then
			gems.Value = gemsData
		end
		
		if inventory then
			repeat wait() until plr.Team ~= game:GetService("Teams"):WaitForChild("Unemployed")
			 
			local invFolder 
			
			if plr.Team ~= nil then
				plr.PlayerGui.Buttons.Warning.Text = "Loading Data"
				task.wait(1.5)
				invFolder = game:GetService("ServerStorage"):FindFirstChild(tostring(plr.Team.Name))
				plr.PlayerGui.Buttons.Warning.Text = "Successfully loaded data!"
				wait(1)
				plr.PlayerGui.Buttons.Warning.Text = ""
			end
					
			if invFolder then
				for i, v in pairs(inventory) do
					if invFolder:FindFirstChild(v) then
						invFolder[v]:Clone().Parent = workspace.Tycoons:FindFirstChild(tostring(plr.Team.Name)).PurchasedObjects
						invFolder[v]:Clone().Parent = itemFolder
						for _, object in pairs(workspace.Tycoons[tostring(plr.Team.Name)].Buttons:GetChildren()) do
							if workspace.Tycoons[tostring(plr.Team.Name)].PurchasedObjects:FindFirstChild(object.Object.Value) then
								object:Destroy()
							end
						end
					end
				end
			end
		end
	else
		plr:Kick("Data failed to load, rejoining is recommended. If this issue persists, contact @basicallyrbx on Twitter.")
	end
	
	
	-- ADD ITEMS TO THE INVENTORY TABLE
	
	coroutine.resume(coroutine.create(function()
		while wait() do
			if plr then
				if plr.Team ~= nil then
					if plr.Team ~= game:GetService("Teams"):WaitForChild("Unemployed") then
						workspace:WaitForChild("Tycoons"):FindFirstChild(tostring(plr.Team.Name)).PurchasedObjects.ChildAdded:Connect(function(child)
							if debounce == true then
								if not table.find(inventory,child.Name) then
									debounce = false
									table.insert(inventory,child.Name)
									child:Clone().Parent = itemFolder
									task.wait(.25)
									debounce = true
								end			
							end
						end)
					end
				end
			end
		end
	end))
	
	
	-- SAVE DATA EVERY 60 SECONDS
	
	coroutine.resume(coroutine.create(function()
		while wait(60) do
			if plr.Team ~= nil then
				if plr.Team ~= game:GetService("Teams"):WaitForChild("Unemployed") then
					
					local data = http:JSONEncode(inventory)
					
					local success, errormsg = pcall(function()
						DataStore:SetAsync("Dollars"..plr.UserId,plr.leaderstats["Dollars"].Value)
						DataStore:SetAsync("Inventory"..plr.UserId,data)
					end)
					
					if success then
						plr.PlayerGui.Buttons.Warning.Text = "Saved Data"
						wait(1.5)
						plr.PlayerGui.Buttons.Warning.Text = ""
					else
						plr.PlayerGui.Buttons.Warning.Text = "Failed to save data, try again in 1 minute"
						wait(2.5)
						plr.PlayerGui.Buttons.Warning.Text = ""
					end
				end
			end
		end
	end))
end)

-- SAVE ON PLAYER LEAVING

game.Players.PlayerRemoving:Connect(function(player)
	
		
		local inventory = {}

		for i, v in pairs(player.ItemFolder:GetChildren()) do
			if not table.find(inventory,v.Name) then
				table.insert(inventory, v.Name)
			end
	end
	
	local data = http:JSONEncode(inventory)
		
	
		local success, errormessage = pcall(function()
			DataStore:SetAsync("Dollars"..player.UserId,player.leaderstats["Dollars"].Value)
			DataStore:SetAsync("Inventory"..player.UserId,data)
		end)	
end)

-- SAVE ON GAME CLOSING

game:BindToClose(function()
	for i, plr in pairs(game:GetService("Players"):GetPlayers()) do
		local inventory = {}

		for i, v in pairs(plr.ItemFolder:GetChildren()) do
			if not table.find(inventory,v.Name) then
				table.insert(inventory, v.Name)
			end
		end
		
		local data = http:JSONEncode(inventory)
		
		local success, errormsg = pcall(function()
			DataStore:SetAsync("Dollars"..plr.UserId,plr.leaderstats["Dollars"].Value)
			DataStore:SetAsync("Inventory"..plr.UserId,data)
		end)
	end
end)

Are you testing only in Studio? Things can get weird in studio, sometimes they won’t save properly. Try to publish your game and test it.

I’m dead inside reading this question. I may not be the smartest but I’m not that dumb. No, the game doesn’t work in studio, client, local test

Sorry, I didn’t intend to offend you. But sometimes people don’t know

1 Like

have you considered that datastoreservice could be down?

Actually, you should make periodic auto-saves to prevent data loss, not only when player leave

My game’s data store saves when player leaves. No data loss. Infact, this will overload the datastore, resulting in data saving having a delay, or dropping data queues. Also roblox themselves recommend you do it when players leave

Sometimes if the player joins and leaves in a short period of time, it would not save the player’s data. But then again, there isn’t much the player could do in that time.

Also, your script should use :updateasync instead, since it’ll prevent data losses. And it’s unlikely for that to happen. Only save when player leaves, otherwise it can overload the data store and causing data losses.

The only response i can give to this: use the datastore2 module.

If your data saves sometimes but not all of the time, its not your fault, thats just how the normal datastore is. But datastore2 is very robust, has backups for your data, and also is very easy to use. I’d suggest you check that out. It also caches the data you wanna save, so it never warns with “cache is full”

The datastore service and roblox servers are reliable including an “auto save” is not a solution for a poorly designed / coded game.

Saving at key game points should be done so you as the game developer are in control over when data is saved at all times.

Using auto saves can flood the datastore as often developers dont care if there is new data to save and when the data was last saved.

2 Likes

and then I’m decoding the data using JsonDecode, please read, I’m using this because datastores are weird with tables sometimes, read what JsonEncode and Decode does, it’s intended for tables mainly

This is getting really annoying real fast lmao. I know how to make a leaderstat man, read the thing, the only problem is the table sometimes gets corrupted and doesn’t save/load

If DataStores have been down for like 3-4 days then idk man

That’s what I used to do before, same thing

Well, idk about you master, but after consulting with various different top scripters I’ve come to the conclusion that saving every 60 seconds is not a bad practice, though I will listen to you and try to do it without saving every 60 seconds, I’ll update soon

Yep, as expected, after a lotta testing without the 60 second autosave, nothing has changed

Managed to fix it! What I was doing was saving when the player left using the itemFolder inside of the player, but the player only had their itemFolder filled with their objects until later in the game which, if they left before getting a tycoon, would result in a full data wipe. I managed to fix it now!

1 Like