Custom tags for players with a gamepass

I want to be able to use this custom tag system I found here which works great on players id’s, but I can’t seem to get it to work for gamepasses

local SPECIAL_DATA = {
    [15619704] = { -- My user ID
        NameColor = BrickColor.new('White').Color,
        Tags = {
            {
                TagText = 'Lead Developer',
                TagColor = Color3.fromRGB(255, 59, 59)
            }
        }
    },
    [PurchaseData.Passes.Premium] = { -- Passes ID
        NameColor = BrickColor.new('White').Color,
        Tags = {
            {
                TagText = 'Premium',
                TagColor = Color3.fromRGB(25, 25, 25)
            }
        }
    },
}

local function handleSpeaker(speakerName)
	local Speaker = ChatService:GetSpeaker(speakerName)
	local Player = Speaker:GetPlayer()
	
	if not Player then return end
	
	local ExtraData = SPECIAL_DATA[Player.UserId]
	if not ExtraData then return end
	
	for i, v in pairs(ExtraData) do
		Speaker:SetExtraData(i, v)
	end
end

ChatService.SpeakerAdded:Connect(handleSpeaker)

for _, speakerName in pairs(ChatService:GetSpeakerList()) do
    handleSpeaker(speakerName)
end

I actually had this same issue for my game, all I had to do was make a RemoteFunction, and invoke the server. The server then checks if that player’s UserId owns the GamePassID, if they do it returns true, if they don’t it returns false, and then in the module if it is true it displays whatever that gamepass Tag would display, and if they don’t, it doesn’t display it.

Edit; Module OR LocalScript, depends what method you are using. They all work the same though, invoking, ect.

This is all being done in the a server script. This script is inside the ServerScriptService (purpose being editing the chat without needing to fork it)

Is the script working? Or is it not, if it isn’t, is there an error? If so, what is the error? Can you provide this error if existing?

When I ask if it is working, I am not only saying the area where you added the gamepass function, I am talking about the script as a whole.

1 Like

No errors, it works with players using their ID, but I want to include gamepass ids as well. Currently trying out this:

local ExtraData = SPECIAL_DATA[Player.UserId]
if not ExtraData then
	if GamepassCheck(Player, PurchaseData.Passes.Premium) then -- Seperate module that runs gamepass checks
		ExtraData = SPECIAL_DATA[PurchaseData.Passes.Premium]
    else
        return
	end
end
1 Like

Could you send the function GamepassCheck? Maybe this is not doing it properly? Try adding a few print() statements around your script, see if it prints. Try printing true and the player’s UserId if they own the gamepass.

1 Like

Try this:

https://wiki.roblox.com/index.php?title=API:Class/MarketplaceService/UserOwnsGamePassAsync

2 Likes

Just like @azahid1 provided you, instead of putting the gamepass id right after local SPECIAL DATA put this in:

   local mps = game:GetService("MarketplaceService")
local Id = --your gamepass id here

