Header
This is a full port of LegacyChat, and not a recreation of LegacyChat
Current version: 1.1
Unstableish: use at your own risk, but core features seem stable. I’ll be testing it on my own, and I’ll be listening to bugs reported on this thread
Here is a list of changes done to the default LegacyChat
Pre 1.0
– Replaced the deprecated draggable property that was used with a custom drag function
– New features (Font objects, Chat Translation & more!) and bug fixes
– Implemented :CanUserDirectChatAsync()
1.0
– Ported LegacyChat to TextChatService’s api (includes modification of the PrivateMessaging module, for whisper, and removal of almost all text filtering functions)
– Moved all the Fast Flags (FFlags) into a FFlags
module
– Added the EchoMessagesFromHiddenChannels
setting, for use with the HiddenChannels
setting
– Bug fixes related to HiddenChannels
and dynamic resizing of message’s TextSize
– Some cleanup of the code
1.1
– Fixed error when sending a message in the system channel
– Fixed whisper not working due to me forgetting to add Chat:CanUsersDirectChatAsync() …
– Fixed Chat:CanUsersChatAsync() checking userIdTo twice, instead of userIdFrom and userIdTo
This could have been bad, but thankfully TextChatService:CanUsersChatAsync() was used internally instead
– Fixed the error message occurring when a player was leaving
– Destroying a TextSource now causes the associated speaker to leave the associated channel.
This behaviour also exists for TextChannels, destroying a TextChannel deletes the associated ChannelObj
– Added padding settings for the message log display (scrolling frame)
– Added texture settings for the underline bar of ChannelTabs
These two settings now allow for obtaining the exact look of the old LegacyChat
Up coming features:
– Support to make the OnIncomingMessage
callbacks be able to modify the look of messages
– More settings to customize the visual look of the chat (exact LegacyChat look, and using images on the background frames)
– System messages currently don’t go through TextChannels. I’ll make them go through TextChannels to allow OnIncomingMessage
callbacks to format the messages
– Adding types for MessageObj, and stuff
– Possibly getting the old bubble chat script working, if there is demand for it. I don’t really like the old bubble chat, so it’s not a priority
Known bugs:
– MessageHistoryLog is disabled by default. This is the last feature that is still using the legacy chat filtering system, as TextChatService doesn’t have an api to store previous messages. You can enable it in the FFlags
module, but make sure to disable it before April 30th
– TextChannel:SetDirectChatRequester()
is currently throwing the error SetDirectChatRequester is not enabled
. I wrapped it in pcalls, and whisper already uses :CanUsersDirectChatAsync()
so should be fine. I assume this is a roblox bug…
– The lock for keeping the scrolling frame at the bottom sometimes fail when resizing the chat
Things people will think are bugs:
– Text messages are stuck as being a ___ placeholder if TextChatService blocks the message from being delivered (ChatCommands, ShouldDeliverCallback, etc). Set ShowUnfilteredMessagePlaceholder
to false in the Settings
module to fix
Introduction
If you’ve been living under a rock, I announce to you the deprecation of the LegacyChat system. Well, it’s not just a deprecation, everyone will have to migrate to the TextChatService api before april 30th, aka LegacyChat can’t be used past that date
Last year, I posted a custom version of the LegacyChat in community resources, which provides a more modern look, bug fixes, features, and chat translation (which was a built in feature of LegacyChat, just had to overwrite some FFlags and add a bool value to get it working :P). This resource is built on top of that
I like the LegacyChat, has it is built fully in lua and accessible by developers, it is probably one of (if not the) most advanced chat system on Roblox, and is fully customizable. The code is quite daunting at first, but it’s definitely not messy code, and isn’t so hard to build onto.
This resource is not just for people looking to maintain compatibility with old code that relied on the LegacyChat, this resource is a custom chat, for those looking to customize their game’s chat
TextChatService, I don’t like so much as it’s less customizable, Player.Chatted has inconsistent behavious (doesn’t fire on the client for the LocalPlayer, but fires for other players? What?), which breaks older chat commands scripts, getting the unfiltered version of messages is a pain in the ass, TextChatCommands only accept two aliases and basically lacks customizability, and I don’t like that roblox is kinda forcing it onto us
I will refer to my custom chat as a custom Lua chat system, as it was named the Lua chat system before TextChatService arrived, and my custom chat is a modernized version :P
Files
By default, the chat looks like this
The chat should go into ReplicatedStorage (although any container that replicates to the client will work)
ChatSettings is THE module for customizing the chat. It contains a lot of settings for the look of the chat and behaviour, most of which are from the original Lua chat system, but it also contains new settings I added
If you plan to use the TextChatService’s api (TextChatCommands, ShouldDeliverCallback, OnIncomingMessage, etc), set the setting module.ShowUnfilteredMessagePlaceholder = false
How to get the old chat look
Download this settings file: ChatSettings.lua (6.6 KB)
and replace the contents of ChatSettings with the contents of this file
To disable chat translations, you can either set TextChatService.ChatTranslationEnabled
to false, or go into the FFlags
module and set FFlags.UserIsChatTranslationEnabled
to false
Download:
Creator store: https://create.roblox.com/store/asset/75678628110599
rbxm: Chat.rbxm (131.5 KB)
– Set TextChatService.ChatVersion to TextChatService
– Disable TextChatService.CreateDefaultCommands, and TextChatService.CreateDefaultTextChannels
– Disable TextChatService.ChatWindowConfiguration.Enabled, and TextChatService.ChatInputBarConfiguration.Enabled
Legacy Chat Compatibility & Changes Made
Here is a list of changes you’ll have to make to get your code working with this custom Lua chat system. You can use ctrl + shift + f to find and replace these in your scripts
LegacyChat | Custom Lua chat system |
---|---|
Chat = game:GetService("Chat") | Chat = require(game.ReplicatedStorage.Chat) |
Player.Chatted | Chat:GetPlayerChattedEvent(Player) Or Chat:GetChattedEvent() |
Chat:RegisterChatCallback(Enum.ChatCallbackType, func) | Chat:RegisterChatCallback(ChatCallbackType, func) ChatCallbackType is the name of the corresponding enum, as a string |
StarterGui:SetCore(...) | StarterGui:SetCore(...) |
StarterGui:GetCore(...) | StarterGui:GetCore(...) |
Other methods from the Chat service that aren’t related to the lua chat system are not included in this custom chat.
The chat scripts use the new RunContext property, this means ChatServiceRunner and ChatScript are no longer getting cloned into ServerScriptService and PlayerScripts. So if you are requiring ChatService
, require it inside ReplicatedStorage
– Chat:GetChattedEvent()
fires for any player and passes the player who chatted as the first argument. The arguments are Player : Player
, Message : string
and Recipient : Player?
. Recipient was a deprecated argument, but I brought it back.
– I’ve changed Chat:RegisterChatCallback(...)
to use a string instead of the ChatCallbackType Enum if I ever want to add more chat callback types in the future. You can do something like Enum.ChatCallbackType.[...].Name
to get the appropriate string for the new method
– StarterGui:SetCore()
and StarterGui:GetCore()
havn’t changed, I acutally forgot about those until I realized my game uses StarterGui:SetCore("ChatMakeSystemMessage",{...})
. They still work as they used to, but there is no garantee they’ll work past april 30th. If it does end up breaking, I’ll do a custom api for it
Deeper integration with the LegacyChat system
Now, if your code has a deeper integration with the LegacyChat system, such as custom channels, custom commands, etc, be wary of the following:
For this port of the Lua chat system, I modified the chat itself, instead of recreating it. This means that in theory, everything should work out of the box (after doing the changes mentioned above). However, that was in theory, and that theory got broken quite quickly when I had to fix the whisper system
The custom Lua chat system relies on two important things to work alongside TextChannels.
- First, the same message cannot be turned into multiple messageObjs (to be sent through different channels, in the case of whisper), since the TextChatService port requires that the ID of the messageObj received by the original sender is the same as the ID received by the receivers. When the sender receives back the messageObj from the server, it sends it through the associated TextChannel, with the ID as metadata, and the receivers will get the filtered message, and use the ID to associate it with their received messageObj
- Second, a player must be in the TextChannel as a TextSource to send a message and receive filtered messages, whilst LegacyChat is allowed to send a messageObj from speaker A using speaker B, making it so a speaker doesn’t need to be in the channel in which the message is sent
These issues were a problem because whisper uses two channels, one being To Player1
, the other being To Player2
, where Player2
is the only speaker of the To Player1
channel, and same for Player1
Because of this, two messageObj used to be created for the same message, and then would be sent to the two channels. Moreover, messages between speakers are sent through channels that only have one of the two speakers.
That doesn’t work with TextChatService. I had to come up with solutions for these two problems, and if you encounter the same issues with your custom channel (if anyone went that far…), here were the solutions:
- I moved the messageObj creation to an independant module, so whisper can create the messageObj directly in the command processor module script, and added
speaker:SendMessageObj(message, messageObj, channelName, fromSpeaker)
andchannel:SendMessageObjToSpeaker(message, messageObj, speakerName, fromSpeakerName)
, so the same messageObj can be sent to different channels - I added
speaker:JoinChannelAsListener(channelName)
,speaker:LeaveChannelAsListener(channelName)
,channel:InternalAddListenerSpeaker(speaker)
andchannel:InternalRemoveListenerSpeaker(speaker)
, which add a TextSource of the corresponding speaker to the TextChannel for TextChatService compatibility, without adding the speaker to the Lua chat system channel object
Other resources
There are already a handful of ports of the LegacyChat, but none that I’ve seen actually port LegacyChat as a whole. However, they might fit your needs better anyway, so here they are:
– Textchatservice disguised as Legacy Chat
– NewOldChat: Legacy Chat ported to TextChatService [BETA]
– Basic Legacy Chat Rewrite for TextChatService
– Old Chat System - LegacyChatSystem converted to TextChatService API
– WinryChat | Open-Source Chat UI for TextChatService (This one isn’t a “LegacyChat”)
There is also this post about using the Lua chat system:
– How to make chat-commands using the lua chat system
Here is the documentation page for the Lua chat system:
– Legacy chat system
– Lua Chat System (older version of the current docs, has some more stuff)
Footnotes
This post took so long to write ;-;
Anyway, I probably forgot some stuff, and I’ll probably rework the post as well. If you have any suggestion, feedback, or whatever, let me know!
If you want to test the chat without downloading it, I’ve added it to one of my games: Roblox - Game Discovery Hub. It will feel just like my custom LegacyChat though (that doesn’t use TextChatService), unless there are bugs