How To Change Chat Message Text Order From Left To Right To Right To Left?

I asked about the issue in the title. I am from Asian Country and in my country we write from right to left.
what I really need is that the chat will change text order…

really important!:

when I write in the chat in my language it will set the text order to right to left
and when I write in the chat in English it will set the order to left to right.

i appreciate all who can help, i am trying to make that about a month and i can’t do it…

1 Like

Best bet prob would be a custom chat

What’s your language?

You can do this with the base chat pretty easily.

1 Like

how can i do it i am over month trying to make that happen?

What’s the code you used to originally change the text order from right to left at first?

some time ago i asked this question before i had the idea to do it:

i used originally the solution script:

but after i saw the problem with english i didn’t know how to fix it

Change the script that person told you to use to this:

--	// FileName: ChatServiceRunner.lua
--	// Written by: Xsitsu
--	// Description: Main script to initialize ChatService and run ChatModules.

local EventFolderName = "DefaultChatSystemChatEvents"
local EventFolderParent = game:GetService("ReplicatedStorage")
local modulesFolder = script

local PlayersService = game:GetService("Players")
local RunService = game:GetService("RunService")
local Chat = game:GetService("Chat")

local ChatService = require(modulesFolder:WaitForChild("ChatService"))

local ReplicatedModules = Chat:WaitForChild("ClientChatModules")
local ChatSettings = require(ReplicatedModules:WaitForChild("ChatSettings"))

local ChatLocalization = nil
pcall(function() ChatLocalization = require(Chat.ClientChatModules.ChatLocalization :: any) end)
ChatLocalization = ChatLocalization or {}

local MAX_CHANNEL_NAME_LENGTH = ChatSettings.MaxChannelNameCheckLength or 50
local MAX_MESSAGE_LENGTH = ChatSettings.MaximumMessageLength
local MAX_BYTES_PER_CODEPOINT = 6

if not ChatLocalization.FormatMessageToSend or not ChatLocalization.LocalizeFormattedMessage then
	function ChatLocalization:FormatMessageToSend(key,default) return default end
end

local MAX_BLOCKED_SPEAKERS_PER_REQ = 50

local useEvents = {}

local EventFolder = EventFolderParent:FindFirstChild(EventFolderName)
if (not EventFolder) then
	EventFolder = Instance.new("Folder")
	EventFolder.Name = EventFolderName
	EventFolder.Archivable = false
	EventFolder.Parent = EventFolderParent
end

local function validateMessageLength(msg)
	if msg:len() > MAX_MESSAGE_LENGTH*MAX_BYTES_PER_CODEPOINT then
		return false
	end

	if utf8.len(msg) == nil then
		return false
	end

	if utf8.len(utf8.nfcnormalize(msg)) > MAX_MESSAGE_LENGTH then
		return false
	end

	return true
end

local function validateChannelNameLength(channelName)
	if channelName:len() > MAX_CHANNEL_NAME_LENGTH*MAX_BYTES_PER_CODEPOINT then
		return false
	end

	if utf8.len(channelName) == nil then
		return false
	end

	if utf8.len(utf8.nfcnormalize(channelName)) > MAX_CHANNEL_NAME_LENGTH then
		return false
	end

	return true
end

--// No-opt connect Server>Client RemoteEvents to ensure they cannot be called
--// to fill the remote event queue.
local function emptyFunction()
	--intentially empty
end

local function GetObjectWithNameAndType(parentObject, objectName, objectType)
	for _, child in pairs(parentObject:GetChildren()) do
		if (child:IsA(objectType) and child.Name == objectName) then
			return child
		end
	end

	return nil
end

local function CreateIfDoesntExist(parentObject, objectName, objectType)
	local obj = GetObjectWithNameAndType(parentObject, objectName, objectType)
	if (not obj) then
		obj = Instance.new(objectType)
		obj.Name = objectName
		obj.Parent = parentObject
	end
	useEvents[objectName] = obj

	return obj
end

