Contenido generado con IA — puede contener errores.

Módulo de chat

El módulo de chat

Qué significa encender el chat integrado, los archivos que le pertenecen, el pipeline que recorre un mensaje y cómo se entrega la línea.

El módulo de chat viene apagado. Con él encendido, ExyliaChatCosmetics es el chat del servidor: canales, formatos, mensajes privados, el filtro, menciones, emojis, ítems mostrados y el anunciador. Los cosméticos entran en la línea directamente, sin pasar por un placeholder, porque el módulo construye la línea él mismo en vez de entregarle un texto al formato de otro plugin.

Encenderlo

plugins/ExyliaChatCosmetics/config.yml
chat:
  module:
    enabled: true

Mientras el módulo funciona, el chat.hook cosmético queda desinstalado. Los dos nunca pueden estar encendidos a la vez: el hook existe para pintar un mensaje que va a entregar otro plugin de chat, y el módulo pinta el cuerpo él mismo (CosmeticsProcessor) y dibuja la etiqueta y el nombre dentro del formato como {tag} y {nick}. Apaga el módulo y el hook vuelve a instalarse, con los cosméticos funcionando exactamente como antes.

Si un archivo de chat/ no se puede leer, el módulo se niega a arrancar, lo dice en la consola y el hook vuelve: una lista de palabras rota te cuesta el módulo, nunca los cosméticos.

Dos recargas, dos alcances

/cca reload relee todo y enciende o apaga el módulo según config.yml. /cca chat reload relee solo los archivos del módulo — canales, formatos, el filtro, las tablas de emojis y gramática, los anuncios — y no toca los cosméticos. También reconstruye los comandos, así que un comando apagado en chat/config.yml deja de responder sin reiniciar.

Los archivos

Todo lo que le pertenece al módulo vive en plugins/ExyliaChatCosmetics/chat/, escrito en el primer arranque con el módulo encendido.

chat/
  config.yml         los interruptores: comandos, menciones, emojis, ítems, enlaces, cross-server
  messages.yml       cada línea que envía el módulo, con su propio prefijo
  channels.yml       adónde va un mensaje
  announcements.yml  la rotación
  formats/           un archivo por formato — vienen default.yml y msg.yml
  filter/            config.yml, rules.yml, whitelist.yml, leet.yml, punishments.yml
  text/              emojis.yml, grammar.yml — las tablas que reescriben lo que se escribió

Una versión anterior dejaba siete de esos archivos sueltos en chat/. Un servidor que actualiza conserva sus ediciones: cada uno se mueve a su carpeta en el primer arranque, una sola vez, y un archivo que ya esté en el sitio nuevo se deja como está.

Estaba enAhora está en
chat/filter.ymlchat/filter/config.yml
chat/rules.ymlchat/filter/rules.yml
chat/whitelist.ymlchat/filter/whitelist.yml
chat/leet.ymlchat/filter/leet.yml
chat/punishments.ymlchat/filter/punishments.yml
chat/emojis.ymlchat/text/emojis.yml
chat/grammar.ymlchat/text/grammar.yml

Qué necesita

El módulo se monta sobre el AsyncChatEvent de Paper y su ChatRenderer, así que necesita Paper. La mitad cosmética funciona en Spigot a través del hook antiguo; el módulo no.

Folia está soportado. Cada mensaje se decide en el hilo del chat a partir de instantáneas en memoria — las reglas, los formatos y los canales se cambian enteros al recargar, nunca se editan en su sitio — y todo lo que toca a un jugador, un sonido o una ventana, salta antes al hilo de ese jugador.

Las versalitas no se aplican a una línea de chat

El small-text de ExyliaLib dibuja en versalitas cada línea que escribe el servidor: menús, mensajes, scoreboards. La línea de chat queda exenta, y no hay nada que configurar.

El mensaje, la etiqueta, el nombre, el formato que los rodea, los susurros, la copia de la consola, el social spy y las piezas de mención, emoji, comando y [item] llegan a la pantalla con las letras con las que se escribieron. Un jugador que escribe WELCOME lee WELCOME. Los menús acompañan: la línea de ejemplo bajo SE VE ASÍ, la vista previa de TU CHAT y lo que una pantalla dice que llevas puesto se leen como los va a leer el chat, y una etiqueta que alguien se escribió conserva sus letras. El lore que las rodea — que lo escribió el servidor — se queda en versalitas, y también todo lo de chat/messages.yml y el anunciador.

El motivo es una regla, no un gusto: una línea de chat no es el servidor hablando. Dibujar media línea en versalitas y media en letras normales se lee como dos voces, así que la línea entera se interpreta tal cual.

El pipeline

Un mensaje es un ChatMessage recorrido por ChatProcessors, ordenados por etapa y después por prioridad, de menor a mayor. Un procesador que cancela detiene el recorrido: nada después de una compuerta debería gastar tiempo en una línea que nadie va a leer.

