Last active
March 21, 2024 16:04
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--!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