--// All remote events will have a no-opt OnServerEvent connecdted on construction
local function CreateEventIfItDoesntExist(parentObject, objectName)
	local obj = CreateIfDoesntExist(parentObject, objectName, "RemoteEvent")
	obj.OnServerEvent:Connect(emptyFunction)
	return obj
end

CreateEventIfItDoesntExist(EventFolder, "OnNewMessage")
CreateEventIfItDoesntExist(EventFolder, "OnMessageDoneFiltering")
CreateEventIfItDoesntExist(EventFolder, "OnNewSystemMessage")
CreateEventIfItDoesntExist(EventFolder, "OnChannelJoined")
CreateEventIfItDoesntExist(EventFolder, "OnChannelLeft")
CreateEventIfItDoesntExist(EventFolder, "OnMuted")
CreateEventIfItDoesntExist(EventFolder, "OnUnmuted")
CreateEventIfItDoesntExist(EventFolder, "OnMainChannelSet")
CreateEventIfItDoesntExist(EventFolder, "ChannelNameColorUpdated")

CreateEventIfItDoesntExist(EventFolder, "SayMessageRequest")
CreateEventIfItDoesntExist(EventFolder, "SetBlockedUserIdsRequest")
CreateIfDoesntExist(EventFolder, "GetInitDataRequest", "RemoteFunction")
CreateIfDoesntExist(EventFolder, "MutePlayerRequest", "RemoteFunction")
CreateIfDoesntExist(EventFolder, "UnMutePlayerRequest", "RemoteFunction")

EventFolder = useEvents

local function CreatePlayerSpeakerObject(playerObj)
	--// If a developer already created a speaker object with the
	--// name of a player and then a player joins and tries to
	--// take that name, we first need to remove the old speaker object
	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if (speaker) then
		ChatService:RemoveSpeaker(playerObj.Name)
	end

	speaker = ChatService:InternalAddSpeakerWithPlayerObject(playerObj.Name, playerObj, false)

	for _, channel in pairs(ChatService:GetAutoJoinChannelList()) do
		speaker:JoinChannel(channel.Name)
	end

	speaker:InternalAssignEventFolder(EventFolder)

	speaker.ChannelJoined:connect(function(channel, welcomeMessage)
		local log = nil
		local channelNameColor = nil

		local channelObject = ChatService:GetChannel(channel)
		if (channelObject) then
			log = channelObject:GetHistoryLogForSpeaker(speaker)
			channelNameColor = channelObject.ChannelNameColor
		end
		EventFolder.OnChannelJoined:FireClient(playerObj, channel, welcomeMessage, log, channelNameColor)
	end)

	speaker.Muted:connect(function(channel, reason, length)
		EventFolder.OnMuted:FireClient(playerObj, channel, reason, length)
	end)

	speaker.Unmuted:connect(function(channel)
		EventFolder.OnUnmuted:FireClient(playerObj, channel)
	end)

	ChatService:InternalFireSpeakerAdded(speaker.Name)
end

EventFolder.SayMessageRequest.OnServerEvent:connect(function(playerObj, message, channel)
	if type(message) ~= "string" then
		return
	elseif not validateMessageLength(message) then
		return
	end

	if type(channel) ~= "string" then
		return
	elseif not validateChannelNameLength(channel) then
		return
	end

	local speaker = ChatService:GetSpeaker(playerObj.Name)

	if (speaker) then
		local temp, words = message:split(""), {}
		local allEnglishCharacters = {}

		for i, character in ipairs(temp) do
			if string.match(character, "%w") == character then
				table.insert(allEnglishCharacters, character)
			end
		end
		
		if #allEnglishCharacters >= #temp / 2 then
			return speaker:SayMessage(table.concat(temp, ""), channel)
		end
		
		local temp, words = message:split(""), {}

		local count = 1

		for i = #temp, 1, -1 do
			words[count] = temp[i]
			count += 1
		end
		
		return speaker:SayMessage(table.concat(words, " "), channel)
	end

	return nil
end)