EtapaProcesadorPrioridadHace
GATEGateProcessor−100chat silenciado (bypass.mute), permiso del canal, mensaje vacío
GATECooldownProcessor−50chat/filter/config.yml → cooldown (bypass.cooldown)
FILTERSimilarityProcessor−30demasiado parecido al mensaje anterior (bypass.similarity)
FILTERFloodProcessor−20demasiado largo, demasiados caracteres repetidos (bypass.flood)
FILTERCapsProcessor−10demasiadas mayúsculas: se pasa a minúsculas o se bloquea (bypass.caps)
FILTERPatternProcessor0ip, url, dominio, teléfono, unicode: enmascarado o bloqueado, puntos
FILTERRulesProcessor10rules.yml: enmascarado o bloqueado, puntos (bypass.filter)
TRANSFORMGrammarProcessor−50correcciones de grammar.yml
TRANSFORMEmojiProcessor−40los disparadores de emojis.yml se vuelven símbolos
TRANSFORMRenderProcessor−35[item], [inv], [ec] se vuelven lo que nombran
TRANSFORMCommandReplacer−30un /comando se vuelve una sugerencia clicable
TRANSFORMLinkProcessor−20una URL se vuelve clicable, para quien tenga chat.links
TRANSFORMMentionProcessor−10un nombre, con @ o sin ella, se resalta — solo se puede mencionar a quien lee el mensaje
COSMETICSCosmeticsProcessor0fuente, modificadores y color sobre los tramos de texto
FORMATInfractionProcessor−100anota los puntos, aplica los castigos
FORMATFormatProcessor0elige el formato, construye la línea
DELIVERYChatApi.events−1000lanza ChatMessageEvent
DELIVERYaviso de mención0el efecto de feedback para el mencionado — por defecto un sonido
DELIVERYCooldownProcessor.Start100arranca la espera, así solo la cobra un mensaje que salió

Un procesador que lanza una excepción se reporta como mucho una vez por minuto y se salta — salvo en GATE y FILTER, donde falla cerrado y el mensaje se cancela. Una lista de emojis rota no es motivo para perder una línea; un filtro de palabras roto sí.

Otros plugins añaden sus propios procesadores por la API. Ver API.

Cómo se entrega la línea

La entrega no es un procesador. ChatDelivery toma el evento de chat en listener-priority (HIGHEST por defecto, para que todos los demás plugins hayan hablado antes), ejecuta el pipeline y después hace dos cosas pequeñas:

  1. Recorta los viewers del evento a quienes leen el canal, menos todos los que Chats.canHear rechaza y todos los que ignoran al emisor.
  2. Pone un renderer.

Nunca cancela un mensaje que el pipeline dejó pasar y nunca envía la línea él mismo, así que el servidor la entrega exactamente como lo habría hecho — firmada, con el mismo hover y el mismo clic que ve cualquier otro plugin. Si otro plugin entregó el conjunto de viewers en modo de solo lectura, el recorte se pierde y se reporta; la línea se sigue pintando para todos.

Un formato que se lee igual para todos se dibuja una vez, en la etapa FORMAT, y se le entrega a cada viewer. Un formato per-viewer, o que nombre un placeholder %rel_…%, se dibuja por lector dentro del renderer. La consola recibe su propia línea a partir de console-format.

Un mensaje que el pipeline canceló hace que se cancele el evento, y si lo canceló el filtro de palabras se le sigue mostrando al staff con exyliachatcosmetics.chat.staff.filtered, marcado con filtered-marker. Un mensaje que falla de forma irrecuperable también se cancela y se le avisa al emisor: entregar una línea que quizá el filtro nunca leyó es peor que perderla.

Segmentos

Después del recorrido el texto no es una cadena, sino una lista de segmentos: tramos de texto escrito, que los cosméticos pintan, y componentes que ya construyó otra función — un emoji, una mención, un enlace, un ítem mostrado — que llegan al lector exactamente como se hicieron. Nada repinta el componente de otro, y el color del texto que los rodea corre por el texto que hay entre ellos.

Un mensaje que nadie transformó nunca construye la lista: se queda como una sola cadena hasta la etapa de cosméticos.

Rendimiento

  • El evento de chat es asíncrono y el pipeline entero corre sobre él, leyendo instantáneas inmutables.
  • Las expresiones regulares se compilan al cargar: una alternancia para todos los disparadores de emojis, una por palabra de regla, una para todos los disparadores de ítems mostrados.
  • Los textos de un formato son plantillas de placeholders ya compiladas, y un formato que no depende del lector se dibuja una vez por mensaje en lugar de una vez por lector.
  • Las instantáneas de ítems viven en una caché acotada que caduca. Hay un solo temporizador para el anunciador y ninguna tarea por mensaje. Sonidos, títulos y ventanas saltan al hilo del jugador.

Ver dónde termina un hover

/cca chat line [mensaje] dibuja tu propia línea de chat con el formato que te toca, te la envía y escribe en la consola esa misma línea partida en los tramos que comparten un hover y un clic.

Esa es la herramienta para la única pregunta que una captura no responde: dónde termina el hover de una pieza. Un hover que se mete en la pieza de al lado aparece aquí como un tramo donde esperabas dos.

Format 'default' for Notch:
  [Notch] hover INFORMATION, click /msg Notch
  [ ➠ ] no hover
  [hello] hover WARNING, click /report Notch offensive_language

Adónde seguir

Los comandos y permisos del módulo están completos en Comandos y Permisos; los procesadores, eventos y servicios que expone están en API.

¿Falta algo en esta página? Dínoslo en Discord