Adding an item I don't want to be saved by DataStore spams DataStore save requests

I’m new to DataStores and am saving items players have bought with their in-game points via one. However, I put in a vending machine that gives the player an item for free, but I DON’T want it to be saved by the DataStore- players have to pick it up every time. It doesn’t get saved, which is the good part, however it spams my console with DataStore save requests.

How do I fix this?

Here’s my DataStore’s code:

local dss = game:GetService("DataStoreService")
local SStorage = game:GetService("ServerStorage")
local DS = dss:GetDataStore("InventorySave")
local wepfolder = SStorage.Weapons
local cansave = true

game.Players.PlayerAdded:Connect(function(player)
	local inventory = Instance.new("Folder", SStorage.Inventories)
	inventory.Name = player.Name
	
	local keycode = "keycode: "..player.UserId
	local data
	if DS:GetAsync(keycode) then
		data = DS:GetAsync(keycode)
		if #data > 0 then
			for i,v in pairs(wepfolder:GetChildren()) do
				for q,tool in pairs(data) do
					if tool == v.Name then
						v:clone().Parent = inventory
					end
				end
			end
			print('found some items bought by: '..keycode..'['..player.Name..']')
		else
			print('no stuff saved: '..player.Name)
		end
	else
		print('new player:'..keycode..'['..player.Name..']')
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local inventoryfolder = SStorage.Inventories:FindFirstChild(player.Name)
	pcall(function()
		if inventoryfolder then
			game.Debris:AddItem(inventoryfolder, 2)
		end
	end)
	local keycode = "keycode: "..player.UserId
	local weps = {}
	local pos = 1
	for i,v in pairs(inventoryfolder:GetChildren()) do
		if v:IsA("Tool") then
			table.insert(weps, pos, v.Name)
			pos = pos + 1
		end
	end
	if #weps > 0 then
		local succ, err = pcall(function()
			DS:SetAsync(keycode, weps)
		end)
		if succ then
			print('saved inventory for: '..player.Name)
		else
			print(tostring(err))
		end
	end
end)

function save(player)
	local inventoryfolder = SStorage.Inventories:FindFirstChild(player.Name)
	if not inventoryfolder then return end
	local keycode = "keycode: "..player.UserId
	local weps = {}
	local pos = 1
	for i,v in pairs(inventoryfolder:GetChildren()) do
		if v:IsA("Tool") then
			table.insert(weps, pos, v.Name)
			print('added weapon: '..v.Name..' to position: '..pos)
			pos = pos + 1
		end
	end
	if #weps > 0 then
		local succ, err = pcall(function()
			DS:SetAsync(keycode, weps)
		end)
		if succ then
			print('saved inventory for: '..player.Name)
		else
			print(tostring(err))
		end
	end
end

while true do
	wait(60)
	for i,v in pairs(game.Players:GetPlayers()) do
		if cansave == true then
			save(v)
			cansave =false
			delay(10, function()
				cansave = true
			end)
		end
	end
end

Now I’m not sure why it would be spamming save requests, as (to my knowledge), this shouldn’t save the player’s Backpack upon a new item being added to it.

Providing code examples with your explanations would be awesome, I learn best by example!

I’m too tired to figure this out, but you should ALWAYS make instances formatted like THIS:

local folder = Instance.new("Folder")
folder.Parent = workspace

and NOT like THIS:

local folder = Instance.new("Folder", workspace) -- I'm using workspace for the parent just as an example here, the parent could be anything.

I’m not just saying this because I like how the first one looks better or something, the second format (for example, the way you created your inventory folder in your script) is almost 200% more laggy—and this is according to the roblox staff. Just make sure

Hey!
I found your code doing some extra effort that maybe its not needed.
Actually I would go with a different approach. Instead of cloning tools inside a folder called with the player’s name, you could save that data into a table. And when saving the datastore, no need to iterate into any folder, just save the table related with the player.

But, anyway, by doing the folder approach, I would change some stuff firstly in your PlayerAdded and PlayerRemoving event

First, use the pcall to wrap the Datastore calls.
When data is found, no need to iterate twice in the data and in the folder, you would need only one for loop, inside the data from DSS.
Each tool name found will be searched inside the WeaponsFolder, clone it and parent it to the player’s folder.
When playerRemoving using again the pcall. Iterate the player’s folder, insert the names of tools inside an array, the save the array into players Datastore, if successful saving delete the player’s folder, if not success, build a loop with retries for saving into datastore.

local dss = game:GetService("DataStoreService")
local SStorage = game:GetService("ServerStorage")
local DS = dss:GetDataStore("InventorySave")
local wepfolder = SStorage.Weapons
local cansave = true

game.Players.PlayerAdded:Connect(function(player)
	local inventory = Instance.new("Folder", SStorage.Inventories)
	inventory.Name = player.Name

	local keycode = "keycode: "..player.UserId
	
	local success, data = pcall(function()
		return DS:GetAsync(keycode)
	end)

	if success then
		warn("roblox datastore query successful")
		if data then
			warn("data found in DB for player")
			for _, v in pairs(data) do
				if wepfolder:FindFirstChild(v) then
					wepfolder:FindFirstChild(v):Clone().Parent = inventory
				end
			end
		else
			warn("no data in DB about player")
		end
	else
		warn("connection issue with datastore")
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local inventoryfolder = SStorage.Inventories:FindFirstChild(player.Name)
	
	local keycode = "keycode: "..player.UserId
	local weps = {}
	
	for i, v in pairs(inventoryfolder:GetChildren()) do
		if v:IsA("Tool") then
			table.insert(weps, v.Name)
		end
	end

	if #weps > 0 then
		local success, err = pcall(function()
			return DS:SetAsync(keycode, weps)
		end)

		if success then
			warn("successful saving")
			SStorage.Inventories:FindFirstChild(player.Name):Destroy()
		else
			warn("failed saving retry")
		end
	end
end)

About the loop that you are using to constantly save the players datastore each 60 seconds?
I should read it carefully first before talking about it.
BTW if you are getting into console too many tries of saving the datastore warning, could be the loop.

Some small stuff, maybe you would prefer to name the folders of players with the keycode too, instead of their names, using the UserId its better than their names always.
And maybe you would like to try to save the data into a Server Table inside a module so many scripts can access the data about the players inventory. To me is cleaner to keep the data as tables instead of folders in ServerStorage

Thanks for cleaning it up.

I actually ended up solving it- the DataStore spamming wasn’t the extra tool, but instead my leaderboard script calling GetOrderedDataStore much more than it needed to. Just misattributed it. Oops!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.