EventFolder.MutePlayerRequest.OnServerInvoke = function(playerObj, muteSpeakerName)
	if type(muteSpeakerName) ~= "string" then
		return
	end

	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if speaker then
		local muteSpeaker = ChatService:GetSpeaker(muteSpeakerName)
		if muteSpeaker then
			speaker:AddMutedSpeaker(muteSpeaker.Name)
			return true
		end
	end
	return false
end

EventFolder.UnMutePlayerRequest.OnServerInvoke = function(playerObj, unmuteSpeakerName)
	if type(unmuteSpeakerName) ~= "string" then
		return
	end

	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if speaker then
		local unmuteSpeaker = ChatService:GetSpeaker(unmuteSpeakerName)
		if unmuteSpeaker then
			speaker:RemoveMutedSpeaker(unmuteSpeaker.Name)
			return true
		end
	end
	return false
end

-- Map storing Player -> Blocked user Ids.
local BlockedUserIdsMap = {}

PlayersService.PlayerAdded:connect(function(newPlayer)
	for player, blockedUsers in pairs(BlockedUserIdsMap) do
		local speaker = ChatService:GetSpeaker(player.Name)
		if speaker then
			for i = 1, #blockedUsers do
				local blockedUserId = blockedUsers[i]
				if blockedUserId == newPlayer.UserId then
					speaker:AddMutedSpeaker(newPlayer.Name)
				end
			end
		end
	end
end)

PlayersService.PlayerRemoving:connect(function(removingPlayer)
	BlockedUserIdsMap[removingPlayer] = nil
end)

EventFolder.SetBlockedUserIdsRequest.OnServerEvent:Connect(function(player, blockedUserIdsList)
	if type(blockedUserIdsList) ~= "table" then
		return
	end

	local prunedBlockedUserIdsList = {}
	local speaker = ChatService:GetSpeaker(player.Name)
	if speaker then
		for i = 1, math.min(#blockedUserIdsList, MAX_BLOCKED_SPEAKERS_PER_REQ) do
			if type(blockedUserIdsList[i]) == "number" then

				table.insert(prunedBlockedUserIdsList, blockedUserIdsList[i])

				local blockedPlayer = PlayersService:GetPlayerByUserId(blockedUserIdsList[i])
				if blockedPlayer then
					speaker:AddMutedSpeaker(blockedPlayer.Name)
				end
			end
		end

		-- We only want to store the first
		-- MAX_BLOCKED_SPEAKERS_PER_REQ number of ids as needed
		BlockedUserIdsMap[player] = prunedBlockedUserIdsList
	end
end)

EventFolder.GetInitDataRequest.OnServerInvoke = (function(playerObj)
	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if not (speaker and speaker:GetPlayer()) then
		CreatePlayerSpeakerObject(playerObj)
		speaker = ChatService:GetSpeaker(playerObj.Name)
	end

	local data = {}
	data.Channels = {}
	data.SpeakerExtraData = {}

	for _, channelName in pairs(speaker:GetChannelList()) do
		local channelObj = ChatService:GetChannel(channelName)
		if (channelObj) then
			local channelData =
				{
					channelName,
					channelObj:GetWelcomeMessageForSpeaker(speaker),
					channelObj:GetHistoryLogForSpeaker(speaker),
					channelObj.ChannelNameColor,
				}

			table.insert(data.Channels, channelData)
		end
	end

	for _, oSpeakerName in pairs(ChatService:GetSpeakerList()) do
		local oSpeaker = ChatService:GetSpeaker(oSpeakerName)
		data.SpeakerExtraData[oSpeakerName] = oSpeaker.ExtraData
	end

	return data
end)

local function DoJoinCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if (speaker) then
		if (channel) then
			if (channel.Joinable) then
				if (not speaker:IsInChannel(channel.Name)) then
					speaker:JoinChannel(channel.Name)
				else
					speaker:SetMainChannel(channel.Name)
					local msg = ChatLocalization:FormatMessageToSend(
						"GameChat_SwitchChannel_NowInChannel",
						string.format("You are now chatting in channel: '%s'", channel.Name),
						"RBX_NAME",
						channel.Name)
					speaker:SendSystemMessage(msg, channel.Name)
				end
			else
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatServiceRunner_YouCannotJoinChannel",
					"You cannot join channel '" .. channelName .. "'.",
					"RBX_NAME",
					channelName)
				speaker:SendSystemMessage(msg, fromChannelName)
			end
		else
			local msg = ChatLocalization:FormatMessageToSend(
				"GameChat_ChatServiceRunner_ChannelDoesNotExist",
				"Channel '" .. channelName .. "' does not exist.",
				"RBX_NAME",
				channelName)
			speaker:SendSystemMessage(msg, fromChannelName)
		end
	end
