Is there currently a way to temporarily disable the classic chat for a select group of players? I don’t want to disable the entire chat system (because I want the bubble chat to remain active), and I’m trying to avoid creating my own custom chat if possible.
I’ve tried forking the existing client chat modules and then editing them while a game is in session, but nothing happens. After reading through a number of pages on the forums, they only seem to discuss how to disable the chat overall, or how to disable classic chat permanently. I’ve also looked at RegisterChatCallback and other similar API pages. It seems like most of these only disable chat upon the window being created. The BubbleChatEnabled property under the Chat service is close to what I want, but I’m trying to toggle classic chat, not bubble chat.
Any help would be appreciated. In short, I want to be able to remove a player’s classic chat mid-game, not right when a player joins, and I want them to keep their bubble chat when their classic chat is removed.
You’ll need to create a remote event in a location shared between the server and clients like ReplicatedStorage. Then when you want the chat to be disabled, fire the event at the players you want the chat to be disabled with by using :FireClient(). Then you’ll need a LocalScript for the client to receive the event action and turn off the chat when fired.
--Server Script
local DisableChatEvent = game:GetService("ReplicatedStorage"):WaitForChild("DisableChatEvent")
local TargetPlayers = {Player1, Player2, etc.} --Add the players to this array using their Player object.
for _,FocusedPlayer in ipairs(TargetPlayers) do --Does the following for every target player:
if FocusedPlayer then --Checks to make sure the player exists before firing the event. (In case they left the game.)
Event:FireClient(FocusedPlayer) --Sends a signal to each target player.
end
end
--Client LocalScript (A good location would be PlayerStarterScripts)
local DisableChatEvent = game:GetService("ReplicatedStorage"):WaitForChild("DisableChatEvent")
DisableChatEvent.OnClientEvent:connect(function()
game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.Chat, false)
end)
You can make another event that would do the same thing but for turning the chat on instead of off. Then fire that event after however long of a period of time or until you want those players to have chat enabled again.
Make a custom chat system that relies on server-side for both types of chats, (a bubble chat and a list type chat) Then manipulate the custom GUIs! The only reason I’m suggesting this, is because it’s an alternative to relying on a LocalScript to enable/disable CoreGui. This method probably won’t fix exploitation of events firing, but, you’re controlling the chat being enabled/disabled on the server exclusively, per player, instead of remoting their CoreGuis on and off. For one instance, if they copied the custom chat GUI and typed a message, it wouldn’t send because you disabled them server-side!
Unfortunately, this doesn’t solve my problem. I’m trying to disable classic chat only, not the entire chat system. In other words, I still want bubble chat to be available for players. Disabling the Chat CoreGui would disable all methods of chatting. But thank you regardless.
I am fully aware that creating a custom chat system would enable me to achieve what I want, but the problem is that I want to work with Roblox’s default chat system.
I’m still looking for API documentation that enables me to achieve this with their current system and I can’t seem to find anything which is surprising considering the amount of features they’ve been adding to chat over the years (e.g. channels, modifying bubble chat).
You could set the classic chat enabled property using a localscript, but it wont unanimize (my word for “make unanimous”) the chat when an exploiter just enables the property
Disabling the Chat using CoreGui does not disable bubble chat. Users with CoreGui Chat disabled will still see bubble chat.
Enabling and disabling Chat.BubbleChatEnabled is what determines whether or not players will see player’s bubble chats. Bubble chat is not a CoreGui, it’s a LocalScript that displays chat messages above parts in the form of BillboardGuis. If Chat.BubbleChatEnabled is false, it won’t display bubbles for players. Objects and NPCs can still use bubble chat, even with bubble chat disabled. If Chat.BubbleChatEnabled is true, it will display bubbles for all players, regardless of your CoreGui Chat setting.
I’m confused as to what you’re trying to achieve here.
Do you still want them to have the capability to chat even without a chat window? Without a text display, it can be extremely difficult for the player to keep track of what they’re typing and for the player to tell if they’re making any typos.
If so, you really only have two options.
You can remove the visibility of everything other than the input field UI (highlighted below).
For example:
--Server Script
local ChatEvent = game:GetService("ReplicatedStorage"):WaitForChild("DisplayChatEvent") --A remote event.
local TargetPlayers = {Player1, Player2, Player3, etc.} --Add the players to this array using their Player object.
for _,FocusedPlayer in ipairs(TargetPlayers) do --Does the following for every target player:
if FocusedPlayer then --Checks to make sure the player exists before firing the event. (In case they left the game.)
ChatEvent:FireClient(FocusedPlayer, false) --Sends a signal to each target player.
end
end
--LocalScript in StarterPlayerScripts
local LocalPlayer = game:GetService("Players").LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
local PreviousSettings = {}
local CurrentlyHidden = false --debounce.
game:GetService("ReplicatedStorage"):WaitForChild("DisplayChatEvent").OnClientEvent:Connect(function(EnableOrDisable)
local ChatGui = PlayerGui:FindFirstChild("Chat")
if not ChatGui then return end
local Frame = ChatGui:FindFirstChild("Frame")
local TextEntryParentFrame = ChatGui:FindFirstChild("ChatBarParentFrame", true)
if not TextEntryParentFrame or not Frame then return end
for i,v in pairs(ChatGui:GetDescendants()) do
if v:IsA("GuiObject") and v ~= Frame and v ~= TextEntryParentFrame and not v:IsDescendantOf(TextEntryParentFrame) then
if EnableOrDisable == false and CurrentlyHidden == false then
PreviousSettings[v] = v.Visible
v.Visible = false
elseif EnableOrDisable == true then
if type(PreviousSettings[v]) == "boolean" then
v.Visible = PreviousSettings[v]
end
end
end
end
if EnableOrDisable == true then
PreviousSettings = {} --Reset settings.
CurrentlyHidden = false
elseif EnableOrDisable == false then
CurrentlyHidden = true
end
end)
OR
You’d have to make your own custom chat and/or input field. The easiest way is probably moving a TextBox off screen and focusing it when the player presses the / key and use Players:Chat() when the player presses the Enter key. (Though I am unsure if Enter is detected by InputBegan from a mobile keyboard.)
For example:
local LocalPlayer = game:GetService("Players").LocalPlayer
local PlayerScripts = LocalPlayer:WaitForChild("PlayerScripts")
local TextBox = nil --A textbox object.
TextBox.Position = UDim2.new(math.huge,0,math.huge,0)
local MobileButton = nil --A mobile button to toggle the chat entry. (optional)
TextBox.ClearTextOnFocus = true --Since the TextBox will be hidden off screen and the player can't see their own text, it's probably a good idea to clear the text on focus.
local UIS = game:GetService("UserInputService")
function OnChatButtonPressed()
if UIS.OnScreenKeyboardVisible == true and TextBox.Focused then --Toggle on screen keyboard
TextBox:ReleaseFocus()
return
end
TextBox:CaptureFocus()
local EnterPressed = false
local EnterCon = UIS.InputBegan:Connect(function(SubInput)
if SubInput.KeyCode == Enum.KeyCode.Return then
EnterPressed = true
end
end)
TextBox.FocusLost:Wait()
task.wait(0.1) --Wait needed so FocusLost and Enter input don't overlap.
if EnterPressed == true then
local Character = LocalPlayer.Character
if Character then
local DesiredMessage = TextBox.Text
if string.find(DesiredMessage,"/") == 1 then --Remove any / characters at the beginning of the message if :CaptureFocus responds too quickly.
repeat DesiredMessage = DesiredMessage:gsub("/", "", 1)
until string.find(DesiredMessage,"/") ~= 1
end
TextBox.Text = DesiredMessage
local ChatModule = PlayerScripts:FindFirstChild("ChatMain", true)
if ChatModule then
if ChatModule:IsA("ModuleScript") then
local ChatMain = require(ChatModule)
local MessageEvent = ChatMain.MessagePosted
if MessageEvent then
--pcall(function() MessageEvent:Fire({TextBox.Text}) end) --MessagePosted bindable is currently broken as of 6/13/2022 (I also tried the SetCore method, same result) so you'll have to use Chat:Chat() instead. If they fix it, use this line instead of Chat:Chat().
if game.Chat.BubbleChatEnabled == true then --Need to check if bubble chat is enabled before using :Chat() since it would make a bubblechat even if it were disabled.
game:GetService("Chat"):Chat(Character, TextBox.Text)
end
end
end
end
end
end
EnterCon:Disconnect()
end
UIS.InputBegan:Connect(function(Input)
if UIS:GetFocusedTextBox() then --Checks to make sure they aren't currently chatting/inputting.
return
end
if Input.KeyCode == Enum.KeyCode.Slash then
OnChatButtonPressed()
end
end)
if MobileButton then
if UIS.TouchEnabled then
MobileButton.TouchTap:connect(OnChatButtonPressed)
else
MobileButton.Visible = false
end
end
The classic chat is disabled, but the bubble chat is not. And as you can see, they have the capability to chat with a text display, so it’s easy to tell if typos are being made.
The issue I’m having is, as far as I can tell, I can only achieve this with Roblox’s Enum.ChatCallbackType.OnCreatingWindow. In other words, I can’t seem to disable and enable the chat whenever I want, but instead whenever the window is created.
I hope this further clarifies what I was looking for. Your sample code actually does what I want and I’ll embarrassingly admit that I never realized the chat was accessible via PlayerGui. Instead of disabling/enabling via RegisterChatCallback, I’ll just change the visibility and then adjust the chat bar’s offset so it isn’t sticking in the middle of the screen for no reason.