Skip to content

Instantly share code, notes, and snippets.

@gaymeowing
Last active March 21, 2024 16:04
Show Gist options
  • Save gaymeowing/9da07c8b2dab5281e8056117e65c2cb5 to your computer and use it in GitHub Desktop.
Save gaymeowing/9da07c8b2dab5281e8056117e65c2cb5 to your computer and use it in GitHub Desktop.
TextChatUtil a small utility for TextChatService with mute & easy adding/removing from TextChatChannels as methods. Uses futures for async operations https://github.com/red-blox/Util/tree/main/libs/Future
--!strict
-- TextChatUtil
-- simple utility module for TextChat
-- @Kalrnlo
-- 21/03/2023
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TextChatService = game:GetService("TextChatService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Future = require(script.Parent.Future)
local VerifiedUnicode = utf8.char(0xE000) -- chat verified icon unicode
local DefualtMessagePrefix = ": "
local HasServerInitiated = false
local ChatNameColors = {
Color3.new(253/255, 41/255, 67/255), -- BrickColor.new("Bright red").Color,
Color3.new(1/255, 162/255, 255/255), -- BrickColor.new("Bright blue").Color,
Color3.new(2/255, 184/255, 87/255), -- BrickColor.new("Earth green").Color,
BrickColor.new("Bright violet").Color,
BrickColor.new("Bright orange").Color,
BrickColor.new("Bright yellow").Color,
BrickColor.new("Light reddish violet").Color,
BrickColor.new("Brick yellow").Color,
}
local AmountOfNameColors = #ChatNameColors
local function ComputeNameColor(Name: string)
local SubtractionNumber = if #Name % 2 == 1 then -1 else 0
local NameValue = 0
for Index, Codepoint in utf8.codes(Name) do
NameValue += if (((#Name - Index) + 1) - SubtractionNumber) % 4 >= 2 then
-Codepoint
else
Codepoint
end
return ChatNameColors[(NameValue % AmountOfNameColors) + 1]
end
local TextChatUtil = {}
-- If a channel is provided this will only mute the player in that channel
-- if not the player will be muted in all channels they are in
local function SetMuteForPlayer(IsMuted: boolean, Player: Player, Channel: TextChannel?)
assert(RunService:IsServer(), "Cannot mute player in TextChannel or TextChat on client")
if Channel then
local TextSource = Channel:FindFirstChild(Player.Name) :: TextSource
if TextSource then
TextSource.CanSend = IsMuted
end
else
for _, Object in TextChatService:GetDescendants() do
if not Object:IsA("TextChannel") then continue end
local TextSource = Object:FindFirstChild(Player.Name) :: TextSource
if not TextSource then continue end
TextSource.CanSend = IsMuted
end
end
end
local function RemovePlayerFromChannel(Player: Player, Channel: TextChannel)
assert(RunService:IsServer(), "Cannot remove player from TextChannel on client")
local TextSource = Channel:FindFirstChild(Player.Name)
if TextSource then
TextSource:Destroy()
return true
else
return false
end
end
local function AddPlayerToChannel(Player: Player, Channel: TextChannel)
assert(RunService:IsServer(), "Cannot add player to TextChannel on client")
return Future.new(function(Player: Player, Channel: TextChannel)
local CanPlayerChat = TextChatService:CanUserChatAsync(Player.UserId)
if not CanPlayerChat then return false end
-- The sucess value also indicates if the user can chat or not,
-- but in this case it only indicates if it didnt add a textsource,
-- or if it couldnt because the player left the game as
-- we already checked if the player can use chat or not
local TextSource, Sucess = Channel:AddUserAsync(Player.UserId)
if Player:IsDescendantOf(Players) and not TextSource and Sucess then
repeat
TextSource = Channel:AddUserAsync(Player.UserId)
RunService.PostSimulation:Wait()
until TextSource or not Player:IsDescendantOf(Players)
end
return TextSource ~= nil
end, Player, Channel)
end
local function GetColorForUserId(UserId: number)
return Future.Try(function(UserId: number)
return
end, UserId)
end
local function GetColorForName(Name: string)
local Player = Players:FindFirstChild(Name)
if Player then
local TeamColor3 = Player.TeamColor and Player.TeamColor.Color
return TeamColor3 or ComputeNameColor(Player.Name)
else
-- returning the defualt chat color otherwise
return TextChatService.ChatWindowConfiguration.TextColor3
end
end
local function GetColorForTextSource(TextSource: TextSource)
-- When adding a player to a channel, the TextSources name is the players username
-- so using TextSource.Name is fine
return GetColorForName(TextSource.Name)
end
local function IsPlayerMuted(Player: Player, Channel: TextChannel?)
assert(RunService:IsServer(), "Cannot mute player in TextChannel or TextChat on client")
if Channel then
local TextSource = Channel:FindFirstChild(Player.Name) :: TextSource
if TextSource then
return TextSource.CanSend
else
return true
end
else
-- just check if the player is muted in every single chat channel
local AmountOfChannelsMutedIn = 0
local NumberOfTextChannels = 0
for _, Descendant in TextChatService:GetDescendants() do
if Descendant:IsA("TextSource") then
if Descendant.UserId ~= Player.UserId then continue end
if Descendant.CanSend then continue end
AmountOfChannelsMutedIn += 1
elseif Descendant:IsA("TextChannel") then
NumberOfTextChannels += 1
end
end
return AmountOfChannelsMutedIn == NumberOfTextChannels
end
end
local function GetChatPrefix(
DisplayName: string,
Name: string,
HasVerifiedBadge: boolean?,
IncludeName: boolean?,
MessagePrefix: string?
)
local DisplayedName = if IncludeName then `{DisplayName}(@{Name})` else DisplayName
local ColorForUser = TextChatUtil.GetColorForName(Name):ToHex()
local MessagePrefix = MessagePrefix or DefualtMessagePrefix
DisplayName ..= if HasVerifiedBadge then VerifiedUnicode else ""
return `<font color="#{ColorForUser}">{DisplayedName}</font>{MessagePrefix}`
end
local Exports = table.freeze {
RemovePlayerFromChannel = RemovePlayerFromChannel,
GetColorForTextSource = GetColorForTextSource,
AddPlayerToChannel = AddPlayerToChannel,
GetColorForUserId = GetColorForUserId,
SetMuteForPlayer = SetMuteForPlayer,
GetColorForName = GetColorForName,
GetChatPrefix = GetChatPrefix,
IsPlayerMuted = IsPlayerMuted,
}
return Exports
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment