Flectone LogoFlectonePulse

Отправка сообщений

MessageDispatcher и EventMetadata, отправка сообщений через конвейер FlectonePulse с фильтрами, дистанцией, звуком и назначением

Отправить сообщение можно двумя способами

СпособКогда подходит
MessageSenderНужно просто отдать готовый Component одному игроку или в консоль
MessageDispatcherНужен весь конвейер с локализацией, форматированием, фильтрами, дистанцией, звуком, прокси и интеграциями

MessageSender

Пакет net.flectone.pulse.platform.sender
import net.flectone.pulse.platform.sender.MessageSender;
import net.kyori.adventure.text.Component;

MessageSender messageSender = flectonePulse.get(MessageSender.class);

messageSender.sendMessage(fPlayer, Component.text("Привет"), false);
messageSender.sendToConsole(Component.text("Сообщение в консоль"));
messageSender.sendToConsole("Строку тоже можно");
МетодЧто делает
sendMessage(FPlayer, Component, boolean silent)Отправляет сообщение игроку или консоли
sendToConsole(Component)Отправляет компонент в консоль
sendToConsole(String)Отправляет строку в консоль

Параметр silent отправляет пакет тихо, без сопутствующих эффектов клиента


MessageDispatcher

Пакет net.flectone.pulse.dispatcher

Собирает сообщение, считает получателей, форматирует текст лично для каждого и отправляет

import net.flectone.pulse.dispatcher.MessageDispatcher;

MessageDispatcher messageDispatcher = flectonePulse.get(MessageDispatcher.class);
МетодЧто делает
dispatch(ModuleLocalization, EventMetadata)Отправляет от имени модуля и берёт локализацию из него
dispatch(ModuleName, EventMetadata)Отправляет по имени модуля
dispatch(ModuleName, EventMetadata, Set<FPlayer>)Отправляет заранее посчитанному списку получателей
dispatch(MessageSendEvent)Отправляет уже собранное событие
createReceivers(ModuleName, EventMetadata)Считает получателей и ничего не отправляет
createMessageEvent(FPlayer, ModuleName, EventMetadata)Собирает событие для одного получателя

Все методы возвращают набор игроков, до которых сообщение дошло


EventMetadata

Описывает, как доставить сообщение. Кому, куда на экране, на какое расстояние, с каким звуком и надо ли дублировать его в Discord или на другие серверы

import net.flectone.pulse.constant.ModuleName;
import net.flectone.pulse.model.event.EventMetadata;
import net.flectone.pulse.model.event.message.context.MessageContext;
import net.flectone.pulse.model.value.Destination;
import net.flectone.pulse.model.value.Range;

messageDispatcher.dispatch(ModuleName.ADDON, EventMetadata.builder()
        .range(Range.Type.SERVER)
        .destination(Destination.EMPTY_CHAT)
        .filter(receiver -> receiver.isOnline())
        .messageContext(receiver -> MessageContext.builder()
                .sender(fPlayer)
                .receiver(receiver)
                .message("<display_name> <white>привет всем")
                .build()
        )
        .build()
);
Внимание

Без вызова messageContext(...) метод build() бросит NullPointerException. Это единственное обязательное поле

Методы билдера

МетодЧто задаёт
messageContext(Function<FPlayer, MessageContext>)Строит контекст сообщения для каждого получателя, обязателен
filter(FPlayer)Отправку только одному игроку
filter(Collection<FPlayer>)Отправку перечисленным игрокам
filter(Predicate<FPlayer>)Произвольное условие
destination(Destination)Место на экране
range(Range)Дистанцию распространения
sound(Pair<Sound, PermissionSetting>)Звук и право на его прослушивание
proxy()Отправку на другие серверы
proxy(ProxyDataConsumer<DataOutputStream>)Отправку на другие серверы вместе с данными
integration()Дублирование в Discord, Telegram и Twitch
Информация

Каждый вызов filter() сужает аудиторию, условия складываются через and и не заменяют друг друга

Контекст для каждого получателя

Параметр метода messageContext это функция от получателя. Она вызывается отдельно для каждого игрока, поэтому текст можно подобрать под язык и настройки конкретного человека

