Global chat issue

I’m trying to create a global chat system for my Clan chat

[By ‘Global’ i mean across all servers for all people in the Clan]

I dont get ANY errors.

These are my current codes [I’m not a scripter]

SERVER

local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
local MessagingService = game:GetService("MessagingService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TextService = game:GetService("TextService")

local ClanService = require(ReplicatedStorage:WaitForChild("modules"):WaitForChild("ClanService"))

local clanChatRemotes = ReplicatedStorage:WaitForChild("remotes"):WaitForChild("clan"):WaitForChild("clanChat")
local ClanChatSendEvent = clanChatRemotes:WaitForChild("ClanChat_Send")
local ClanChatReceiveEvent = clanChatRemotes:WaitForChild("ClanChat_Receive")
local Messenger = clanChatRemotes:WaitForChild("Messenger")

local globalTopic = "GlobalChat"

local TextChannelsFolder = TextChatService:WaitForChild("TextChannels")
local clanChannels = {}
local subscribedClans = {}

local function getOrCreateClanChannel(clanId)
	if clanChannels[clanId] then
		return clanChannels[clanId]
	end
	local clanData = ClanService.allClans[clanId]
	if not clanData or type(clanData.Name) ~= "string" or clanData.Name == "" then
		return nil
	end
	local channelName = clanData.Name .. " Clan Chat"
	local channel = TextChannelsFolder:FindFirstChild(channelName)
	if not channel then
		channel = Instance.new("TextChannel")
		channel.Name = channelName
		channel.Parent = TextChannelsFolder
		channel.ShouldDeliverCallback = function(message, recipientPlayer)
			local senderUserId = message.TextSource.UserId
			local senderClanId = ClanService:GetPlayerClanId(Players:GetPlayerByUserId(senderUserId))
			local recipientClanId = ClanService:GetPlayerClanId(recipientPlayer)
			return senderClanId == clanId and recipientClanId == clanId
		end
	end
	clanChannels[clanId] = channel
	local topicName = "Clan_" .. clanId
	if not subscribedClans[clanId] then
		subscribedClans[clanId] = true
		MessagingService:SubscribeAsync(topicName, function(packet)
			local data = packet.Data
			if type(data) == "table" and data.ClanId == clanId then
				local chan = clanChannels[clanId]
				if chan then
					chan:SendAsync({
						Text = data.Text,
						FromSpeaker = tostring(data.PublisherUserId),
						Time = data.Timestamp
					})
				end
				for _, plr in ipairs(Players:GetPlayers()) do
					if ClanService:GetPlayerClanId(plr) == clanId then
						ClanChatReceiveEvent:FireClient(plr, {
							PublisherUserId = data.PublisherUserId,
							Text = data.Text,
							Timestamp = data.Timestamp
						})
					end
				end
			end
		end)
	end
	return channel
end

ClanChatSendEvent.OnServerEvent:Connect(function(player, payload)
	if type(payload) ~= "table" then
		return
	end
	local clanId = payload.ClanId
	local text = payload.Text
	if type(clanId) ~= "string" or type(text) ~= "string" then
		return
	end
	if ClanService:GetPlayerClanId(player) ~= clanId then
		return
	end
	local channel = getOrCreateClanChannel(clanId)
	if not channel then
		return
	end
	local timestamp = os.time()
	local topicName = "Clan_" .. clanId
	pcall(function()
		MessagingService:PublishAsync(topicName, {
			ClanId = clanId,
			PublisherUserId = player.UserId,
			Text = text,
			Timestamp = timestamp
		})
	end)
end)

Messenger.OnServerEvent:Connect(function(player, message)
	local dataToSend = player.Name .. "\\" .. message
	pcall(function()
		MessagingService:PublishAsync(globalTopic, dataToSend)
	end)
end)

local function onPlayerClanChanged(player, oldClanId, newClanId)
	if oldClanId and clanChannels[oldClanId] then
		local chan = clanChannels[oldClanId]
		pcall(function()
			chan:RemoveUserAsync(player.UserId)
		end)
	end
	if newClanId then
		local newChan = getOrCreateClanChannel(newClanId)
		if newChan then
			pcall(function()
				newChan:AddUserAsync(player.UserId)
			end)
		end
	end
end

Players.PlayerAdded:Connect(function(player)
	local clanId = ClanService:GetPlayerClanId(player)
	if clanId then
		local chan = getOrCreateClanChannel(clanId)
		if chan then
			pcall(function()
				chan:AddUserAsync(player.UserId)
			end)
		end
	end
end)

ClanService.PlayerClanChanged.Event:Connect(onPlayerClanChanged)

for _, player in ipairs(Players:GetPlayers()) do
	local clanId = ClanService:GetPlayerClanId(player)
	if clanId then
		local chan = getOrCreateClanChannel(clanId)
		if chan then
			pcall(function()
				chan:AddUserAsync(player.UserId)
			end)
		end
	end
end

MessagingService:SubscribeAsync(globalTopic, function(message)
	local fromPlayerName, text = string.match(message.Data, "^(.-)\\(.*)$")
	if not fromPlayerName or not text then
		return
	end
	for _, plr in ipairs(Players:GetPlayers()) do
		local success, filteredText = pcall(function()
			local filterResult = TextService:FilterStringAsync(text, Players:GetUserIdFromNameAsync(fromPlayerName), Enum.TextFilterContext.PublicChat)
			return filterResult:GetChatForUserAsync(plr.UserId)
		end)
		if success then
			Messenger:FireClient(plr, fromPlayerName, filteredText)
		end
	end
end)

CLIENT

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")

local clanChatRemotes = ReplicatedStorage:WaitForChild("remotes"):WaitForChild("clan"):WaitForChild("clanChat")
local ClanChatSendEvent = clanChatRemotes:WaitForChild("ClanChat_Send")
local ClanChatReceiveEvent = clanChatRemotes:WaitForChild("ClanChat_Receive")
local ClanChangedEvent = clanChatRemotes:WaitForChild("ClanService_ClanChanged")
local Messenger = clanChatRemotes:WaitForChild("Messenger")

local TextChannelsFolder = TextChatService:WaitForChild("TextChannels")
local generalChannel = TextChannelsFolder:WaitForChild("RBXGeneral")

local currentClanChannelName = nil
local currentClanId = nil

local function removeClanChannel()
	if currentClanChannelName then
		local chan = TextChannelsFolder:FindFirstChild(currentClanChannelName)
		if chan then
			chan:Destroy()
		end
		currentClanChannelName = nil
		currentClanId = nil
	end
end

local function createClanChannel(clanId, clanName)
	removeClanChannel()
	if not clanName or clanName == "" then
		return
	end
	currentClanChannelName = clanName .. " Clan Chat"
	currentClanId = clanId
	if not TextChannelsFolder:FindFirstChild(currentClanChannelName) then
		local newChannel = Instance.new("TextChannel")
		newChannel.Name = currentClanChannelName
		newChannel.Parent = TextChannelsFolder
	end
end

ClanChangedEvent.OnClientEvent:Connect(function(clanId, clanName)
	if type(clanId) == "string" and clanId ~= "" and type(clanName) == "string" and clanName ~= "" then
		createClanChannel(clanId, clanName)
	else
		removeClanChannel()
	end
end)

TextChatService.SendingMessage:Connect(function(message)
	if not currentClanChannelName then
		return
	end
	if message.Channel and message.Channel.Name == currentClanChannelName then
		local text = message.Text
		if text and text ~= "" then
			ClanChatSendEvent:FireServer({ ClanId = currentClanId, Text = text })
		end
	end
end)

ClanChatReceiveEvent.OnClientEvent:Connect(function(data)
	if not currentClanChannelName then
		return
	end
	local chan = TextChannelsFolder:FindFirstChild(currentClanChannelName)
	if chan then
		chan:SendAsync({ FromSpeaker = tostring(data.PublisherUserId), Text = data.Text, Time = data.Timestamp })
	end
end)

Messenger.OnClientEvent:Connect(function(fromPlayer, filteredMessage)
	generalChannel:DisplaySystemMessage(fromPlayer .. ": " .. filteredMessage)
end)

removeClanChannel()

these are all the remotes:

It just doesnt want to be global, neither do i understand anything of the code so i dont know how to fix it.

Can you please add some print statements throughout the SubscribeAsync callback (lines 149 through 163) of the server script, as well as in the PublishAsync area (lines 99 to 104). Also temporarily remove the pcall on line 101, as it may be suppressing an important error…

Also, how are you testing it? If you are currently have an account running in Studio, try testing it in an actual game, as Studio doesn’t really work with MessagingService

I test it in the actual game in 1 player servers i’m in a server and my friend in a diff server. I will add the print statements right now give me a minute

New updated code with your instructions

local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
local MessagingService = game:GetService("MessagingService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TextService = game:GetService("TextService")

local ClanService = require(ReplicatedStorage:WaitForChild("modules"):WaitForChild("ClanService"))

local clanChatRemotes = ReplicatedStorage:WaitForChild("remotes"):WaitForChild("clan"):WaitForChild("clanChat")
local ClanChatSendEvent = clanChatRemotes:WaitForChild("ClanChat_Send")
local ClanChatReceiveEvent = clanChatRemotes:WaitForChild("ClanChat_Receive")
local Messenger = clanChatRemotes:WaitForChild("Messenger")

local globalTopic = "GlobalChat"

local TextChannelsFolder = TextChatService:WaitForChild("TextChannels")
local clanChannels = {}
local subscribedClans = {}

local function getOrCreateClanChannel(clanId)
	if clanChannels[clanId] then
		return clanChannels[clanId]
	end
	local clanData = ClanService.allClans[clanId]
	if not clanData or type(clanData.Name) ~= "string" or clanData.Name == "" then
		return nil
	end
	local channelName = clanData.Name .. " Clan Chat"
	local channel = TextChannelsFolder:FindFirstChild(channelName)
	if not channel then
		channel = Instance.new("TextChannel")
		channel.Name = channelName
		channel.Parent = TextChannelsFolder
		channel.ShouldDeliverCallback = function(message, recipientPlayer)
			local senderUserId = message.TextSource.UserId
			local senderClanId = ClanService:GetPlayerClanId(Players:GetPlayerByUserId(senderUserId))
			local recipientClanId = ClanService:GetPlayerClanId(recipientPlayer)
			return senderClanId == clanId and recipientClanId == clanId
		end
	end
	clanChannels[clanId] = channel
	local topicName = "Clan_" .. clanId
	if not subscribedClans[clanId] then
		subscribedClans[clanId] = true
		MessagingService:SubscribeAsync(topicName, function(packet)
			local data = packet.Data
			if type(data) == "table" and data.ClanId == clanId then
				local chan = clanChannels[clanId]
				if chan then
					chan:SendAsync({
						Text = data.Text,
						FromSpeaker = tostring(data.PublisherUserId),
						Time = data.Timestamp
					})
				end
				for _, plr in ipairs(Players:GetPlayers()) do
					if ClanService:GetPlayerClanId(plr) == clanId then
						ClanChatReceiveEvent:FireClient(plr, {
							PublisherUserId = data.PublisherUserId,
							Text = data.Text,
							Timestamp = data.Timestamp
						})
					end
				end
			end
		end)
	end
	return channel
end

ClanChatSendEvent.OnServerEvent:Connect(function(player, payload)
	if type(payload) ~= "table" then
		return
	end
	local clanId = payload.ClanId
	local text = payload.Text
	if type(clanId) ~= "string" or type(text) ~= "string" then
		return
	end
	if ClanService:GetPlayerClanId(player) ~= clanId then
		return
	end
	local channel = getOrCreateClanChannel(clanId)
	if not channel then
		return
	end
	local timestamp = os.time()
	local topicName = "Clan_" .. clanId
	pcall(function()
		MessagingService:PublishAsync(topicName, {
			ClanId = clanId,
			PublisherUserId = player.UserId,
			Text = text,
			Timestamp = timestamp
		})
	end)
end)

Messenger.OnServerEvent:Connect(function(player, message)
	local dataToSend = player.Name .. "\\" .. message
	--pcall(function()
	--	MessagingService:PublishAsync(globalTopic, dataToSend) -- temporary disabled
	--end)
end)

local function onPlayerClanChanged(player, oldClanId, newClanId)
	if oldClanId and clanChannels[oldClanId] then
		local chan = clanChannels[oldClanId]
		pcall(function()
			chan:RemoveUserAsync(player.UserId)
		end)
	end
	if newClanId then
		local newChan = getOrCreateClanChannel(newClanId)
		if newChan then
			pcall(function()
				newChan:AddUserAsync(player.UserId)
			end)
		end
	end
end

Players.PlayerAdded:Connect(function(player)
	local clanId = ClanService:GetPlayerClanId(player)
	if clanId then
		local chan = getOrCreateClanChannel(clanId)
		if chan then
			pcall(function()
				chan:AddUserAsync(player.UserId)
			end)
		end
	end
end)

ClanService.PlayerClanChanged.Event:Connect(onPlayerClanChanged)

for _, player in ipairs(Players:GetPlayers()) do
	local clanId = ClanService:GetPlayerClanId(player)
	if clanId then
		local chan = getOrCreateClanChannel(clanId)
		if chan then
			pcall(function()
				chan:AddUserAsync(player.UserId)
			end)
		end
	end
end

MessagingService:SubscribeAsync(globalTopic, function(message)
	print("Received raw message.Data:", message.Data)

	local fromPlayerName, text = string.match(message.Data, "^(.-)\\(.*)$")
	print("Parsed fromPlayerName:", fromPlayerName, "| text:", text)

	if not fromPlayerName or not text then
		print("Invalid message format, skipping processing.")
		return
	end

	for _, plr in ipairs(Players:GetPlayers()) do
		print(string.format("Filtering for recipient: %s (UserId: %d)", plr.Name, plr.UserId))
		local success, filteredText = pcall(function()
			local filterResult = TextService:FilterStringAsync(
				text,
				Players:GetUserIdFromNameAsync(fromPlayerName),
				Enum.TextFilterContext.PublicChat
			)
			print(string.format("FilterStringAsync completed for %s -> %s", fromPlayerName, plr.Name))
			return filterResult:GetChatForUserAsync(plr.UserId)
		end)

		if success then
			print(string.format("Sending filtered message to %s: %s", plr.Name, filteredText))
			Messenger:FireClient(plr, fromPlayerName, filteredText)
		else
			warn(string.format("Failed to filter/send message for %s: %s", plr.Name, tostring(filteredText)))
		end
	end
end)

It doesnt print anything at all

1 Like