Hello! So I recently worked on a Rank Donation Center, I used a tutorial by the way.
I run into trouble when executing this code:
script.Parent.MouseButton1Click:Connect(function()
if game:GetService("MarketPlaceService"):UserOwnsGamePassAsync(7564322, game.Players.LocalPlayer.UserId) then
local rankid = 5
game.ReplicatedStorage.RankPlayer:FireServer(game.Players.LocalPlayer, rankid)
end
end)
So the first time I did it without a end (didn’t work), I put a end (didn’t work).
UserOwnsGamePassAsync takes the UserId as the first argument and the gamepass id as the second.
Also, it’s MarketplaceService - not MarketPlaceService.
I feel the way this is set up is asking for trouble, unless you have additional server checks, but I cannot tell from the code you have posted. Though it looks as though you don’t.
Also, when you fire the RemoteEvent, you pass the player as a parameter. This isn’t necessary as when clients fire a remote, the first argument passed to the connection signal will be the player object that fired the remote. When checking if a user owns a pass, the userId should be the first parameter, and the passId being the second.
As you’ve probably heard before, you should never trust the client. But the way it’s currently working seems to be doing the exact opposite. You want the client to request a rank, and have the server validate whether or not they should get it. So, instead of checking if they own a pass on the client, have the client request a rank and then check if they own the corresponding pass like so:
Server
local ranks = {
-- [rank] = passId;
[5] = 7564322;
}
local marketServ = game:GetService("MarketplaceService")
game.ReplicatedStorage.RankPlayer.OnServerEvent:Connect(plr, rank)
local pass = ranks[rank] -- Look up corresponding pass for requested rank
if not pass then -- If pass doesn't exist, stop processing
return
end
if marketServ:UserOwnsGamePassAsync(plr.UserId, pass) then
-- Server ranking logic here
end
end)
Client
local rank = 5 -- Rank to be requested
script.Parent.MouseButton1Click:Connect(function()
game.ReplicatedStorage.RankPlayer:FireServer(rank) -- Request the rank
end)
If you were checking on the client for feedback, so you can display a message if they don’t own the pass then you should consider using a RemoteFunction instead. This way, you can return the success of the request. You could also have the validation logic on the client as well as the server, but not just on the client as this would be a large vulnerability - especially for changing user ranks!
PlayerHasPass is deprecated and should not be used. This function is intended to work with any game passes that still have an id on the catalog id system (migrated passes not created after the update). All game passes are on a separate id system now which UserOwnsGamePassAsync respects.