end

local function DoLeaveCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if (speaker) then
		if (speaker:IsInChannel(channelName)) then
			if (channel.Leavable) then
				speaker:LeaveChannel(channel.Name)
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatService_YouHaveLeftChannel",
					string.format("You have left channel '%s'", channelName),
					"RBX_NAME",
					channel.Name)
				speaker:SendSystemMessage(msg, "System")
			else
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatServiceRunner_YouCannotLeaveChannel",
					("You cannot leave channel '" .. channelName .. "'."),
					"RBX_NAME",
					channelName)
				speaker:SendSystemMessage(msg, fromChannelName)
			end
		else
			local msg = ChatLocalization:FormatMessageToSend(
				"GameChat_ChatServiceRunner_YouAreNotInChannel",
				("You are not in channel '" .. channelName .. "'."),
				"RBX_NAME",
				channelName)
			speaker:SendSystemMessage(msg, fromChannelName)
		end
	end
end

ChatService:RegisterProcessCommandsFunction("default_commands", function(fromSpeaker, message, channel)
	if (string.sub(message, 1, 6):lower() == "/join ") then
		DoJoinCommand(fromSpeaker, string.sub(message, 7), channel)
		return true
	elseif (string.sub(message, 1, 3):lower() == "/j ") then
		DoJoinCommand(fromSpeaker, string.sub(message, 4), channel)
		return true
	elseif (string.sub(message, 1, 7):lower() == "/leave ") then
		DoLeaveCommand(fromSpeaker, string.sub(message, 8), channel)
		return true
	elseif (string.sub(message, 1, 3):lower() == "/l ") then
		DoLeaveCommand(fromSpeaker, string.sub(message, 4), channel)
		return true
	end

	return false
end)

if ChatSettings.GeneralChannelName and ChatSettings.GeneralChannelName ~= "" then
	local allChannel = ChatService:AddChannel(ChatSettings.GeneralChannelName)

	allChannel.Leavable = false
	allChannel.AutoJoin = true

	allChannel:RegisterGetWelcomeMessageFunction(function(speaker)
		if RunService:IsStudio() then
			return nil
		end
		local player = speaker:GetPlayer()
		if player then
			local success, canChat = pcall(function()
				return Chat:CanUserChatAsync(player.UserId)
			end)
			if success and not canChat then
				return ""
			end
		end
	end)
end

local systemChannel = ChatService:AddChannel("System")
systemChannel.Leavable = false
systemChannel.AutoJoin = true
systemChannel.WelcomeMessage = ChatLocalization:FormatMessageToSend(
	"GameChat_ChatServiceRunner_SystemChannelWelcomeMessage", "This channel is for system and game notifications."
)

systemChannel.SpeakerJoined:connect(function(speakerName)
	systemChannel:MuteSpeaker(speakerName)
end)


local function TryRunModule(module)
	if module:IsA("ModuleScript") then
		local ret = require(module)
		if (type(ret) == "function") then
			ret(ChatService)
		end
	end
end

local modules = Chat:WaitForChild("ChatModules")
modules.ChildAdded:connect(function(child)
	local success, returnval = pcall(TryRunModule, child)
	if not success and returnval then
		print("Error running module " ..child.Name.. ": " ..returnval)
	end
end)

for _, module in pairs(modules:GetChildren()) do
	local success, returnval = pcall(TryRunModule, module)
	if not success and returnval then
		print("Error running module " ..module.Name.. ": " ..returnval)
	end
