DataStore not working as intended on different place even with the same code

I’m saving players’ items when they leave, including the item that they currently have equipped (Items go to the player’s model when equipped).

I got to do this by just making the player unequip all items when their character is being removed

game.Players.PlayerAdded:Connect(function(player)
    -- Player's items are loaded here

    -- When character is being removed, unequip their tools so that it goes to backpack
	player.CharacterRemoving:Connect(function(char)
		char:WaitForChild("Humanoid"):UnequipTools()
	end)
end)


game.Players.PlayerRemoving:Connect(function(player)
	local playerID = player.UserId
	local playerChar = player.Character
	local playerBackpack = player.Backpack
	local leaderstats = player:FindFirstChild("leaderstats")
	
	if not leaderstats then
		warn(playerID .. "'s leaderstats does not exist for data save!")
		return
	else
		local items = {}
        -- Get all items from player backpack to save
		for i, v in pairs(playerBackpack:GetChildren()) do
			if v.ClassName == "Tool" then
				table.insert(items, v.Name)
			end
		end
		
		local data = {
			Pets = leaderstats.Pets.Value,
			Items = items
		}
		
		local success, response = pcall(function()
			DataStore:SetAsync(playerID, data)
		end)
		
		if success then
			print(playerID .. " data successfully saved")
		else
			warn(playerID .. " data failed to save: " .. response)
		end
	end
end)

On the original place, this all works, but on a different place the item that the player has equipped while leaving won’t be saved, so they’ll lose it when they rejoin. The CharacterRemoving event definitely triggered before the PlayerRemoving event, but the item the player has supposedly unequipped isn’t found in the backpack, why?

1 Like

I’ve created a post about this, DataStores handled on your own is not the best, please use Profile Service.

Here is a video to set it up.

If you still experience Issues please reply again!

Does leaderstats actually exist? Can you show me a hierarchy of the player structure? The code should be working.

image

If the leaderstats doesn’t exist it should print out a warning, but it’s not doing that so it should be there, btw the place I transferred the script to has team create enabled, I don’t know if that changes anything…

Try putting a return inside before the SetAsync function and also put print statements in every line to make sure it actually ran. Also, take note of what was being saved by printing the names of the tools.

At this point, you should use the debugger

Yeah, first thing to debug is what is being saved. Then we know what is going wrong in there.

Since you have print calls helping you understand if data was successfully saved, and are not making any statements against that, I’ll assume your script is working in that regard. Your data-persistence implementation is very elementary, but it is ultimately incomplete. I noticed you’re missing a game:BindToClose callback. This method of the DataModel allows developers to run code whenever a Roblox server shuts down.

A Roblox server shuts down either

  1. Unexpectedly
  2. Forcefully by the hand of the game’s owner or an authorized developer
  3. When the last client disconnects (applicable to solo Roblox Studio test sessions)

When a Roblox server shuts down it is no longer a priority to operate the engine, leading to multiple processes being cancelled. The firing of the Players.PlayerRemoving event is no longer reliable, so you’ll need to handle data-saving in that new callback. Begin by converting your event listener to a named function so its code may be re-used:

local function onPlayerRemoving(player: Player)
    -- ...
end
Players.PlayerRemoving:Connect(onPlayerRemoving)

game:BindToClose(function()
    for _, player in Players:GetPlayers() do
        onPlayerRemoving(player)
    end
end)
1 Like

I’ve implemented your idea in the script, but the same problem persists, it’s saving items in the backpack but not the item the player has equipped, which I made the player unequip so that it goes into the backpack

image

I had 2 items here, a Fusion Coil and a Gravity Coil, but it only saved the Gravity Coil because the Fusion Coil didn’t go to my backpack even though it’s supposed to be unequipped and be put back in my backpack

local Players = game:GetService("Players")

local function onPlayerRemoving(player: Player)
	local playerID = player.UserId
	local playerChar = player.Character
	local playerBackpack = player.Backpack
	local leaderstats = player:FindFirstChild("leaderstats")

	if not leaderstats then
		warn(playerID .. "'s leaderstats does not exist for data save!")
		return
	else
		local items = {}
		for i, v in pairs(playerBackpack:GetChildren()) do
			if v.ClassName == "Tool" then
				table.insert(items, v.Name)
				print("Saved: " .. v.Name)
			end
		end

		local data = {
			Pets = leaderstats.Pets.Value,
			Items = items
		}

		local success, response = pcall(function()
			DataStore:SetAsync(playerID, data)
		end)

		if success then
			print(playerID .. " data successfully saved")
		else
			warn(playerID .. " data failed to save: " .. response)
		end
	end
end

Players.PlayerRemoving:Connect(onPlayerRemoving)

game:BindToClose(function()
	for _, player in Players:GetPlayers() do
		onPlayerRemoving(player)
	end
end)
1 Like

Why not just save in StarterGear instead if you have just put all your items in there as well? If not, make sure that the playerbackpack is cloned with the same weapon when it dies.

EDIT: If the player has tools when it dies, parent it into the backpack instead of unequipping, maybe that’ll work.

1 Like

Oh wow yeah, instead of saving the items based on their backpack, I did it based on their StarterGear, and it fixed everything.

I still wonder why the tool isn’t transferred back to the backpack when UnequipTools() was called though

1 Like

Also, if you save using StarterGear, just make sure, you are loading the tools inside StarterGear as well.

please start using modules instead of hardcoding stuff

1 Like

Can you please elaborate on how I’m supposed to use a ModuleScript in this case?

1 Like

you make dedicated modules so its easily useable in any scripts for example you could have a module that handles all data saving and another module that handles gamepasses,and etc hardcoding stuff can get messy quickly and cause issues in the future like having code thats hard to update

good code structure :

image

Bad code structure :

image

similar design structure can be seen outside of roblox as well one of them being minecraftt :ice_cube:

also when saving player data you should add retry logic so if it fails once it retries for certain amount of time and you should handle unexpected exceptions as well