game.Players.PlayerAdded:Connect(function(player)
if mps:UserOwnsGamePassAsync(player.UserId, Id) then
--put the rest of your script here

And make sure to make this a (Server)Script in ServerScriptService so that way the function works.

1 Like

When it comes to game passes, all I do is return a table of constants which are key-value pair. For each key in the table, SetExtraData is called and the key-value pair is passed as the arguments. That was my old style at least. Now I just write out premium chat data raw.

For the code in the linked thread, don’t put game passes in SPECIAL_DATA, because the iterator for that table is only designed to assume that all entries are for UserIds. You’ll have to tailor that table differently if you want to put all data in that table. Such can include an extra table entry, “Type”.

This is how I currently set up VIP data:

local function handleVIPTags(speakerName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local player = speaker:GetPlayer()
	
	if player then
		local userOwnsGamePass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, GamePasses.VIP)
		
		if userOwnsGamePass then
			local vipTag = {
				TagText = VIP_TAG_NAME,
				TagColor = GOLD_COLOR
			}
			
			speaker:SetExtraData("ChatColor", GOLD_COLOR)
			speaker:SetExtraData("Tags", {vipTag})
		end
	end
end

GamePasses, the variable referenced in the UserOwnsGamePassAsync call, is an upvalue which references a ModuleScript that returns my game pass IDs. Just replace that with your ID or whatever system you have for getting the pass ID - in your case, PurchaseData.Passes.Premium.

VIP_TAG_NAME and GOLD_COLOR are both upvalues as well - VIP_TAG_NAME is a string and GOLD_COLOR is a Color3 value. I keep GOLD_COLOR as a variable so I can reuse it twice over. They’re implemented in my code near my variable declarations as follows:

local GOLD_COLOR = BrickColor.new("Gold").Color
local VIP_TAG_NAME = "VIP"

Edit: Forgot my iterator removed special chat data and only handles it for VIP data. Just merge my code with yours where applicable.

@colbert2677 actually gave a better way of doing your script so just like he said merge your script along with his, just make sure that you use the UserOwnsGamePassAsync call, an upvalue refrencing a module script returning gamepass ids when making anymore gamepass scripts

I was the one who wrote the original code. :blush:

The main point to understand here is that the provided code only accounts for UserIds in the SPECIAL_DATA table and can’t assume the purpose of an id, therefore a unique identifier needs to be provided. That can be through a separate handling process, an extra validator (e.g. including a Type indice and reading from that to decide the next steps) or hard coding it in. With multiple VIP game passes, you’ll have to get creative and tier up by determining the user’s highest VIP level.

I don’t have the old code anymore since I removed special data (I’m not a fan of supporting code just so about 5 people can get special data and people with game access going in and giving themselves chat stuff), but I can roughly remember how it went.

Note that I never return out-of-scope if there’s a nil value. I find that to be pointless, but I guess others have different conventions. I prefer to only handle pass cases.

local VIP_DATA = { -- Assume this is returned by a module somewhere
    -- stuff here
}

local function handleSpeaker(speakerName)
    local speaker = ChatService:GetSpeaker(speakerName)
    local player = speaker:GetPlayer()

    if player then
        local specialData = SPECIAL_DATA[player.UserId]
        local userOwnsGamePass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, GamePasses.VIP)

        -- Ignore VIP data if player has special tags
        if specialData then
            for key, value in pairs(specialData) do
                speaker:SetExtraData(key, value)
            end
        elseif userOwnsGamePass then
            for key, value in pairs(VIP_DATA) do
                speaker:SetExtraData(key, value)
            end
        end
    end
end

Naturally:

  • This doesn’t work with multiple game passes, that’s something to be implemented yourself.

  • This convention can get messy if not done properly. I typically suggest separating your special chat constants from your chat tags set up, unless you’re only accounting for one type of tag. In my case nowadays, I only account for VIP, hence why my provided function is limited.

  • Aim to consolidate. You can realistically handle special data and VIP data in separate code, but it’s much cleaner to handle everything in one.

wow nice job man and yes I agree this code will definitely be screwed if there are multiple of them, but everybody should use the UserOwnsGamePassAsync call when making any gamepass, usually using this code of script:

   local mps = game:GetService("MarketplaceService")
local Id = --your gamepass id here

game.Players.PlayerAdded:Connect(function(player)
if mps:UserOwnsGamePassAsync(player.UserId, Id) then
--put the rest of your script here

But kind of not with a player tag.:smirk:

Oh, you’d be surprised. You don’t have to use my code to set chat tags. The Lua Chat System supports quite a bit of support for external code wanting to interact with it or modify something related to chat via the API it exposes. My code takes advantage of that through a handler.

You could very easily write a chat tag handler using the code you put forth. My code is pretty much the same way (notice how I use the ChatService’s SpeakerAdded instead of Players’ PlayerAdded, for example). I prefer to write clean and clear code.

The reason why I don’t use PlayerAdded is because I’d rather rely on the ChatService’s methods. Unlike other code, ChatService is independent from players. It’d be better to listen to when a speaker is registered than a player joining.

You can also create non-player speakers to chat in the ChatService, so all the more reason. :slightly_smiling_face:

Yeah I can agree on that, actually there are plenty of ways to do this, but I believe yours might be one of the best and simplest.