end

PlayersService.PlayerRemoving:connect(function(playerObj)
	if (ChatService:GetSpeaker(playerObj.Name)) then
		ChatService:RemoveSpeaker(playerObj.Name)
	end
end)

image
for English it works perfect but now i can’t write in Hebrew

Fixed, change the script to this:

--	// FileName: ChatServiceRunner.lua
--	// Written by: Xsitsu
--	// Description: Main script to initialize ChatService and run ChatModules.

local EventFolderName = "DefaultChatSystemChatEvents"
local EventFolderParent = game:GetService("ReplicatedStorage")
local modulesFolder = script

local PlayersService = game:GetService("Players")
local RunService = game:GetService("RunService")
local Chat = game:GetService("Chat")

local ChatService = require(modulesFolder:WaitForChild("ChatService"))

local ReplicatedModules = Chat:WaitForChild("ClientChatModules")
local ChatSettings = require(ReplicatedModules:WaitForChild("ChatSettings"))

local ChatLocalization = nil
pcall(function() ChatLocalization = require(Chat.ClientChatModules.ChatLocalization :: any) end)
ChatLocalization = ChatLocalization or {}

local MAX_CHANNEL_NAME_LENGTH = ChatSettings.MaxChannelNameCheckLength or 50
local MAX_MESSAGE_LENGTH = ChatSettings.MaximumMessageLength
local MAX_BYTES_PER_CODEPOINT = 6

if not ChatLocalization.FormatMessageToSend or not ChatLocalization.LocalizeFormattedMessage then
	function ChatLocalization:FormatMessageToSend(key,default) return default end
end

local MAX_BLOCKED_SPEAKERS_PER_REQ = 50

local useEvents = {}

local EventFolder = EventFolderParent:FindFirstChild(EventFolderName)
if (not EventFolder) then
	EventFolder = Instance.new("Folder")
	EventFolder.Name = EventFolderName
	EventFolder.Archivable = false
	EventFolder.Parent = EventFolderParent
end

local function validateMessageLength(msg)
	if msg:len() > MAX_MESSAGE_LENGTH*MAX_BYTES_PER_CODEPOINT then
		return false
	end

	if utf8.len(msg) == nil then
		return false
	end

	if utf8.len(utf8.nfcnormalize(msg)) > MAX_MESSAGE_LENGTH then
		return false
	end

	return true
end

local function validateChannelNameLength(channelName)
	if channelName:len() > MAX_CHANNEL_NAME_LENGTH*MAX_BYTES_PER_CODEPOINT then
		return false
	end

	if utf8.len(channelName) == nil then
		return false
	end

	if utf8.len(utf8.nfcnormalize(channelName)) > MAX_CHANNEL_NAME_LENGTH then
		return false
	end

	return true
end

--// No-opt connect Server>Client RemoteEvents to ensure they cannot be called
--// to fill the remote event queue.
local function emptyFunction()
	--intentially empty
end

local function GetObjectWithNameAndType(parentObject, objectName, objectType)
	for _, child in pairs(parentObject:GetChildren()) do
		if (child:IsA(objectType) and child.Name == objectName) then
			return child
		end
	end

	return nil
end

local function CreateIfDoesntExist(parentObject, objectName, objectType)
	local obj = GetObjectWithNameAndType(parentObject, objectName, objectType)
	if (not obj) then
		obj = Instance.new(objectType)
		obj.Name = objectName
		obj.Parent = parentObject
	end
	useEvents[objectName] = obj

	return obj
end

--// All remote events will have a no-opt OnServerEvent connecdted on construction
local function CreateEventIfItDoesntExist(parentObject, objectName)
	local obj = CreateIfDoesntExist(parentObject, objectName, "RemoteEvent")
	obj.OnServerEvent:Connect(emptyFunction)
	return obj
end

