As you can see in the video, that the client send a checking system and the server checks it then return to the client. I need suggestions to improve this script because the respond is quite slow. It took me around 2 seconds to prompt the purchase(with the print function in it). Here’s the script.
Local Script
local MarketPlaceService = game:GetService("MarketplaceService")
local MusicGui = script.Parent.Frame.ScrollingFrame.Music
local Frame2 = MusicGui.Frame2
local ProductId = 1106526442
local GamepassId = 1246712
Frame2.MouseButton1Click:Connect(function()
if MarketPlaceService:UserOwnsGamePassAsync(player.UserId, GamepassId) then
print("Player owns gamepass")
Frame2:Destroy()
else
print("Player doesn't owns gamepass")
print("Sending signal to the server to check if player has bought the product")
game.ReplicatedStorage.Check:FireServer(player)
game.ReplicatedStorage.Check2.OnClientEvent:Connect(function(Value)
if Value == true then
print("Player owns product")
Frame2:Destroy()
else
print("Player doesn't owns product")
MarketPlaceService:PromptProductPurchase(player, ProductId)
end
end)
end
end)
Server Script
local MarketPlaceService = game:GetService("MarketplaceService")
local ProductID = 1106526442
game.ReplicatedStorage.Check.OnServerEvent:Connect(function(player)
print("Checking if player bought the poduct")
game.ReplicatedStorage.Check2:FireClient(player, player.Others.OwnsProduct.Value)
end)
MarketPlaceService.ProcessReceipt = function(purchaseInfo)
local PlayerPurchased = game.Players:GetPlayerByUserId(purchaseInfo.PlayerId)
if not PlayerPurchased then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
if purchaseInfo.ProductId == ProductID then
PlayerPurchased:WaitForChild("Others").OwnsProduct.Value = true
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
If there is any suggestions to improve it please let me know. I accept any suggestions from other developers. Thank you for reading.
The thing is, I don’t think you necessarily need that remote event to check it if all you’re doing in the server side is reading a value inside the player instance.
You can just store the localplayer in a variable and access it something like this as I can see:
local player = game.Players.LocalPlayer
print(player.Others.OwnsProduct.Value)
That actually solves the problem, but there are some other wrong things you’re doing in your code. It is that you are connecting a OnClientEvent to that Check2 Remote Event everytime someone clicks that Frame2. You can just connect it outside that MouseButton1Click connection.
But the thing is you can just use a remote function, instead of two different Remote Events too, but isn’t needed in this case anymore as the problem can be solved without using any events, as I showed firstly.
The thing is exploiters can just turn the value to true and the client will think that it’s true but it’s not.
I didn’t it’s just for the example that it works. Here is the REAL script:
if MarketPlaceService:UserOwnsGamePassAsync(player.UserId, GamepassId) then
print("Player owns gamepass")
Frame2:Destroy()
else
print("Player doesn't owns gamepass")
print("Sending signal to the server to check if player has bought the product")
game.ReplicatedStorage.Check:FireServer(player)
game.ReplicatedStorage.Check2.OnClientEvent:Connect(function(Value)
if Value == true then
print("Player owns product")
Frame2:Destroy()
else
print("Player owns product")
MarketPlaceService:PromptProductPurchase(player, ProductId)
end
end)
wait(3)
game.ReplicatedStorage.Check:FireServer(player)
game.ReplicatedStorage.Check2.OnClientEvent:Connect(function(Value)
if Value == true then
Frame2:Destroy()
end
end)
end
end)
That basically is the same thing, if you know exploiters can turn the value to true in client side, you should also know the OnClientEvent is client sided too, they could just change what is supposed to happen onClientEvent too. So you don’t need to do anything like this, all I would say is before you do anything related to that gamepass, you should check in server side if the player owns the gamepass.
Also the script that you have given recently, has 2 OnClientEvent Connections for Check2, may I know why? I have a feeling you need to go through how remote events and functions work:
Because there was a bug that when the player bought the product, The frame wouldn’t go away. So the player could’ve bought the product again. Instead I check it again when the player clicked it so they wouldn’t have to buy the product again.
You need to go through some of the API Reference properly, then most of your doubts will get solved. As for the bug you referenced, is not a bug, its obvious. What you can do is bind a .Changed to that boolValue inside the player that stores if player owns it or not, also when player makes a purchase call, I would do it on the Server Side, using a remote event, so you can check if player owns it already.