Why my data store doesn't work?

my data store doesn’t work
what wrong in those scripts?

Checkpoints(Script in ServerScriptService):

    local Players = game:GetService("Players")
    local MarketplaceService = game:GetService("MarketplaceService")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local SkipStage = ReplicatedStorage:WaitForChild("SkipStage")

    local Checkpoints = workspace:WaitForChild("Checkpoints")
    local inGameStartupPlayers = {}
    local CurrentStage = {}
    local CurrentPoints = {}
    local TouchDb = {}

    local ProductId = 1145455293
    local Products = {
    	{
    		ProductPrice = 5, --The price from the Developer Product.
    		ProductId = 1141211330 -- The ID from the Developer Product.	
    	},
    	{
    		ProductPrice = 25, --The price from the Developer Product.
    		ProductId = 1141214738 -- The ID from the Developer Product.	
    	},
    	{
    		ProductPrice = 50, --The price from the Developer Product.
    		ProductId = 1141214866 -- The ID from the Developer Product.	
    	},
    	{
    		ProductPrice = 100, --The price from the Developer Product.
    		ProductId = 1141214989 -- The ID from the Developer Product.	
    	},
    	{
    		ProductPrice = 1000, --The price from the Developer Product.
    		ProductId = 1141215192 -- The ID from the Developer Product.	
    	},
    	
    }


    local function NewCharacter(player, char)
    	local TempCurrentStage = CurrentStage[player.UserId]
    	if TempCurrentStage ~= nil then
    		local TempCheckpoint = Checkpoints:FindFirstChild(TempCurrentStage)
    		if TempCheckpoint ~= nil then
    			repeat wait(0.1) until char.PrimaryPart ~= nil
    			char:SetPrimaryPartCFrame(CFrame.new(TempCheckpoint.Position + Vector3.new(0, 3, 0)) * CFrame.Angles(0, math.rad(TempCheckpoint.Orientation.Y) + math.rad(90), 0))
    		end
    	end
    end

    local function NewPlayer(player)
    	CurrentStage[player.UserId] = 1

    	local leaderstats = Instance.new("Folder", player)
    	leaderstats.Name = "leaderstats"
    	local Stage = Instance.new("IntValue", leaderstats)
    	Stage.Name = "Stage"
    	Stage.Value = 1
    	local TempChar = player.Character
    	if TempChar ~= nil then
    		NewCharacter(player, TempChar)
    	end
    	player.CharacterAdded:Connect(function(char)
    		NewCharacter(player, char)
    	end)
    end

    Players.PlayerAdded:Connect(function(player)
    	if inGameStartupPlayers[player] == nil then
    		NewPlayer(player)
    	end
    end)

    Players.PlayerRemoving:Connect(function(player)
    	CurrentStage[player.UserId] = nil
    end)

    SkipStage.OnServerInvoke = function(player)
    	local connection
    	local leaderstats = player:FindFirstChild("leaderstats")
    	if leaderstats ~= nil then
    		local Stage = leaderstats:FindFirstChild("Stage")
    		if Stage ~= nil then
    			if #Checkpoints:GetChildren() ~= Stage.Value then
    				local PurchaseResult = "Purchase Failed"
    				connection = MarketplaceService.PromptProductPurchaseFinished:Connect(function(userId, productId, purchased)
    					if player.UserId == userId and productId == ProductId then
    						if purchased == true then
    							PurchaseResult = "Success"
    						end
    					end
    					connection:Disconnect()
    				end)
    				MarketplaceService:PromptProductPurchase(player, ProductId)
    				repeat wait(0.1) until connection.Connected == false or Players:GetPlayerByUserId(player.UserId) == nil
    				return PurchaseResult
    			else
    				return "You have reached the highest stage!"
    			end
    		end
    	end
    end

    MarketplaceService.ProcessReceipt = function(recieptInfo)
    	local player = Players:GetPlayerByUserId(recieptInfo.PlayerId)

    	-- Don't grant purchase if the player left or is not here for whatever reason
    	if not player then
    		return Enum.ProductPurchaseDecision.NotProcessedYet
    	end

    	if recieptInfo.ProductId == ProductId then
    		CurrentStage[player.UserId] = CurrentStage[player.UserId] + 1
    		local leaderstats = player:FindFirstChild("leaderstats")
    		if leaderstats ~= nil then
    			local Stage = leaderstats:FindFirstChild("Stage")
    			if Stage ~= nil then
    				Stage.Value = CurrentStage[player.UserId]
    			end
    		end
    		local TempChar = player.Character
    		if TempChar ~= nil then
    			NewCharacter(player, TempChar)
    		end
    		return Enum.ProductPurchaseDecision.PurchaseGranted
    	end

    	-- Loop through the product data
    	for _, productData in ipairs(Products) do
    		-- if the productData's productId matches the prouct being purchased's id then continue
    		if productData.ProductId == recieptInfo.ProductId then
    			-- Since IncrementAsync can error we wrap it in a pcall (protected call)
    			local success, err = pcall(function()
    				game:GetService("DataStoreService"):GetOrderedDataStore("TopDonators"):IncrementAsync(player.UserId, productData.ProductPrice)
    			end)
    			-- If it errored we wanna know what went wrong
    			if success then
    				return Enum.ProductPurchaseDecision.PurchaseGranted
    			else
    				warn("Failed to increment amount donated. Error thrown: " .. err)
    				return Enum.ProductPurchaseDecision.NotProcessedYet
    			end
    		end
    	end

    	return Enum.ProductPurchaseDecision.NotProcessedYet
    end

    for i,v in pairs(Checkpoints:GetChildren()) do
    	local StageNum = tonumber(v.Name)
    	v.Touched:Connect(function(hit)
    		local char = hit.Parent
    		if char ~= nil then
    			local Humanoid = char:FindFirstChildOfClass("Humanoid")
    			if Humanoid ~= nil and Humanoid.Health > 0 then
    				local player = Players:GetPlayerFromCharacter(char)
    				if player ~= nil and (TouchDb[player.UserId] or 0) + 1 <= os.time() then
    					TouchDb[player.UserId] = os.time()
    					local TempCurrentStage = CurrentStage[player.UserId]
    					if TempCurrentStage == StageNum - 1 then
    						CurrentStage[player.UserId] = StageNum
    						local TempLeaderstats = player:FindFirstChild("leaderstats")
    						if TempLeaderstats ~= nil then
    							local TempStage = TempLeaderstats:FindFirstChild("Stage")
    							if TempStage ~= nil then
    								TempStage.Value = StageNum
    							end
    						end
    					end
    				end
    			end
    		end
    	end)
    end

    inGameStartupPlayers = Players:GetPlayers()
    for i,v in pairs(inGameStartupPlayers) do
    	spawn(function()
    		NewPlayer(v)
    	end)
    end

