Problem regarding DevProduct scripts

Hello, Thanks for clicking on this post.

I recently created a DevProduct script AND a Datastore script with a shop. The shop works fine, no problems. But the real problem is that I’ve been trying to update my leaderstats.Points.Value variable without while true do since it would just go on forever and never return true. The reason I’m trying to update my variable? When I buy some points from the store, it takes the first values from the datastore. Even if the value changed after that.

In simple words:
I have 16 points.
I buy something for 4 points.
I have 12 points.
I buy 10 points.
I have 26 points.

It just takes the old Points values and never takes the current ones.

Any help is appreciated,
OceanTubez

Can you send us the shop script and devproduct script?

here:

DevProduct: Server

local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

-- Data store for tracking purchases that were successfully processed
local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")

-- Table setup containing product IDs and functions for handling purchases
local productFunctions = {1228461943, 1228464400}

-- ProductId 456456 for 100 gold
productFunctions[1228464400] = function(receipt, player)
	-- Logic/code for player buying 500 gold (may vary)
	
	local stats = player:FindFirstChild("leaderstats")
	local gold = stats and stats:FindFirstChild("Points")
	
	
	if gold then
		gold.Value = gold.Value + 500
		-- Indicate a successful purchase
		return true
	end
end

productFunctions[1228461943] = function(receipt, player)
	-- Logic/code for player buying 100 gold (may vary)
	local stats = player:FindFirstChild("leaderstats")
	local gold = game.ReplicatedStorage.Player.Points
	if gold then
		gold.Value = gold.Value + 100
		-- Indicate a successful purchase
		return true
	end
end

-- The core 'ProcessReceipt' callback function
local function processReceipt(receiptInfo)

	-- Determine if the product was already granted by checking the data store  
	local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
	local purchased = false
	local success, errorMessage = pcall(function()
		purchased = purchaseHistoryStore:GetAsync(playerProductKey)
	end)
	-- If purchase was recorded, the product was already granted
	if success and purchased then
		return Enum.ProductPurchaseDecision.PurchaseGranted
	elseif not success then
		error("Data store error:" .. errorMessage)
	end

	-- Find the player who made the purchase in the server
	local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
	if not player then
		-- The player probably left the game
		-- If they come back, the callback will be called again
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	-- Look up handler function from 'productFunctions' table above
	local handler = productFunctions[receiptInfo.ProductId]

	-- Call the handler function and catch any errors
	local success, result = pcall(handler, receiptInfo, player)
	if not success or not result then
		warn("Error occurred while processing a product purchase")
		print("\nProductId:", receiptInfo.ProductId)
		print("\nPlayer:", player)
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	-- Record transaction in data store so it isn't granted again
	local success, errorMessage = pcall(function()
		purchaseHistoryStore:SetAsync(playerProductKey, true)
	end)
	if not success then
		error("Cannot save purchase data: " .. errorMessage)
	end

	-- IMPORTANT: Tell Roblox that the game successfully handled the purchase
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

-- Set the callback; this can only be done once by one script on the server! 
MarketplaceService.ProcessReceipt = processReceipt

Heres the shop:


local function Exchange()
	local Sounds = script.Parent.Parent.Parent.Parent.Parent.Sounds
	local Cola = game.ReplicatedStorage.ToolsGUI.CocaCola
	local Points = game.Players.LocalPlayer.leaderstats.Points
	
	if Points.Value >= 400 then
		Points.Value = Points.Value - 400
		
		local NCola = Cola:Clone()
		NCola.Parent = game.Players.LocalPlayer.Backpack
		
		Sounds.ching:Play()
		
		print(game.Players.LocalPlayer.Name.." has just bought a Cola!")
		
	else
		
		Sounds.fail:Play()
		
		script.Parent.Parent.Failed.Visible = true
		
		print(game.Players.LocalPlayer.Name.." tried to buy a cola but didn't have enough points. RIP : (")
		
	end
	
	
end

script.Parent.Activated:Connect(Exchange)

You would have to use remote events for the shop localscript so that the change in the player’s cash replicates to the server.

and how exactly would I do that?

I’m pretty new here, don’t have a good experience with RE’s that much.

Example code (this should work):

(also, remember to add a RemoteEvent into ReplicatedStorage)

Shop LocalScript:

--//Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

--//Variables
local RemoteEvent = ReplicatedStorage.RemoteEvent
local LocalPlayer = Players.LocalPlayer

--//Functions
script.Parent.Activated:Connect(function()
	local Sounds = script.Parent.Parent.Parent.Parent.Parent.Sounds

	if Points.Value >= 400 then
		
		RemoteEvent:FireServer("Cola")
		Sounds.ching:Play()
	else
		
		Sounds.fail:Play()
		script.Parent.Parent.Failed.Visible = true
		return
	end
end) 

ServerScript:

--//Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--//Variables
local RemoteEvent = ReplicatedStorage.RemoteEvent
local Cola = ReplicatedStorage.ToolsGUI.CocaCola

--//Functions
RemoteEvent.OnServerConnect(function(player, item)
	if item == "Cola" then 
		if player.leaderstats.Points.Value >= 400 then -- Sanity check
			player.leaderstats.Points.Value -= 400
			
			local NCola = Cola:Clone()
			NCola.Parent = player.Backpack
			
			print(player.Name .. " has just bought a Cola!")
		else
			print(player.Name.." tried to buy a cola but didn't have enough points. RIP : (")
		end
	end
end)

Oops. Looks like the script broke : (

1 Like

when I buy 100 Points, it gives me like 1000

Change the numbering, as @katrist said " (this should work) " there isn’t a full guarantee it will use the fixed code and skim through it to figure out numbering and receive coins/points as needed.

You’re modifying the “Points” stat from the client (through code executed inside local scripts) which means that these changes won’t replicate to the server (won’t be seen/observed/noticed by the server), this consequently means that the server script which handles DataStore saving will not realise these changes and only save the stat which is currently known to the server.

Change the numbers and values. My script was only an example script but it should work for your situation.