Ierarchia
Il sistema di chat legacy usa il modello client-server. I componenti del modulo di chat lato server sono gestiti da ChatChannel e ChatSpeaker mentre la gestione del client è affidata al 2>ChatService2> sul Server, mentre la comunicazione tra il server e i client è gestita automaticamente utilizzando 5>Class.RemoteEvent|RemoteEvents5>.
Il servizio motore Chat è l'unità di archiviazione essenziale per il sistema di chat: quando viene caricato un luogo Roblox (anche nel client o in Studio quando si esegue o si gioca), i seguenti componenti vengono caricati automaticamente nel servizio Chat se Chat.LoadDefaultChat è vero.
- ChatModuleScript — Questo Folder è una collezione di moduli che sono richiesti dal ChatServiceRunner . Tutti i contenuti di questo cartelletta sono richiesti dallo script e vengono utilizzati per creare comportamenti personalizzati sul Server.
- ClientChatModule — Questa cartella contiene varie ModuleScripts richieste dal ChatScript .
- CommandModuleScript — Contiene moduli utilizzati per implementare comandi di chat lato client.
- MessageCreatorModule — Contiene moduli utilizzati per gestire e formattare i messaggi.
- ChatCommands — Contiene costanti condivise dal server e dal client.
- ChatSettings — memorizza varie impostazioni per configurare diversi aspetti della ChatWindow .
- ChatLocalization — Struttura dei dati che memorizza le traduzioni del testo.
- ChatServiceRunner — Questo Script esegue il server component del chat. In generale, non è necessario modificare per creare un comportamento e una funzionalità di chat personalizzati.
- BubbleChat — Mostra i messaggi di chat dell'utente sopra il loro avatar (se abilitato).
- ChatScript — Questo LocalScript esegue il client component del chat. Come ChatServiceRunner, questo non dovrebbe essere modificato per personalizzare il chat. Quando il gioco esegue questo viene clonato automaticamente nel StarterPlayerScripts .
Modificare il sistema di chat
Per modificare o personalizzare il sistema di chat legacy, devi prima creare una copia della gerarchia sopra.
Nella finestra Explorer, individua TextChatService . Quindi, nella finestra Proprietà, imposta la proprietà 2> ChatVersion2> su 5> LegacyChatService5> .
Esegui l'esperienza usando il pulsante Gioca ( F5 ).
Seleziona e copia ( CtrlC o ⌘C ) gli oggetti che vengono aggiunti a 2> Class.Chat2> .
Interrompi l'esperienza utilizzando il pulsante Interrompi ( ShiftF5 ).
Assicurati che Chat.LoadDefaultChat sia Abilitato.
Workflow di chat
Prima di creare moduli per personalizzare la chat, è importante capire il flusso di lavoro che un messaggio di chat passa attraverso. Insieme all'invio di messaggi di testo, ci sono varie comandi costruiti nel sistema di chat, quindi ogni messaggio deve essere controllato per vedere se devono essere interpretati come un comando o solo un messaggio di Messaggio. Anche i messaggi di testo possono essere modificati e filtrati nel processo.
Dopo che un utente ha il focus nell'input del chat e inserisce un personaggio, diversi check vengono eseguiti immediatamente sul client. Se il personaggio è Esc, l'input box si chiude e non vengono prese azioni. Se il personaggio
Nella parte client del chat, ci sono due tipi di processori: In corso di elaborazione e Completato . Il primo valuta dopo che ogni personaggio è stato digitato, mentre il secondo valuta solo quando l'utente ha finito di digitare e ha raggiunto Inserisci .
Quando l'utente finisce di digitare e premi Inserisci il testo, il loro input viene inviato attraverso più processori di comando. Se un comando In corso viene eseguito con uno stato di chat Server, il chat controlla lo stato per vedere se un comando finale deve essere eseguito e se il messaggio deve essere continu
Una volta che il messaggio raggiunge il Server, viene eseguito attraverso un altro set di elaboratori di comando. Come i Completati elaboratori sul client, se qualsiasi di questi elaboratori restituisce vero, allora il messaggio smette di essere eseguito. Altrimenti il messaggio viene inviato a tutti i canali e ai relatori appropriati. Una volta che tutto questo è fatto il messaggio viene inviato a tutti i canali e ai relatori appropriati.
Moduli del server
I moduli inseriti in ChatModule possono essere utilizzati per una varietà di scopi. Questi moduli possono essere utilizzati per gestire canali e speaker di chat, aggiungere filtri e funzioni di comando, eseguire bot di chat o qualsiasi altra cosa che deve essere gestita sul Server. Per interagire con il sistema di chat, ogni modulo è passato un oggetto ChatService .
Quando il ChatServiceRunner inizia, richiede ogni modulo all'interno di ChatModule . Especta che ogni modulo restituisca una funzione come poi chiama ciascun modulo in turno, passando nel suo oggetto ChatService ogni funzione. Indipendentemente dal fatto che il modulo sia destinato a fare qualcosa (eseguire un bot, aggiungere una funzione di filtro, ecc.)
Framework del modulo di esempio
local function Run(ChatService)
-- Il codice va qui
end
return Run
Aggiungere canali
Una delle cose più semplici che un ChatModule può fare è gestire canali . Gli oggetti dei canali possono essere creati con il metodo AddChannel() di 2> ChatService2> . Nota che l'oggetto dei canaleha solo bisogno di essere utilizzato quando si r
local function Run(ChatService)
local myChannel = ChatService:AddChannel("MyChannel")
end
return Run
Configurazione del canale di base
I canali hanno diverse proprietà che possono essere utilizzate per modificarli leggermente. Ad esempio, questo modulo crea un canale e imposta il messaggio di benvenuto e fa in modo che gli utenti si uniscano automaticamente al canale quando entrano nell'esperienza.
local function Run(ChatService)
local myChannel = ChatService:AddChannel("MyChannel")
-- Imposta il messaggio che viene mostrato quando un utente si unisce al canale
myChannel.WelcomeMessage = "Welcome to my channel!"
-- Causa ai giocatori di entrare automaticamente nel canale quando entrano nel Gioco
myChannel.AutoJoin = true
end
return Run
Eventi del canale
I canali hanno più eventi che possono essere sottoscritti. Questi eventi vengono attivati quando un ChatMessage viene pubblicato sul canale, quando un ChatSpeaker si lascia o si unisce, o quando uno Speaker è disattivato o non disattivato. Ad esempio, questo modulo creerà un canale con il nome MyChannel . Quando uno
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
Funzioni di Comando
Un'altra cosa potente che ChatModule può fare sono i comandi di chat . Quando un messaggio viene inviato al Server, il chat invierà il
Le funzioni di comando sono spesso utilizzate per implementare Commandi di amministratore, che sono comandi di testo che alcuni utenti possono utilizzare per manipolare lo stato dell'esperienza attraverso un testo specifico detto nella chat.
In questo esempio un ChatModule viene utilizzato per creare un Part se un utente digita /part nella chat. Nota che questa funzione restituisce vero se viene creata una parte che interrompe il messaggio e non viene visualizzato nessun messaggio. Se una parte non viene creata, questa funzione deve restituire false in modo che il messaggio possa continuare a funzionare attraverso il 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
Entrambi ChatChannels e ChatService possono avere comandi di chat. Il processore di comando ChatService viene eseguito su ogni messaggio inviato al Server, mentre i comandi del canale vengono eseguiti solo se il messaggio viene inviato al canale a cui il comando è registrato.
Funzioni di filtro
I messaggi che non sono bloccati da una funzione di comando andranno attraverso tutte le funzioni di filtro che sono registrate al ChatService e ai canali rilevanti. Ogni funzione di filtro è passata al oggetto del messaggio e al nome del canale. Tutte le modifiche apportate all'oggetto del messaggio persistono e ogni funzione di filtro successiva vedrà il Messaggioaggiornato. Nota che le funz
In questo esempio, una semplice funzione di filtro è registrata per far apparire ogni messaggio in maiuscolo minuscolo.
local function Run(ChatService)
local function makeLowercase(sender, messageObject, channelName)
messageObject.Message = string.lower(messageObject.Message)
end
ChatService:RegisterFilterMessageFunction("makeLowercase", makeLowercase)
end
return Run
Moduli del client
I moduli inseriti in ClientChatModule possono essere utilizzati per creare comportamenti personalizzati per i client. Questi moduli sono divisi in due cartelle diverse: Moduli di Comando e Moduli di Creatore di Messaggi.
Moduli di Comando
I moduli di comando lavorano molto simile ai moduli sul server che registra funzioni di comando . Questi moduli definiscono funzioni che si attivano dopo che l'utente ha inserito in testo. Questo testo può essere letto e il comando può o lasciare il messaggio attra
In entrambi i tipi di comandi, il modulo deve restituire un dizionario che dice quale tipo di elaboratore deve utilizzare il comando e quale funzione eseguire quando l' elaboratore viene chiamato. Ad esempio, un elaboratore di messaggi completato dovrebbe prendere 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 che l'KEY_COMMAND_PROCESSOR_TYPE枚umerazione è definita nell'UtilModuleScript all'interno della cartella 1>CommandModuleScript1> .
Comandi completati
I comandi del messaggio completati vengono eseguiti quando l'utente ha finito di digitare e ha raggiunto Inserisci . La funzione del processore viene passata all'oggetto ChatMessage del Servere alla tabella 0> ChatSettings0>. Se la funzione restituisce vero, all
Ad esempio, il seguente processore rimuoverà il messaggio più vecchio nel canale corrente se l'utente inserisce il 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
}
Comandi in corso
Comandi in corso di esecuzione vengono valutati ogni volta che un utente digita un personaggio nell'input di chat. Ad esempio, il seguente codice riproduce un clack dopo ogni keypress per farlo suonare come se l'utente stesse digitando su 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
}
I comandi in corso di esecuzione sono spesso utilizzati per creare uno stato personalizzato per il chat per inviare messaggi a utenti specifici invece che al canale corrente. Ad esempio, i sistemi Whisper e Team Chat controllano se l'utente ha digitato /whisper o /whisper rispettivamente e inviano il messaggio finito ai solo utenti appropriati.
Lo stato personalizzato è previsto di essere tabella con le seguenti funzioni:
- TextUpdated() — Chiamato quando il testo nella casella di input cambia.
- GetMessage() — Chiamato dopo che l'utente ha finito di inserire il messaggio e ha raggiunto Inserisci . Questa funzione è prevista per restituire una Stringa.
- ProcessCompletedMessage() — Chiamato come il messaggio viene elaborato. Un elaboratore di stato personalizzato verrà sempre attivato prima che i processori completati. Come altri elaboratori, questa funzione dovrebbe restituire vero se il messaggio non deve essere inviato, altrimenti dovrebbe restituire falso.
- Destroy() — Chiamato dopo che il messaggio è stato inviato. Dovrebbe essere utilizzato per pulire qualsiasi cosa impostata dallo stato personalizzato.
Per utilizzare uno stato personalizzato, la funzione ProcessMessage() del modulo di comando deve restituire lo stato. Un stato personalizzato di base prenderà la seguente 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
}
Uno degli aspetti positivi dell'utilizzo di uno stato personalizzato è che un modulo può modificare la barra di chat e il suo contenuto di testo mentre l'utente sta digitando sia in termini di funzione che di aspetto, e poi può facilmente ripristinarlo dopo (una volta inviato un Messaggio, lo stato personalizzato viene automaticamente rimosso e tutto viene ripristinato). Ad
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
}
Come menzionato prima, una volta inviato un messaggio qualsiasi stato personalizzato viene rimosso e la chat viene ripristinata alla normalità. Se è necessario per reimpostare uno stato personalizzato prima di inviare il Messaggio, lo stato può essere reimpostato con ChatBar:ResetCustomState() . Nota che questo rimuoverà anche il focus dalla casella di testo della barra di chat.
Moduli di Creatore di Messaggi
Un altro tipo di modulo che può essere utilizzato nel client component è un Message Creator modulo. Questo tipo di modulo viene utilizzato per creare gli elementi GUI nella finestra di chat per visualizzare il Messaggio. Ogni tipo di creatore di messaggi definisce un nuovo inserisci / scrividi messaggio, in modo che differenti tipi di creatori di messaggi possano essere creati con diversi formattazione. Inoltre, gli elementi GUI possono essere aggiunti alla visualizzazione dei messaggi in questo modo che consente
Questi moduli richiedono l'impostazione in più di un luogo. Per ciascun inserisci / scrividi messaggio, deve essere presente un ModuleScript all'interno di MessageCreatorModuleScript . Inoltre, il Class.ModuleScript deve essere modificato per includere il nuovo inserisci / scrividi inserisci / scrivifornito. Infine, i moduli vengono utilizzati solo se un component di chat del server crea
L'esempio seguente mostrerà come creare un bot che dice l'ora ogni 5 secondi e il messaggio che viene inviato ottiene un sfondo rosso.
Per Iniziare, cominciare, il ChatConstraints ModuleScript deve aggiungere un campo per il nuovo tipo di Messaggio.
-- Costanti di chatlocal module = {}--- [[ Tipi di messaggio ]]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
Il bot stesso viene creato in un nuovo ChatModule sul Server. Nota che una funzione di filtro viene utilizzata per aggiungere il nuovo tipo di messaggio ai messaggi che il bot invia.
-- Nuovo ModuleScript da posizionare in 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
Infine, un modulo di creazione del messaggio deve essere fatto. Questo modulo deve restituire un dizionario con due elementi: il tipo del Messaggio, con KEY_MESSAGE_TYPE , e la funzione da chiamare quando si crea il messaggio GUI elementi, con KEY_CREATOR_FUNCTION .
La funzione memorizzata da KEY_CREATOR_FUNCTION deve restituire un dizionario con più componenti. In primo luogo, deve includere una funzione Frame e Class
-- nuovo ModuleScript da includere in 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 gli oggetti GUI per il Frame e TextLabel per contenere il Messaggio
local BaseFrame, BaseMessage = util:CreateBaseMessage("", ChatSettings.DefaultFont, ChatSettings.ChatWindowTextSize, ChatSettings.DefaultMessageColor)
-- Cambia il background della Frame per rosso
BaseFrame.BackgroundColor3 = Color3.new(1,0,0)
BaseFrame.BackgroundTransparency = 0
-- Maneggia il testo del messaggio di aggiornamento
local function UpdateTextFunction(messageObject)
if messageObject.IsFiltered then
BaseMessage.Text = messageObject.Message
end
end
UpdateTextFunction(messageData)
-- Usa la funzione util per determinare l'altezza della finestra
local function GetHeightFunction(xSize)
return util:GetMessageHeight(BaseMessage, BaseFrame, xSize)
end
-- Crea funzioni di fusione che vengono chiamate quando la finestra di chat scompare
local FadeParameters = {}
FadeParameters[BaseMessage] = {
TextTransparency = {FadedIn = 0, FadedOut = 1},
TextStrokeTransparency = {FadedIn = 0.75, FadedOut = 1}
}
local FadeInFunction, FadeOutFunction, UpdateAnimFunction = util:CreateFadeFunctions(FadeParameters)
-- Restituisci la dizione che definisce il Etichetta
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
}