Flectone LogoFlectonePulse

Модули и команды

Модульная архитектура FlectonePulse, ModuleSimple и ModuleController, права доступа и регистрация своих команд

Каждая функция FlectonePulse живёт в отдельном модуле. Модули собраны в дерево, и выключение родителя выключает всё, что под ним

MODULE
├── COMMAND
│   ├── COMMAND_BAN
│   └── COMMAND_COIN
├── MESSAGE
│   ├── MESSAGE_CHAT
│   └── MESSAGE_FORMAT
│       └── MESSAGE_FORMAT_MENTION
└── INTEGRATION
    └── INTEGRATION_DISCORD
Пакет net.flectone.pulse.module
ИнтерфейсЧто добавляет
ModuleSimpleИмя, конфигурацию, право, включение и выключение
ModuleLocalizationПереводимые тексты, кулдаун и звук
ModuleCommandРегистрацию чат команды
ModuleКорневой модуль проекта

ModuleSimple

МетодВозвращаетЧто отдаёт
name()ModuleNameИдентификатор в конфигурации, правах и прокси канале
config()EnableSettingСекцию настроек модуля
permission()PermissionSettingПраво, которое управляет модулем
onEnable()voidВызывается при включении модуля
onDisable()voidВызывается при выключении модуля
isDisable()BiPredicate<FEntity, Boolean>Дополнительное условие отключения для конкретной сущности
children()Set<Class<? extends ModuleSimple>>Вложенные модули
permissions()Set<PermissionSetting>Все права, которые регистрирует модуль

ModuleLocalization

Добавляет к модулю переводы, кулдаун и звук

МетодЧто делает
localization(FPlayer)Отдаёт секцию локализации на языке конкретного игрока
cooldown()Отдаёт Optional с кулдауном и правом обхода
cooldownOrThrow()То же самое, но бросает исключение, если кулдаун не настроен
sound()Отдаёт Optional со звуком и правом на его прослушивание
soundOrThrow()То же самое, но бросает исключение, если звук не настроен
// текст на языке получателя
String format = module.localization(receiver).format();

// текст на языке по умолчанию
String defaultFormat = module.localization(FPlayer.UNKNOWN).format();

ModuleController

Пакет net.flectone.pulse.platform.controller

Управляет всем деревом модулей

import net.flectone.pulse.platform.controller.ModuleController;

ModuleController moduleController = flectonePulse.get(ModuleController.class);
МетодЧто делает
isEnable(ModuleSimple)Проверяет, включён ли модуль
isEnable(ModuleName)То же самое, но по имени модуля
isDisabledFor(ModuleSimple, FEntity)Проверяет модуль для конкретной сущности с учётом конфигурации, права и своего условия модуля
isDisabledFor(ModuleSimple, FEntity, boolean checkLocalizationModule)То же самое, но ещё проверяет локализацию
enable(ModuleSimple, Predicate<ModuleSimple>)Включает модуль
disable(ModuleSimple)Выключает модуль
containsChild(ModuleSimple, ModuleName)Ищет модуль среди потомков
collectModuleStatuses()Отдаёт состояния всех модулей
isInstanceOfAny(ModuleSimple, Set<Class<? extends ModuleSimple>>)Проверяет принадлежность модуля к одной из групп
Информация

Метод isDisabledFor() учитывает всё сразу. Включён ли модуль, есть ли у игрока право и не отключил ли модуль сам себя для этой сущности. Вызывай его перед любым действием от имени модуля

import net.flectone.pulse.module.message.chat.ChatModule;

ChatModule chatModule = flectonePulse.get(ChatModule.class);

if (moduleController.isDisabledFor(chatModule, fPlayer)) {
    return; // модуль выключен или у игрока нет права
}

Получение модуля

Модуль это обычный компонент, поэтому берётся через get()

import net.flectone.pulse.module.command.ban.BanModule;
import net.flectone.pulse.module.message.bubble.BubbleModule;

BanModule banModule = flectonePulse.get(BanModule.class);
BubbleModule bubbleModule = flectonePulse.get(BubbleModule.class);

Реакция на переключение