.messageContext(receiver -> MessageContext.builder()
        .sender(fPlayer)
        .receiver(receiver)
        .message(localization(receiver).format()) // свой перевод каждому
        .build()
)

Destination

Пакет net.flectone.pulse.model.value

Определяет, куда именно клиенту придёт сообщение

Destination.TypeГде рисуется
CHATОбычный чат
ACTION_BARСтрока над хотбаром
BOSS_BARПолоса босса
TITLEЗаголовок по центру экрана
SUBTITLEПодзаголовок по центру экрана
TAB_HEADERВерх списка игроков
TAB_FOOTERНиз списка игроков
TOASTВсплывающее уведомление о достижении
TEXT_SCREENПлавающий текст
BRANDНазвание сервера в отладочном экране

Для назначений со значениями по умолчанию есть готовые константы, например Destination.EMPTY_CHAT, Destination.EMPTY_TITLE и Destination.EMPTY_TOAST. Если нужны свои параметры, у Destination есть поля subtext, bossBar, times, toast и textScreen, заполняются только те, что относятся к выбранному типу


Range

Определяет, кто вообще увидит сообщение

Range.TypeКто увидит
PLAYERТолько сам отправитель
BLOCKSИгроки в радиусе N блоков
WORLD_NAMEИгроки в том же мире
WORLD_TYPEИгроки в мире того же типа
SERVERВсе игроки этого сервера
PROXYВсе игроки сети прокси
// именованная область
Range serverRange = Range.get(Range.Type.SERVER);

// радиус в блоках
Range blocksRange = Range.get(100);

Звук

Звук идёт парой вместе с правом, и игрок услышит его, только если это право у него есть

import net.flectone.pulse.model.value.Pair;
import net.flectone.pulse.model.value.Sound;

// у модулей звук берётся из конфигурации
.sound(module.soundOrThrow())

Отдельно звук проигрывает SoundPlayer

import net.flectone.pulse.platform.sender.SoundPlayer;

SoundPlayer soundPlayer = flectonePulse.get(SoundPlayer.class);
soundPlayer.play(soundPermission, sender, receiver);

Запись Sound хранит поля enable, volume, pitch, category и name


Прокси и интеграции

// продублировать сообщение на другие серверы сети
.proxy()

// то же самое, но с дополнительными данными
.proxy(output -> output.writeInt(percent))

// продублировать в Discord, Telegram и Twitch
.integration()

Про передачу данных между серверами написано на странице прокси


Пример

Объявление всем игрокам сервера, заголовком и с уходом в сеть

import net.flectone.pulse.constant.ModuleName;
import net.flectone.pulse.model.entity.FPlayer;
import net.flectone.pulse.model.event.EventMetadata;
import net.flectone.pulse.model.event.message.context.MessageContext;
import net.flectone.pulse.model.value.Destination;
import net.flectone.pulse.model.value.Range;

import java.util.Set;

public void announce(FPlayer sender, String text) {
    Set<FPlayer> received = messageDispatcher.dispatch(
            ModuleName.ADDON,
            EventMetadata.builder()
                    .range(Range.Type.SERVER)
                    .destination(Destination.EMPTY_TITLE)
                    .filter(receiver -> !receiver.isConsole())
                    .messageContext(receiver -> MessageContext.builder()
                            .sender(sender)
                            .receiver(receiver)
                            .message("<gradient:#FF0000:#00FF00>" + text + "</gradient>")
                            .build()
                    )
                    .proxy()
                    .build()
    );

    getLogger().info("Сообщение получили " + received.size() + " игроков");
}

Что происходит внутри

Метод createReceivers() считает получателей, применяет фильтры с дистанцией и смотрит, включён ли модуль для каждого игрока

Срабатывает MessagePrepareEvent, тут список получателей ещё можно поменять

Для каждого получателя собирается MessageContext и срабатывает MessageFormattingEvent

Текст проходит MessagePipeline и становится Component

Срабатывает MessageSendEvent, после чего сообщение уходит игроку

Примечание

ModuleName это перечисление, свой элемент туда добавить нельзя. Для своих сообщений бери ModuleName.ADDON или существующий модуль или отправляй через MessageSender. Как настроить сам текст, написано на странице форматирования

Последнее изменение 11 августа 2026 г.
Редактировать на GitHub

На этой странице