CreateEventIfItDoesntExist(EventFolder, "OnNewMessage")
CreateEventIfItDoesntExist(EventFolder, "OnMessageDoneFiltering")
CreateEventIfItDoesntExist(EventFolder, "OnNewSystemMessage")
CreateEventIfItDoesntExist(EventFolder, "OnChannelJoined")
CreateEventIfItDoesntExist(EventFolder, "OnChannelLeft")
CreateEventIfItDoesntExist(EventFolder, "OnMuted")
CreateEventIfItDoesntExist(EventFolder, "OnUnmuted")
CreateEventIfItDoesntExist(EventFolder, "OnMainChannelSet")
CreateEventIfItDoesntExist(EventFolder, "ChannelNameColorUpdated")

CreateEventIfItDoesntExist(EventFolder, "SayMessageRequest")
CreateEventIfItDoesntExist(EventFolder, "SetBlockedUserIdsRequest")
CreateIfDoesntExist(EventFolder, "GetInitDataRequest", "RemoteFunction")
CreateIfDoesntExist(EventFolder, "MutePlayerRequest", "RemoteFunction")
CreateIfDoesntExist(EventFolder, "UnMutePlayerRequest", "RemoteFunction")

EventFolder = useEvents

local function CreatePlayerSpeakerObject(playerObj)
	--// If a developer already created a speaker object with the
	--// name of a player and then a player joins and tries to
	--// take that name, we first need to remove the old speaker object
	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if (speaker) then
		ChatService:RemoveSpeaker(playerObj.Name)
	end

	speaker = ChatService:InternalAddSpeakerWithPlayerObject(playerObj.Name, playerObj, false)

	for _, channel in pairs(ChatService:GetAutoJoinChannelList()) do
		speaker:JoinChannel(channel.Name)
	end

	speaker:InternalAssignEventFolder(EventFolder)

	speaker.ChannelJoined:connect(function(channel, welcomeMessage)
		local log = nil
		local channelNameColor = nil

		local channelObject = ChatService:GetChannel(channel)
		if (channelObject) then
			log = channelObject:GetHistoryLogForSpeaker(speaker)
			channelNameColor = channelObject.ChannelNameColor
		end
		EventFolder.OnChannelJoined:FireClient(playerObj, channel, welcomeMessage, log, channelNameColor)
	end)

	speaker.Muted:connect(function(channel, reason, length)
		EventFolder.OnMuted:FireClient(playerObj, channel, reason, length)
	end)

	speaker.Unmuted:connect(function(channel)
		EventFolder.OnUnmuted:FireClient(playerObj, channel)
	end)

	ChatService:InternalFireSpeakerAdded(speaker.Name)
end

EventFolder.SayMessageRequest.OnServerEvent:connect(function(playerObj, message, channel)
	if type(message) ~= "string" then
		return
	elseif not validateMessageLength(message) then
		return
	end

	if type(channel) ~= "string" then
		return
	elseif not validateChannelNameLength(channel) then
		return
	end

	local speaker = ChatService:GetSpeaker(playerObj.Name)

	if (speaker) then
		local temp, words = message:split(""), {}
		local allEnglishCharacters = {}

		for i, character in ipairs(temp) do
			if string.match(character, "%w") == character then
				table.insert(allEnglishCharacters, character)
			end
		end
		
		if #allEnglishCharacters >= #temp / 2 then
			return speaker:SayMessage(table.concat(temp, ""), channel)
		end

		temp, words = message:split(" "), {}

		local count = 1

		for i = #temp, 1, -1 do
			words[count] = temp[i]
			count += 1
		end

		return speaker:SayMessage(table.concat(words, " "), channel)
	end

	return nil
end)

EventFolder.MutePlayerRequest.OnServerInvoke = function(playerObj, muteSpeakerName)
	if type(muteSpeakerName) ~= "string" then
		return
	end

	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if speaker then
		local muteSpeaker = ChatService:GetSpeaker(muteSpeakerName)
		if muteSpeaker then
			speaker:AddMutedSpeaker(muteSpeaker.Name)
			return true
		end
	end
	return false
end

