Developer product that spawns a part/makes one visible only for the player that bought the product?

  1. What do you want to achieve? Developer product that spawns a part/makes one visible for only the player that bought the product

  2. What is the issue? I have no clue how to make one :frowning:

  3. What solutions have you tried so far? I did look from DevHub, but did not found an answer

Sorry for my stupid questions, but hey, you got to start somewhere :stuck_out_tongue:

Whenever you want to make something only a certain player sees, you want to make it locally. I.e., you do not put a Script to make that part into ServerScriptService, but make it run from a LocalScript, on the Player.

You can achieve similar things much more securely, by making BillboardGuis which hide from all players who have not purchased the product.

I can only speculate what you wish to do with this though.

I did read that article. Didn’t help me :S Having hard time understanding how to make the part appear only to one player

This would require the use of local scripts, remote functions, and server scripts. Basically, invoke a remote function to get the server to check if the player owns a developer product and make it return either true or false depending on the result. Then receive that from a local script and do whatever it is you need to do

1 Like
––LocalScript
local part = Instance.new('Part')
part.Parent = workspace
part.CFrame = humanoidRootPart.CFrame.LookVector * 1
part.Name = 'localPart'

Sounds complicated, we’ll see how it goes :smiley:

You could use this article:

Yes, local scripts only effect the local player (which is you)

So, anything that happens on LocalScript only appears on the specific player? Am I right?

You could use this article:
Bindable Events and Functions | Documentation - Roblox Creator Hub

" Note that a Player object must be passed along with the FireClient() call to indicate which specific player should be targeted."

How do I get the player object?

This is what I have so far

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Room1Button = game.ReplicatedStorage:WaitForChild("Room1Button")

-- 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 = {}


productFunctions[1154938854] = function(receipt, player)
	Room1Button:FireClient()
	return true
end

The Player object must be the player for whom you want to fire the event for:
You can get it by several ways such as Players.PlayerAdded and whoever fired the remote event/function

example code for remote events

-- local script
local remote = game.ReplicatedStorage:WaitForChild("RemoteEvent")
remote:FireServer() -- this would send an event to the server and whatever server script is hooked to it will recieve it
-- server script
local remote = game.ReplicatedStorage:WaitForChild("RemoteEvent")

remote.OnServerEvent:Connect(function(playerWhoFired)
   -- roblox automatically passes the player who fired the remote event as the first parameter
   -- you don't have to pass it through the local script
   -- after the player argument is the arguments that you would send through the event
   -- note: the player who fired is ALWAYS the first parameter

   remote:FireClient(playerWhoFired, "sent event to client") -- fire the remote event back to the client
end)
-- in a different local script
local remote = game.ReplicatedStorage:WaitForChild("RemoteEvent")

remote.OnClientEvent:Connect(function(text)
    -- roblox doesn't pass the player in this context, why? because you're already in a local script and can get the player

    print(text) -- "text" is the argument that we passed from the server script
end)

Ugh, this is more complicated than I thought :smiley: Maybe too complicated for someone who started scripting a week ago.

I mean, you can check if they own the developer product with a local script and handle everything from there but exploiters would probably abuse that since they can read and edit local scripts

At this point I don’t really care about exploiters. If they really want to exploit in a game where you find a button then sure, go for it…

But, I somehow managed to do something that works. Now it makes the big red button go invisible only for the player that bought the product. xD

Room1Button.OnClientEvent:Connect(function(player)
       game.Workspace.Room1.namiska1.Transparency = 1
end)

Btw, is this all really needed? I borrowed the code from DevHub.

local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Room1Button = game.ReplicatedStorage:WaitForChild("Room1Button")



-- 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 = {}



productFunctions[1154938854] = function(receipt, player)
	Room1Button:FireClient(player)
	return true
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