Datastore acting very weird

I’ve been making a game about collecting items. All is going well, except the fact that the datastore started being very, VERY “weird”. :wave:

It works perfectly in studio, i can leave, rejoin, change my items and such and it will still save my bucks AND my items.

However, if i enter the actual game (not in studio), after a few tries all my items dissapear and the only thing left are my bucks.

I’m pretty sure the problem is the data loading, as if i open an datastore editor plugin, my data is fine, though what i’m guessing is that when the game fails to load your data, it saves your empty item inventory when you leave and rejoin. Only problem is I suck at datastores, so that’s why I’m asking you! :fire: (perhaps you could cut me some slack and just code the thing for me, also sorry for any grammar mistakes, as English isn’t my language.)

Below is my datastore script:

local players = game:GetService('Players')
local dataStoreService = game:GetService('DataStoreService')
local repStorage = game:GetService('ReplicatedStorage')
local toolsFolder = game.ServerStorage:WaitForChild('Items')

local toolData = dataStoreService:GetDataStore('skibidiFishingGame')

local playerTools = {}

local function playerAdded(plr)
	local leaderstats = Instance.new("Folder")
	leaderstats.Parent = plr
	leaderstats.Name = "leaderstats"

	local bucks = Instance.new("IntValue")
	bucks.Parent = leaderstats
	bucks.Name = "bucks"

	print(plr.Name.. ' is joining!')
	local success, data
	repeat
		success, data = pcall(function()
			return toolData:GetAsync(plr.UserId)
		end)
		if not success then
			warn("Failed to load data for " .. plr.Name .. ": " .. tostring(data))
			task.wait(5)
		end
	until success

	bucks.Value = 0

	if data then
		bucks.Value = data.bucks or 0
		print('Loaded bucks:', bucks.Value)

		if data.tools then
			for _, toolName in pairs(data.tools) do
				local tool = toolsFolder:FindFirstChild(toolName)
				if tool then
					tool:Clone().Parent = plr.Backpack
				else
					warn("There's no tool named:", toolName)
				end
			end
			playerTools[plr] = data.tools
		else
			playerTools[plr] = {}
		end
		data = nil
	else
		playerTools[plr] = {}
	end

	local function updateTools()
		local toolNames = {}
		if plr.Character then
			for _, v in pairs(plr.Character:GetChildren()) do
				if v and v:IsA('Tool') then
					table.insert(toolNames, v.Name)
				end
			end
			for _, v in pairs(plr.Backpack:GetChildren()) do
				if v and v:IsA('Tool') then
					table.insert(toolNames, v.Name)
				end
			end
		end
		playerTools[plr] = toolNames
	end

	plr.Backpack.ChildAdded:Connect(updateTools)
	plr.Backpack.ChildRemoved:Connect(updateTools)

	local function charAdded()
		print('Character added!')
		local char = plr.Character
		char.ChildAdded:Connect(updateTools)
		char.ChildRemoved:Connect(updateTools)
		char:WaitForChild('Humanoid')
		char:WaitForChild('HumanoidRootPart')
	end

	if plr.Character then
		charAdded()
	end
	plr.CharacterAdded:Connect(charAdded)
end

local function playerLeaving(plr)
	print(plr.Name.. ' is leaving!')
	local tableToSave = {
		tools = playerTools[plr],
		bucks = plr.leaderstats.bucks.Value
	}
	local success, err
	repeat
		success, err = pcall(function()
			return toolData:SetAsync(plr.UserId, tableToSave)
		end)
		if not success then
			warn("Failed to save data for " .. plr.Name .. ": " .. tostring(err))
			task.wait(3)
		end
	until success
	print('Saved!')
	playerTools[plr] = nil
end

players.PlayerAdded:Connect(playerAdded)
players.PlayerRemoving:Connect(playerLeaving)

Thanks for any help you can give me! :fish::sob:

Before you can be sure if the problem is with the DataStore, use a print to get the results from the DataStore after GetAsync and SetAsync.

Everything seems to be printing.

its obvious since you cant return SetAsync() since your saving data not retrieving it.Additionally, there is a common misconceptions when saving data, you need to use if statements to check the data exists for saving data as a player may join then leave too early before game has loaded which resets your datastore is data to nil as there overwriting each other.

Also,i think its better to not use repeat until to save the data as you should call it once

Try this Script:

local players = game:GetService('Players')
local dataStoreService = game:GetService('DataStoreService')
local repStorage = game:GetService('ReplicatedStorage')
local toolsFolder = game.ServerStorage:WaitForChild('Items')

local toolData = dataStoreService:GetDataStore('skibidiFishingGame')

local playerTools = {}

local function playerAdded(plr)
	local leaderstats = Instance.new("Folder")
	leaderstats.Parent = plr
	leaderstats.Name = "leaderstats"

	local bucks = Instance.new("IntValue")
	bucks.Parent = leaderstats
	bucks.Name = "bucks"

	print(plr.Name.. ' is joining!')
	local success, data
	repeat
		success, data = pcall(function()
			return toolData:GetAsync(plr.UserId)
		end)
		if not success then
			warn("Failed to load data for " .. plr.Name .. ": " .. tostring(data))
			task.wait(5)
		end
	until success

	bucks.Value = 0

	if data then
		bucks.Value = data.bucks or 0
		print('Loaded bucks:', bucks.Value)

		if data.tools then
			for _, toolName in pairs(data.tools) do
				local tool = toolsFolder:FindFirstChild(toolName)
				if tool then
					tool:Clone().Parent = plr.Backpack
				else
					warn("There's no tool named:", toolName)
				end
			end
			playerTools[plr] = data.tools
		else
			playerTools[plr] = {}
		end
		data = nil
	else
		playerTools[plr] = {}
	end

	local function updateTools()
		local toolNames = {}
		if plr.Character then
			for _, v in pairs(plr.Character:GetChildren()) do
				if v and v:IsA('Tool') then
					table.insert(toolNames, v.Name)
				end
			end
			for _, v in pairs(plr.Backpack:GetChildren()) do
				if v and v:IsA('Tool') then
					table.insert(toolNames, v.Name)
				end
			end
		end
		playerTools[plr] = toolNames
	end

	plr.Backpack.ChildAdded:Connect(updateTools)
     plr.Backpack.ChildRemoved:Connect(updateTools)
	

	local function charAdded()
		print('Character added!')
		local char = plr.Character
		char.ChildAdded:Connect(updateTools)
		char.ChildRemoved:Connect(updateTools)
		char:WaitForChild('Humanoid')
		char:WaitForChild('HumanoidRootPart')
	end

	if plr.Character then
		charAdded()
	end
	plr.CharacterAdded:Connect(charAdded)
end

local function playerLeaving(plr)
	print(plr.Name.. ' is leaving!')
    local leaderstats=plr:FindFirstChild("leaderstats")
    if leaderstats and leaderstats:FindFirstChild("bucks") then

	   local tableToSave = {
		tools = playerTools[plr],
		bucks = plr.leaderstats.bucks.Value
	   }
	    local success, err
		success, err = pcall(function()
			toolData:SetAsync(plr.UserId, tableToSave)
		end)
		if not success then
			warn("Failed to save data for " .. plr.Name .. ": " .. tostring(err))
		end
	     print('Saved!')
	     playerTools[plr] = nil
    end
end

players.PlayerAdded:Connect(playerAdded)
players.PlayerRemoving:Connect(playerLeaving)