EventFolder.UnMutePlayerRequest.OnServerInvoke = function(playerObj, unmuteSpeakerName)
	if type(unmuteSpeakerName) ~= "string" then
		return
	end

	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if speaker then
		local unmuteSpeaker = ChatService:GetSpeaker(unmuteSpeakerName)
		if unmuteSpeaker then
			speaker:RemoveMutedSpeaker(unmuteSpeaker.Name)
			return true
		end
	end
	return false
end

-- Map storing Player -> Blocked user Ids.
local BlockedUserIdsMap = {}

PlayersService.PlayerAdded:connect(function(newPlayer)
	for player, blockedUsers in pairs(BlockedUserIdsMap) do
		local speaker = ChatService:GetSpeaker(player.Name)
		if speaker then
			for i = 1, #blockedUsers do
				local blockedUserId = blockedUsers[i]
				if blockedUserId == newPlayer.UserId then
					speaker:AddMutedSpeaker(newPlayer.Name)
				end
			end
		end
	end
end)

PlayersService.PlayerRemoving:connect(function(removingPlayer)
	BlockedUserIdsMap[removingPlayer] = nil
end)

EventFolder.SetBlockedUserIdsRequest.OnServerEvent:Connect(function(player, blockedUserIdsList)
	if type(blockedUserIdsList) ~= "table" then
		return
	end

	local prunedBlockedUserIdsList = {}
	local speaker = ChatService:GetSpeaker(player.Name)
	if speaker then
		for i = 1, math.min(#blockedUserIdsList, MAX_BLOCKED_SPEAKERS_PER_REQ) do
			if type(blockedUserIdsList[i]) == "number" then

				table.insert(prunedBlockedUserIdsList, blockedUserIdsList[i])

				local blockedPlayer = PlayersService:GetPlayerByUserId(blockedUserIdsList[i])
				if blockedPlayer then
					speaker:AddMutedSpeaker(blockedPlayer.Name)
				end
			end
		end

		-- We only want to store the first
		-- MAX_BLOCKED_SPEAKERS_PER_REQ number of ids as needed
		BlockedUserIdsMap[player] = prunedBlockedUserIdsList
	end
end)

EventFolder.GetInitDataRequest.OnServerInvoke = (function(playerObj)
	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if not (speaker and speaker:GetPlayer()) then
		CreatePlayerSpeakerObject(playerObj)
		speaker = ChatService:GetSpeaker(playerObj.Name)
	end

	local data = {}
	data.Channels = {}
	data.SpeakerExtraData = {}

	for _, channelName in pairs(speaker:GetChannelList()) do
		local channelObj = ChatService:GetChannel(channelName)
		if (channelObj) then
			local channelData =
				{
					channelName,
					channelObj:GetWelcomeMessageForSpeaker(speaker),
					channelObj:GetHistoryLogForSpeaker(speaker),
					channelObj.ChannelNameColor,
				}

			table.insert(data.Channels, channelData)
		end
	end

	for _, oSpeakerName in pairs(ChatService:GetSpeakerList()) do
		local oSpeaker = ChatService:GetSpeaker(oSpeakerName)
		data.SpeakerExtraData[oSpeakerName] = oSpeaker.ExtraData
	end

	return data
end)

local function DoJoinCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if (speaker) then
		if (channel) then
			if (channel.Joinable) then
				if (not speaker:IsInChannel(channel.Name)) then
					speaker:JoinChannel(channel.Name)
				else
					speaker:SetMainChannel(channel.Name)
					local msg = ChatLocalization:FormatMessageToSend(
						"GameChat_SwitchChannel_NowInChannel",
						string.format("You are now chatting in channel: '%s'", channel.Name),
						"RBX_NAME",
						channel.Name)
					speaker:SendSystemMessage(msg, channel.Name)
				end
			else
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatServiceRunner_YouCannotJoinChannel",
					"You cannot join channel '" .. channelName .. "'.",
					"RBX_NAME",
					channelName)
				speaker:SendSystemMessage(msg, fromChannelName)
			end
		else
			local msg = ChatLocalization:FormatMessageToSend(
				"GameChat_ChatServiceRunner_ChannelDoesNotExist",
				"Channel '" .. channelName .. "' does not exist.",
				"RBX_NAME",
				channelName)
			speaker:SendSystemMessage(msg, fromChannelName)
		end
	end
