I apologize if this seems like a weird question - but I haven’t done scripting relative to RemoteEvents in awhile as I focused my attention more towards redesigning my UI’s & architectural work in general. Just want to make sure everything is secure before implementing it into my new game, thanks!
local
local GamePassService = game:GetService('MarketplaceService')
local player = game.Players.LocalPlayer
script.Parent.MouseButton1Down:connect(function()
if player:IsInGroup(5770388) or GamePassService:UserOwnsGamePassAsync(player.userId, 4702761) then
local group = 5770388
local gp = 4702761
game.ReplicatedStorage.GUI.Assign:FireServer(BrickColor.new("Mint"), group, gp)
else
local gp = 4702761
game:GetService("MarketplaceService"):PromptGamePassPurchase(player,gp)
end
end)
server
local GamePassService = game:GetService('MarketplaceService')
game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color, group, gp)
if plr:IsInGroup(group) or GamePassService:UserOwnsGamePassAsync(plr.userId, gp) then
plr.TeamColor = color
plr:LoadCharacter()
end
end)
Exploiters can edit local scripts meaning they can fire your remote event and change the arguments - Instead you should perform group and gamepass checks all inside the server script.
Say I was an exploiter:
I would fire your event and change the group id to a group I’m a part of or change the gamepass id to a gamepass I own.
An exploiter could just just pass a group that they are in or any random Gamepass that they have in their inventory. It should not be possible for the client to be able to pick which group or Gamepass it wants to be checked.
-- client
local GamePassService = game:GetService('MarketplaceService')
local player = game.Players.LocalPlayer
local gamepassid = 4702761
local groupid = 5770388
script.Parent.MouseButton1Down:connect(function()
if player:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(player.userId, gamepassid) then
game.ReplicatedStorage.GUI.Assign:FireServer(BrickColor.new("Mint"))
else
game:GetService("MarketplaceService"):PromptGamePassPurchase(player, gamepassid)
end
end)
-- server
local GamePassService = game:GetService('MarketplaceService')
local gamepassid = 4702761
local groupid = 5770388
game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color)
if plr:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(plr.userId, gamepassid) then
plr.TeamColor = color
plr:LoadCharacter()
end
end)
Right so for example - should I have the remote event fire off the name of the team; and then the server will check if they own gp or are in the required group for the team. Which if so, change their team.
I updated my reply with the code that should work, your client should do proprietary & group checks for efficiency and the server should be a last resort in case an exploiter fired your remote without those checks.
-- client
local GamePassService = game:GetService('MarketplaceService')
local player = game.Players.LocalPlayer
local gamepassid = 4702761
local groupid = 5770388
script.Parent.MouseButton1Down:connect(function()
if player:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(player.userId, gamepassid) then
game.ReplicatedStorage.GUI.Assign:FireServer(BrickColor.new("Mint"))
else
game:GetService("MarketplaceService"):PromptGamePassPurchase(player, gamepassid)
end
end)
— server
if color == BrickColor.new(“Sand red”) and plr:IsInGroup(ACTUALID) or GamePassService:UserOwnsGamePassAsync(plr.userId, ACTUALID) then
plr.TeamColor == BrickColor.new("Sand red")
else
if color == BrickColor.new("Really blue") and plr:IsInGroup(ACTUALID) or GamePassService:UserOwnsGamePassAsync(plr.userId, ACTUALID) then
plr.TeamColor == BrickColor.new("Really blue")
end
[which then repeat the else until i’ve covered all teams]
Why is this necessary? If you have different gamepasses for different colors then I understand, but in your pseudocode example you seem to be using the same IDs which is confusing me. If you only need to own one gamepass to have an ultimate range of BrickColors, then don’t bother checking the color at all (maybe only check if it’s an actual BrickColor, although for security purposes, passing an invalid color wouldn’t affect much).
I said (ACTUALID) – they would be different ID’s for each color.
Which is why I am implying using the “else” statement to continue the checks for the rest of the teams once they are fired off from the client.
I’ve been developing for about 4 hours now and got a bit lazy, didn’t feel like putting actual numbers into place. Sorry for the confusion.
Essentially - the code is checking which color is being fired, and then checking if they are in the designated group or own the gamepass for that color before changing their team.
Use a lookup table with BrickColors and ID’s then.
local colors_gamepasses = {
[BrickColor.new("Sand red")] = 12345,
[BrickColor.new("Really blue")] = 6789
}
local groupid = 5770388
local GamePassService = game:GetService('MarketplaceService')
game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color)
local gamepass = colors_gamepasses[color]
if gamepass then
if plr:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(plr.UserId, gamepass) then
plr.TeamColor = color
end
end
end)
Sure, you could also keep it all in one and format it like this:
local lookup = {
[BrickColor.new("Sand red")] = {group = 1234, gamepass = 6579};
...
}
local GamePassService = game:GetService('MarketplaceService')
game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color)
local info = lookup[color]
if info then
if plr:IsInGroup(info.group) or GamePassService:UserOwnsGamePassAsync(plr.UserId, info.gamepass) then
plr.TeamColor = color
end
end
end)