@Pulse(priority = Event.Priority.MONITOR, ignoreCancelled = true)
public void onModuleDisable(ModuleDisableEvent event) {
    if (event.module().name() == ModuleName.INTEGRATION_DISCORD) {
        getLogger().info("Интеграция с Discord отключена");
    }
}
Внимание

ModuleName это перечисление, и добавить туда свой элемент нельзя. Сторонние плагины не создают свои модули FlectonePulse, они цепляются к существующим через события и регистрируют свои команды напрямую


Права

Пакет net.flectone.pulse.platform.registry

PermissionRegistry регистрирует права в платформе, чтобы плагины прав видели их в автодополнении и применяли значения по умолчанию

import net.flectone.pulse.config.Permission;
import net.flectone.pulse.platform.registry.PermissionRegistry;

PermissionRegistry permissionRegistry = flectonePulse.get(PermissionRegistry.class);

permissionRegistry.register("myplugin.command.use", Permission.Type.TRUE);
Permission.TypeКому выдаётся
TRUEВсем
FALSEНикому
OPТолько операторам
NOT_OPВсем, кроме операторов

Проверяет права PermissionChecker, он работает и с игроками, и с консолью, и с сущностями из интеграций

import net.flectone.pulse.checker.PermissionChecker;

PermissionChecker permissionChecker = flectonePulse.get(PermissionChecker.class);

if (permissionChecker.check(fPlayer, "myplugin.command.use")) {
    // право есть
}

Команды

FlectonePulse использует Cloud и даёт один способ регистрации команд для всех платформ. Отправителем команды выступает FPlayer

import net.flectone.pulse.model.entity.FPlayer;
import net.flectone.pulse.platform.registry.CommandRegistry;

CommandRegistry commandRegistry = flectonePulse.get(CommandRegistry.class);

commandRegistry.registerCommand(manager -> manager
        .commandBuilder("mycommand")
        .permission("myplugin.command.use")
        .handler(context -> {
            FPlayer fPlayer = context.sender();
            messageSender.sendMessage(fPlayer, Component.text("Команда выполнена"), false);
        })
);
МетодЧто делает
registerCommand(Function<CommandManager<FPlayer>, Command.Builder<FPlayer>>)Регистрирует команду
unregisterCommand(String name)Удаляет команду по имени
init()Поднимает менеджер команд, вызывается самим проектом

Аргументы

import org.incendo.cloud.parser.standard.StringParser;

commandRegistry.registerCommand(manager -> manager
        .commandBuilder("greet")
        .required("target", StringParser.stringParser())
        .handler(context -> {
            String target = context.get("target");
            FPlayer fPlayer = context.sender();
        })
);

В пакете net.flectone.pulse.parser лежат готовые парсеры, которые знают о моделях FlectonePulse. Игроки, наказания, числа и строки с особыми правилами. Бери их вместо ручного разбора аргументов

Предупреждение

Команды, как и слушатели, перерегистрируются при перезагрузке FlectonePulse. Регистрируй их в обработчике EnableEvent с типом READY, тогда они восстановятся сами


Проверки перед действием

Эти компоненты сразу и проверяют, и пишут игроку. Они отдают true, когда действие надо прервать

Пакет net.flectone.pulse.platform.sender
КомпонентМетодЧто проверяет
CooldownSendersendIfCooldown(...)Истёк ли кулдаун
MuteSendersendIfMuted(FEntity)Заглушён ли игрок
DisableSendersendIfDisabled(FEntity, FEntity, ModuleName)Выключен ли модуль для игрока
IgnoreSendersendIfIgnored(FPlayer, FPlayer)Игнорирует ли получатель отправителя
if (muteSender.sendIfMuted(fPlayer)) return;
if (cooldownSender.sendIfCooldown(fPlayer, module.cooldownOrThrow(), "mycommand")) return;

// все проверки прошли, выполняем команду

Если сообщение игроку не нужно, кулдаун можно проверить через CooldownChecker

Примечание

Перед действием от имени модуля всегда вызывай isDisabledFor(), иначе ты обойдёшь настройки администратора сервера. Полный список компонентов лежит в справочнике

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

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