end

local function DoLeaveCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if (speaker) then
		if (speaker:IsInChannel(channelName)) then
			if (channel.Leavable) then
				speaker:LeaveChannel(channel.Name)
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatService_YouHaveLeftChannel",
					string.format("You have left channel '%s'", channelName),
					"RBX_NAME",
					channel.Name)
				speaker:SendSystemMessage(msg, "System")
			else
				local msg = ChatLocalization:FormatMessageToSend(
					"GameChat_ChatServiceRunner_YouCannotLeaveChannel",
					("You cannot leave channel '" .. channelName .. "'."),
					"RBX_NAME",
					channelName)
				speaker:SendSystemMessage(msg, fromChannelName)
			end
		else
			local msg = ChatLocalization:FormatMessageToSend(
				"GameChat_ChatServiceRunner_YouAreNotInChannel",
				("You are not in channel '" .. channelName .. "'."),
				"RBX_NAME",
				channelName)
			speaker:SendSystemMessage(msg, fromChannelName)
		end
	end
end

ChatService:RegisterProcessCommandsFunction("default_commands", function(fromSpeaker, message, channel)
	if (string.sub(message, 1, 6):lower() == "/join ") then
		DoJoinCommand(fromSpeaker, string.sub(message, 7), channel)
		return true
	elseif (string.sub(message, 1, 3):lower() == "/j ") then
		DoJoinCommand(fromSpeaker, string.sub(message, 4), channel)
		return true
	elseif (string.sub(message, 1, 7):lower() == "/leave ") then
		DoLeaveCommand(fromSpeaker, string.sub(message, 8), channel)
		return true
	elseif (string.sub(message, 1, 3):lower() == "/l ") then
		DoLeaveCommand(fromSpeaker, string.sub(message, 4), channel)
		return true
	end

	return false
end)

if ChatSettings.GeneralChannelName and ChatSettings.GeneralChannelName ~= "" then
	local allChannel = ChatService:AddChannel(ChatSettings.GeneralChannelName)

	allChannel.Leavable = false
	allChannel.AutoJoin = true

	allChannel:RegisterGetWelcomeMessageFunction(function(speaker)
		if RunService:IsStudio() then
			return nil
		end
		local player = speaker:GetPlayer()
		if player then
			local success, canChat = pcall(function()
				return Chat:CanUserChatAsync(player.UserId)
			end)
			if success and not canChat then
				return ""
			end
		end
	end)
end

local systemChannel = ChatService:AddChannel("System")
systemChannel.Leavable = false
systemChannel.AutoJoin = true
systemChannel.WelcomeMessage = ChatLocalization:FormatMessageToSend(
	"GameChat_ChatServiceRunner_SystemChannelWelcomeMessage", "This channel is for system and game notifications."
)

systemChannel.SpeakerJoined:connect(function(speakerName)
	systemChannel:MuteSpeaker(speakerName)
end)


local function TryRunModule(module)
	if module:IsA("ModuleScript") then
		local ret = require(module)
		if (type(ret) == "function") then
			ret(ChatService)
		end
	end
end

local modules = Chat:WaitForChild("ChatModules")
modules.ChildAdded:connect(function(child)
	local success, returnval = pcall(TryRunModule, child)
	if not success and returnval then
		print("Error running module " ..child.Name.. ": " ..returnval)
	end
end)

for _, module in pairs(modules:GetChildren()) do
	local success, returnval = pcall(TryRunModule, module)
	if not success and returnval then
		print("Error running module " ..module.Name.. ": " ..returnval)
	end
end

PlayersService.PlayerRemoving:connect(function(playerObj)
	if (ChatService:GetSpeaker(playerObj.Name)) then
		ChatService:RemoveSpeaker(playerObj.Name)
	end
end)
1 Like

again thank you i don’t know how to thank you

1 Like