Hierarquía
El sistema de chat de legado usa el modelo cliente-servidor. Los componentes del módulo de chat del lado del servidor son ChatChannel y ChatSpeaker, mientras que los componentes del módulo de chat del lado del cliente son 2>Class.RemoteEvent|RemoteEvents2> y 5>Class.RemoteEvent|RemoteEvents5>.
El servicio de motor Chat en sí mismo es la unidad de almacenamiento esencial para el sistema de chat: cuando se carga un lugar de Roblox (ya sea en el cliente o en Studio al ejecutar o jugar), los siguientes componentes se cargan automáticamente en el servicio de Chat si Chat.LoadDefaultChat es cierto.
- ChatModuleScript — Este Folder es una colección de módulos que son requeridos por el servicio de chat . Todo el contenido de este directorio se requiere por el script y se usa para crear un comportamiento personalizado en el servidor.
- ClientChatModuleScript — Este directorio contiene varios ModuleScripts requeridos por el ChatScript .
- CommandModuleScript — Contiene módulos que se usan para implementar comandos de chat del lado del cliente.
- Modulo de Creador de Mensajes — Contiene módulos usados para manejar y formatar mensajes.
- ChatCommands — Contiene constantes compartidas por el servidor y el cliente.
- ChatSettings — Almacena varias configuraciones para configurar diferentes aspectos de la Ventana de chat .
- ChatLocalization — Estructura de datos que almacena traducciones de texto.
- ChatServiceRunner — Esto Script ejecuta el componente del servidor del chat. En general, esto no necesita ser modificado para crear un comportamiento y funcionalidad de chat personalizados.
- BubbleChat — Muestra los mensajes de chat del usuario por encima de su avatar (si se habilita).
- ChatScript — Este LocalScript ejecuta el componente del cliente del chat. Como ChatServiceRunner, esto no debería necesitar ser modificado para personalizar el chat. Cuando el juego ejecuta esto, se clona automáticamente en el StarterPlayerScripts .
Modificando el sistema de chat
Para modificar o personalizar el sistema de chat legado, debe hacer una copia de la jerarquía de arriba.
En la ventana Explorer, localiza TextChatService. Luego, en la ventana Propiedades, establece la propiedad 2> ChatVersion2> en 5> LegacyChatService 5> .
Ejecute la experiencia usando el botón Jugar ( F5 ).
Seleccione y copie ( CtrlC o ⌘C ) los objetos que se agregan a 2> Class.chat2> .
Detenga la experiencia usando el botón Detener ( ShiftF5 ).
Seleccione Chat y pegar en (Ctrl 0> Shift 0> 2> V 2> o 5> ⌘ 5> 7> Shift7> 9> V9>).
Asegúrese de que Chat.LoadDefaultChat esté habilitado.
Flujo de trabajo de chat
Antes de crear módulos para personalizar el chat, es importante comprender el flujo de trabajo que pasa a través de un mensaje de chat. Junto con enviar mensajes de texto, hay varios comandos construidos en el sistema de chat, por lo que cada mensaje debe ser revisado para ver si necesita ser interpretado como un comando o solo un mensaje de texto. incluso los mensajes de texto se pueden modificar y filtrar en el proceso.
Luego de que un usuario tenga enfoque en la entrada de chat y ingrese a un personaje, varios cheques se hacen inmediatamente en el client. Si el personaje es Esc, la caja de entrada se cierra y no se toman
En el lado del cliente de chat, hay dos tipos de procesadores: En progreso y Completado . El primero se ejecuta después de que cada personaje se haya escrito, mientras que el segundo solo se ejecuta cuando el usuario haya terminado de escribir y haya presionado Ingrese .
Cuando el usuario termina de escribir y presiona Entrar el texto, su entrada se envía a través de varios procesadores de comando más. Si se hace un comando In-Progress personalizado, el chat verifica el estado para ver si se debe ejecutar un comando final y si el mensaje debe continuar. Si el mensaje se permite
Una vez que el mensaje llegue al servidor, pasa a través de otro conjunto de procesadores de comando. Justo como los Completado procesadores en el cliente, si alguno de estos procesadores regresa veraz, entonces el mensaje deja de ejecutarse. De lo contrario, el mensaje se envía a todos los canales y los hablantes apropiados.
Módulos del servidor
Los módulos puestos en ChatModuleScript se pueden usar para una variedad de propósitos. Estos módulos se pueden usar para administrar canales de chat y hablantes, agregar filtros y funciones de comando, ejecutar chatbots o cualquier otra cosa que se necesita para manejar en el servidor. Para interactuar con el sistema de chat, cada módulo se pasa un objeto de ChatService .
Cuando el ChatServiceRunner se inicia, requiere cada módulo dentro de ChatModule . Espera que cada módulo devuelva una función como luego llama a cada uno de los módulos en orden, pasando en ella su objeto de ChatService a cada uno de los módulos. Independientemente de lo que el módulo esté destinado a hacer (ejecutar un bot, agregar una función de filtro, etc), necesita segu
Marco de módulo de ejemplo
local function Run(ChatService)
-- El código va aquí
end
return Run
Añadir canales
Una de las cosas más simples que un ChatModule puede hacer es administrar canales . Los objetos de canal se pueden crear con el método AddChannel() de 1> ChatService1> . Nota que el objeto de canal solo se necesita cuando se refiere a los miembros de ese canal (como sus propiedades
local function Run(ChatService)
local myChannel = ChatService:AddChannel("MyChannel")
end
return Run
Configuración básica del canal
Los canales tienen varias propiedades que se pueden usar para modificarlos ligeramente. Por ejemplo, este módulo crea un canal y establece el mensaje de bienvenida y hace que los usuarios se unan automáticamente al canal cuando ingresan a la experiencia.
local function Run(ChatService)
local myChannel = ChatService:AddChannel("MyChannel")
-- Establece el mensaje que se muestra cuando un usuario se une al canal
myChannel.WelcomeMessage = "Welcome to my channel!"
-- Causa que los jugadores se unan automáticamente al canal cuando ingresen al juego
myChannel.AutoJoin = true
end
return Run
Eventos de canal
Los canales tienen varios eventos a los que se puede suscribir. Estos eventos se activan cuando se publica un Mensaje de chat al canal, cuando se hace clic en un locutor para salir o unirse, o cuando se silencia o activa un MyChannel. Por ejemplo, este módulo creará un canal con el nombre 2>MyChannel2>
local function Run(ChatService)
local myChannel = ChatService:AddChannel("MyChannel")
local function onSpeakerJoined(speakerName)
myChannel:SendSystemMessage(speakerName .. " has joined the channel.")
end
local function onSpeakerLeft(speakerName)
myChannel:SendSystemMessage(speakerName .. " has left the channel.")
end
myChannel.SpeakerJoined:Connect(onSpeakerJoined)
myChannel.SpeakerLeft:Connect(onSpeakerLeft)
end
return Run
Comandos
Otra poderosa cosa que ChatModule puede hacer son los comandos de chat. Cuando se envía un mensaje al servidor, el chat enviará el mensaje a través de cada fun
Las funciones de comando a menudo se utilizan para implementar Comandos de administrador, que son comandos de texto que algunos usuarios pueden usar para manipular el estado de la experiencia a través de un texto específico dicho en el chat.
En este ejemplo, se usa ChatModule para crear un Part si un usuario escribe /part en el chat. Nota que esta función devuelve true si se creó una parte que detendrá el mensaje y no se mostrará ningún mensaje. Si no se creó una parte, esta función debe devolver false para que el mensaje funcione a través del sistema.
local function Run(ChatService)
local function createPart(speakerName, message, channelName)
if string.sub(message, 1, 5) == "/part" then
local newPart = Instance.new("Part")
newPart.Parent = workspace
return true
end
return false
end
ChatService:RegisterProcessCommandsFunction("createPart", createPart)
end
return Run
Ambos ChatChannels y ChatService pueden tener comandos de chat. El procesador de comandos de ChatService se ejecutará en cada mensaje que se envía al servidor, mientras que los comandos de canal solo se ejecutarán si el mensaje se envió al canal al que se registra el comando.
Filtrar funciones
Mensajes que no son detenidos por una función de comando pasarán a través de todas las funciones de filtro que están registradas en el ChatService y los canales relevantes. Cada función de filtro se pasa al bocina, el objeto de mensaje y el nombre del canal. Cualquier cambio en el objeto de mensaje persistirá y cada función de filtro verá el mensaje actualizado. Nota que las funciones de filtro no necesitan devolver un valor.
En este ejemplo, se registra una simple función de filtro para hacer que cada mensaje aparezca en mayúsculas.
local function Run(ChatService)
local function makeLowercase(sender, messageObject, channelName)
messageObject.Message = string.lower(messageObject.Message)
end
ChatService:RegisterFilterMessageFunction("makeLowercase", makeLowercase)
end
return Run
Módulos de cliente
Los módulos puestos en ClientChatModule se pueden usar para proporcionar un comportamiento personalizado para los clientes. Estos módulos se dividen en dos directorios diferentes: Módulos de Comando y Creador de Mensajes .
Módulos de comando
Los Módulos de Comando funcionan muy similarmente a los módulos en el servidor que registran 함수 de Comando . Estos módulos definen funciones que se ejecutarán después de que el usuario ingrese en texto. Ese texto se puede leer y el comando puede omitir el mensaje a través del
En ambos tipos de comandos, el módulo debe返回一个字典 que dice qué tipo de procesador debe usar el comando, y qué función ejecutar cuando se llama el procesador. Por ejemplo, un procesador de mensajes completado debe tomar la forma:
local util = require(script.Parent:WaitForChild("Util"))
function ProcessMessage(message, ChatWindow, ChatSettings)
end
return {
[util.KEY_COMMAND_PROCESSOR_TYPE] = util.COMPLETED_MESSAGE_PROCESSOR,
[util.KEY_PROCESSOR_FUNCTION] = ProcessMessage
}
Nota que el KEY_COMMAND_PROCESSOR_TYPE tipo de lista está definido en el Util ModuleScript dentro de la carpeta 1> CommandModuleScript1> dentro de la carpeta de 4>Commandos4>.
Comandos de mensaje completados
Comandos de Mensaje Completado son evaluados cuando el usuario ha terminado de escribir y ha presionado Entrar . La función del procesador se pasa el objeto ChatMessage , la ventana de chat del cliente y la tabla 0> ChatSettings 0>. Si la función devuelve true, entonces el
Por ejemplo, el siguiente procesador eliminará el mensaje más antiguo en el canal actual si el usuario ingresa el comando /last .
local util = require(script.Parent:WaitForChild("Util"))
function ProcessMessage(message, ChatWindow, ChatSettings)
if string.sub(message, 1, 5) == "/last" then
local currentChannel = ChatWindow:GetCurrentChannel()
if currentChannel then
currentChannel:RemoveLastMessageFromChannel()
end
return true
end
return false
end
return {
[util.KEY_COMMAND_PROCESSOR_TYPE] = util.COMPLETED_MESSAGE_PROCESSOR,
[util.KEY_PROCESSOR_FUNCTION] = ProcessMessage
}
Comandos en progreso
Comandos en progreso son evaluados cada vez que un usuario escribe un personaje en la entrada de chat. Por ejemplo, el siguiente código toca un clack después de cada tecla para hacer que suene como si el usuario estuviera escribiendo en un tipowriter:
local util = require(script.Parent:WaitForChild("Util"))
local keyEffect = Instance.new("Sound")
keyEffect.SoundId = "rbxassetid://12221976"
keyEffect.Parent = script
function ProcessMessage(message, ChatWindow, ChatBar, ChatSettings)
keyEffect:Play()
end
return {
[util.KEY_COMMAND_PROCESSOR_TYPE] = util.IN_PROGRESS_MESSAGE_PROCESSOR,
[util.KEY_PROCESSOR_FUNCTION] = ProcessMessage
}
A menudo se utilizan los comandos en progreso para crear un estado personalizado para que el chat envíe mensajes a usuarios específicos en lugar de solo el canal actual. Por ejemplo, los sistemas Whisper y Team Chat verifican si el usuario ha escrito /whisper o /team respectivamente y envía el mensaje terminado a solo los usuarios apropiados.
Se espera que un estado personalizado sea una tabla con las siguientes funciones:
- TextUpdated() — Llamado cuando el texto en la caja de entrada cambia.
- GetMessage() — Llamado después de que el usuario haya terminado de ingresar el mensaje y golpee Enter . Esta función se espera que devuelva una cadena.
- ProcessCompletedMessage() — Llamado como el mensaje se está procesando. Un procesador de estado personalizado siempre se ejecutará antes de que se ejecuten los procesadores de mensajes completados. Como otros procesadores, esta función siempre debería devolver true si el mensaje debería dejar de enviarse, de lo contrario debería devolver false.
- Destroy() — Llamado después de que se envíe el mensaje. Se debe usar para limpiar cualquier cosa que se haya configurado por el estado personalizado.
Para usar un estado personalizado, la función ProcessMessage() del módulo de comandos debe devolver el estado. Un estado personalizado básico tomaría la siguiente forma:
local util = require(script.Parent:WaitForChild("Util"))
local oneLineState = {}
oneLineState.__index = oneLineState
function oneLineState:TextUpdated()
local text = self.TextBox.Text
local length = string.len(text)
if length > 20 then
local chopLength = length - 20
local addToPrefix = string.sub(text, 1, chopLength)
self.Prefix = self.Prefix .. addToPrefix
self.TextBox.Text = string.sub(text, chopLength + 1)
end
end
function oneLineState:GetMessage()
local fullString = self.Prefix .. self.TextBox.Text
return fullString
end
function oneLineState:ProcessCompletedMessage()
return false
end
function oneLineState:Destroy()
self.Destroyed = true
end
function oneLineState.new(ChatWindow, ChatBar, ChatSettings)
local obj = {}
setmetatable(obj, oneLineState)
obj.Destroyed = false
obj.ChatWindow = ChatWindow
obj.ChatBar = ChatBar
obj.ChatSettings = ChatSettings
obj.TextBox = ChatBar:GetTextBox()
obj.MessageModeLabel = ChatBar:GetMessageModeTextLabel()
obj.Prefix = ""
return obj
end
local function ProcessMessage(message, ChatWindow, ChatBar, ChatSettings)
return oneLineState.new(ChatWindow, ChatBar, ChatSettings)
end
return {
[util.KEY_COMMAND_PROCESSOR_TYPE] = util.IN_PROGRESS_MESSAGE_PROCESSOR,
[util.KEY_PROCESSOR_FUNCTION] = ProcessMessage
}
Una de las principales ventajas de usar un estado personalizado es que un módulo puede editar la barra de chat y su contenido mientras el usuario está escribiendo tanto en términos de función como de apariencia, y luego se reinicia fácilmente después (una vez enviado el mensaje, todos los caracteres eliminados se restablecen). Por ejemplo, este código crea un estado personalizado que solo
local util = require(script.Parent:WaitForChild("Util"))
local oneLineState = {}
oneLineState.__index = oneLineState
function oneLineState:TextUpdated()
local text = self.TextBox.Text
local length = string.len(text)
if length > 20 then
local chopLength = length - 20
local addToPrefix = string.sub(text, 1, chopLength)
self.Prefix = self.Prefix .. addToPrefix
self.TextBox.Text = string.sub(text, chopLength + 1)
end
end
function oneLineState:GetMessage()
local fullString = self.Prefix .. self.TextBox.Text
return fullString
end
function oneLineState:ProcessCompletedMessage()
return false
end
function oneLineState:Destroy()
self.Destroyed = true
end
function oneLineState.new(ChatWindow, ChatBar, ChatSettings)
local obj = {}
setmetatable(obj, oneLineState)
obj.Destroyed = false
obj.ChatWindow = ChatWindow
obj.ChatBar = ChatBar
obj.ChatSettings = ChatSettings
obj.TextBox = ChatBar:GetTextBox()
obj.MessageModeLabel = ChatBar:GetMessageModeTextLabel()
obj.Prefix = ""
return obj
end
local function ProcessMessage(message, ChatWindow, ChatBar, ChatSettings)
return oneLineState.new(ChatWindow, ChatBar, ChatSettings)
end
return {
[util.KEY_COMMAND_PROCESSOR_TYPE] = util.IN_PROGRESS_MESSAGE_PROCESSOR,
[util.KEY_PROCESSOR_FUNCTION] = ProcessMessage
}
Como se mencionó antes, una vez que se envía un mensaje, cualquier estado personalizado se elimina y el chat se restablece a la normalidad. Si es necesario restablecer un estado personalizado antes de enviar el mensaje, el estado se puede restablecer con ChatBar:ResetCustomState() . Nota que esto eliminará el enfoque de la caja de texto de la barra de chat.
Creador de mensajes
Otro tipo de módulo que se puede utilizar en el módulo del cliente es un módulo Creador de mensajes . Este tipo de módulo se utiliza para crear los elementos de la GUI en la ventana de chat para mostrar el mensaje. Cada tipo de creador de mensajes define un nuevo introducirde mensaje, por lo que se pueden crear diferentes tipos de mensajes con diferentes formas de formato. Además, los elementos de GUI se pueden agregar a la pantalla de mensajes
Estos módulos requieren la configuración en varios lugares diferentes. Para cada introducirde mensaje, debe haber un ModuleScript dentro de MessageCreatorModuleScript . Además, el ChatConstructo 1> Class.ModuleScript1> necesita ser editado para incluir el nuevo introducirde mensaje. Por último, los módulos solo se usan si un componente del servidor de chat crea un
El siguiente ejemplo pasará por hacer un bot que dice el tiempo cada 5 segundos, y el mensaje que se envía obtiene un fondo rojo.
Para iniciar, el ChatConstraints ModuleScript necesita agregar un campo para el nuevo tipo de mensaje.
-- Constantes de chatlocal module = {}--<-[[ Tipos de mensaje ]]module.MessageTypeDefault = "Message"module.MessageTypeSystem = "System"module.MessageTypeMeCommand = "MeCommand"module.MessageTypeWelcome = "Welcome"module.MessageTypeSetCore = "SetCore"module.MessageTypeWhisper = "Whisper"module.MessageTypeTime = "Time"module.MajorVersion = 0module.MinorVersion = 2return module
El propio bot se crea en un nuevo ChatModule en el servidor. Tenga en cuenta que una función de filtro se utiliza para agregar el nuevo tipo de mensaje a los mensajes que envía el bot.
-- Nuevo ModuloScript para colocar en ChatModule
local Chat = game:GetService("Chat")
local ReplicatedModules = Chat:WaitForChild("ClientChatModules")
local ChatConstants = require(ReplicatedModules:WaitForChild("ChatConstants"))
local function Run(ChatService)
local timeBot = ChatService:AddSpeaker("TimeBot")
timeBot:JoinChannel("All")
local function addMessageType(speaker, messageObject, channelName)
if speaker == "TimeBot" then
messageObject.MessageType = ChatConstants.MessageTypeTime
end
end
ChatService:RegisterFilterMessageFunction("TimeBotFilter", addMessageType)
task.spawn(function()
while task.wait(5) do
timeBot:SayMessage("The current time is: " .. os.time(), "All", {})
end
end)
end
return Run
Por último, se debe hacer un módulo de creador de mensajes. Este módulo debe返回一个字典 con dos elementos: el tipo de el mensaje, indexado con KEY_MESSAGE_TYPE , y la función para llamar cuando se crean los elementos de GUI del mensaje, indexados con KEY_CREATOR_FUNCTION .
La función almacenada por KEY_CREATOR_FUNCTION necesita devolver un diccionario con varios componentes. Prim
-- nuevo ModuleScript para incluirse en MessageCreatorModule
local messageCreatorModules = script.Parent
local util = require(messageCreatorModules:WaitForChild("Util"))
local clientChatModules = messageCreatorModules.Parent
local ChatSettings = require(clientChatModules:WaitForChild("ChatSettings"))
local ChatConstants = require(clientChatModules:WaitForChild("ChatConstants"))
local function CreateMessageLabel(messageData, channelName)
-- Crea los objetos de GUI para que la etiqueta de marco y texto lleve el mensaje
local BaseFrame, BaseMessage = util:CreateBaseMessage("", ChatSettings.DefaultFont, ChatSettings.ChatWindowTextSize, ChatSettings.DefaultMessageColor)
-- Cambia el fondo del marco a rojo
BaseFrame.BackgroundColor3 = Color3.new(1,0,0)
BaseFrame.BackgroundTransparency = 0
-- Manipular texto de mensaje de actualización
local function UpdateTextFunction(messageObject)
if messageObject.IsFiltered then
BaseMessage.Text = messageObject.Message
end
end
UpdateTextFunction(messageData)
-- Usa la función util para determinar la altura de la imagen
local function GetHeightFunction(xSize)
return util:GetMessageHeight(BaseMessage, BaseFrame, xSize)
end
-- Crea funciones de desaparición que se llaman cuando la ventana de chat desaparece
local FadeParameters = {}
FadeParameters[BaseMessage] = {
TextTransparency = {FadedIn = 0, FadedOut = 1},
TextStrokeTransparency = {FadedIn = 0.75, FadedOut = 1}
}
local FadeInFunction, FadeOutFunction, UpdateAnimFunction = util:CreateFadeFunctions(FadeParameters)
-- Devolver el diccionario que define la etiqueta de mensaje
return {
[util.KEY_BASE_FRAME] = BaseFrame,
[util.KEY_BASE_MESSAGE] = BaseMessage,
[util.KEY_UPDATE_TEXT_FUNC] = UpdateTextFunction,
[util.KEY_GET_HEIGHT] = GetHeightFunction,
[util.KEY_FADE_IN] = FadeInFunction,
[util.KEY_FADE_OUT] = FadeOutFunction,
[util.KEY_UPDATE_ANIMATION] = UpdateAnimFunction
}
end
return {
[util.KEY_MESSAGE_TYPE] = ChatConstants.MessageTypeTime,
[util.KEY_CREATOR_FUNCTION] = CreateMessageLabel
}