inGameStartupPlayers = {}

SaveData(Doesnt work)

local dataStoreService = game:GetService("DataStoreService"):GetDataStore("SaveData")
game.Players.PlayerAdded:Connect(function(plr)
	wait(0.1)
	local plr_key = "id_"..plr.userId
	local pointsave = plr.leaderstats.Points
	
	local Get_Saved = dataStoreService:GetAsync(plr_key)
	if Get_Saved then
		pointsave.Value = Get_Saved[1]
	else
		local NFS = {pointsave.Value}
		dataStoreService:GetAsync(plr_key, NFS)
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	dataStoreService:SetAsync("id_"..plr.userId, (plr.leaderstats.Points.Value))
end)

Here, you are checking whether the data exists or not, if it does then you are updating the leaderstats points but if it does not exist then why are you trying to use :GetAsync() when the player does not have any data whatsoever.

Adding on to Abroxus, you want to check whether the person has data, so what I did was use a pcall function. If it’s a success, we set it.

	local PlayerUserID = player.UserId
	local success, errormessage = pcall(function()
		Data = NewDataStore:GetAsync(PlayerUserID)
	end)
	if success then
		player.leaderstats.Points.Value = Data --Just making the value what it's saved as
		game.StarterGui.ScreenGui.TextLabel.Text = Cash .. Data --Just Changing GUI value
	end

You also want to do the same with your saving, this is helpful for debugging. My simple script just does this.

game.Players.PlayerRemoving:Connect(function(player)
	local PlayerUserID = player.UserId
	local Cash = player.leaderstats.Points.Value
	local success, errormessage = pcall(function()
		NewDataStore:SetAsync(PlayerUserID, Cash)
	end)
	if success then
		print("DataSaved")
	else
		print("There was an error")
		warn(errormessage)
	end
	
end)

Mine is extremely simple and does not incorporate gamepasses or anything else. I hope this is helpful.

Where exactly do i put those scripts?

I recommend using the ServerScriptService and if you’re really unorganized, you can put it in the workspace if you really want to.

Firstly,
You don’t need that wait() under your PlayerAdded event.

Secondly,
Check if the leaderstats exists (in case the player left before they were created or there were issues with finding it, which will result in an error.)

Thirdly,
You don’t need to save it as a table, simply do :SetAsync(Key, pointsave.Value) as you do not have multiple values (unless you’re planning to add more in the future.)

Fourthly,
Wrap your calls (GetAsync & SetAsync) in a pcall (protected call).
That way, you can easily handle errors, ex. if the data fails to save, you can attempt to save it again.

Recommendations

  1. Add a loop that saves playerdata on an interval (ex. every 2-3 minutes).
  2. Add a game:BindToClose() event in case any unexpected shutdowns occur.

Regardless — good luck on your project.

Let me know if you found this helpful and/or have any questions/issues with implementing these changes.