Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
FlectonePulse
https://github.com/flectone/flectonepulse
Admin
FlectonePulse is a plugin and mod for Minecraft servers that takes control of chat, messages, and
...
Tokens:
8,384
Snippets:
62
Trust Score:
5.9
Update:
1 month ago
Context
Skills
Chat
Benchmark
74.5
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# FlectonePulse FlectonePulse is a comprehensive Minecraft plugin and mod that provides complete control over chat, messages, and notifications for Minecraft servers. It supports all popular platforms including Bukkit, Spigot, Paper, Purpur, Folia, Fabric, BungeeCord, Waterfall, and Velocity on versions 1.8.8 to the latest, plus Hytale. The plugin uses Google Guice for dependency injection and performs all operations asynchronously to avoid impacting the main server thread. The project offers extensive customization capabilities including flexible text formatting with MiniMessage tags and legacy color codes, custom textures in messages without resource packs, player-specific localization based on client language, and integrations with external platforms like Discord, Telegram, and Twitch. It provides over 30 commands for various functionality including moderation (ban, mute, warn), social features (mail, ignore, tell), and fun commands (ball, dice, tictactoe). ## FlectonePulse API - Getting the Main Instance The `FlectonePulseAPI` class is the main entry point for plugin integration. It provides static access to the main `FlectonePulse` instance and enables dependency injection through Google Guice. ```java import net.flectone.pulse.FlectonePulse; import net.flectone.pulse.FlectonePulseAPI; import net.flectone.pulse.service.FPlayerService; import net.flectone.pulse.model.entity.FPlayer; // Get the FlectonePulse instance FlectonePulse flectonePulse = FlectonePulseAPI.getInstance(); // Check if the injector is ready before using if (flectonePulse.isReady()) { // Get services through dependency injection FPlayerService playerService = flectonePulse.get(FPlayerService.class); // Get a player by UUID UUID playerUuid = UUID.fromString("069a79f4-44e9-4726-a5be-fca90e38aaf5"); FPlayer fPlayer = playerService.getFPlayer(playerUuid); System.out.println("Player name: " + fPlayer.name()); System.out.println("Player online: " + fPlayer.isOnline()); } ``` ## FPlayer - Platform-Agnostic Player Model `FPlayer` is the central player representation in FlectonePulse. It provides a unified interface for player data across all supported platforms (Bukkit, Fabric, Velocity, etc.) and includes settings, colors, and ignore lists. ```java import net.flectone.pulse.model.entity.FPlayer; import net.flectone.pulse.service.FPlayerService; import net.flectone.pulse.model.FColor; // Get FPlayerService through dependency injection FPlayerService playerService = flectonePulse.get(FPlayerService.class); // Get player by different identifiers FPlayer byUuid = playerService.getFPlayer(playerUuid); FPlayer byName = playerService.getFPlayer("PlayerName"); FPlayer byId = playerService.getFPlayer(123); // database ID FPlayer console = playerService.getConsole(); // or getFPlayer(-1) // Build a new FPlayer using builder pattern FPlayer newPlayer = FPlayer.builder() .name("TestPlayer") .uuid(UUID.randomUUID()) .online(true) .build(); // Check player properties if (!byUuid.isUnknown()) { boolean isOnline = byUuid.isOnline(); boolean isConsole = byUuid.isConsole(); boolean isIntegration = byUuid.isIntegration(); // Discord/Telegram user // Check if player ignores another player boolean ignoresOther = byUuid.isIgnored(anotherPlayer); // Get player settings boolean hasChatEnabled = byUuid.isSetting(ModuleName.MESSAGE_CHAT); // Get player's custom colors Map<Integer, String> chatColors = byUuid.getFColors(FColor.Type.CHAT); } // Immutable updates with 'with' methods FPlayer updatedPlayer = byUuid .withOnline(false) .withSetting("MESSAGE_JOIN", false) .withIp("192.168.1.1"); ``` ## FPlayerService - Player Management Service The `FPlayerService` manages player storage, retrieval, and persistence across the plugin. It handles player caching, database operations, and provides methods for accessing online and offline players. ```java import net.flectone.pulse.service.FPlayerService; import net.flectone.pulse.model.entity.FPlayer; import net.flectone.pulse.module.command.ignore.model.Ignore; import net.flectone.pulse.module.command.mail.model.Mail; FPlayerService playerService = flectonePulse.get(FPlayerService.class); // Get online players List<FPlayer> onlinePlayers = playerService.getOnlineFPlayers(); List<FPlayer> platformPlayers = playerService.getPlatformFPlayers(); List<FPlayer> withConsole = playerService.getFPlayersWithConsole(); // Get all players from database List<FPlayer> allPlayers = playerService.findAllFPlayers(); // Get random online player FPlayer randomPlayer = playerService.getRandomFPlayer(); // Get visible players for a viewer (respects vanish plugins) FPlayer viewer = playerService.getFPlayer(viewerUuid); List<FPlayer> visibleToViewer = playerService.getVisibleFPlayersFor(viewer); // Get players who can see a target List<FPlayer> canSeeTarget = playerService.getFPlayersWhoCanSee(targetPlayer); // Manage ignore relationships FPlayer sender = playerService.getFPlayer(senderUuid); FPlayer target = playerService.getFPlayer(targetUuid); FPlayer updatedSender = playerService.saveIgnore(sender, target); // Retrieve ignores for a player List<Ignore> ignores = sender.ignores(); // Send mail between players Mail mail = playerService.saveMail(sender, target, "Hello, this is a mail message!"); List<Mail> receivedMails = playerService.getReceiverMails(target); List<Mail> sentMails = playerService.getSenderMails(sender); // Delete mail playerService.deleteMail(mail); // Check group hierarchy (for moderation) boolean canModerate = playerService.hasHigherGroupThan(moderator, target); // Update player locale playerService.updateLocale(player, "en_us"); ``` ## Event System - Listening to FlectonePulse Events FlectonePulse has its own event system using the `@Pulse` annotation. Events support priorities and can be cancelled. Listeners must implement `PulseListener` interface and methods must take a single Event parameter. ```java import net.flectone.pulse.listener.PulseListener; import net.flectone.pulse.annotation.Pulse; import net.flectone.pulse.model.event.Event; import net.flectone.pulse.model.event.player.PlayerJoinEvent; import net.flectone.pulse.model.event.player.PlayerQuitEvent; import net.flectone.pulse.model.event.message.MessageSendEvent; import net.flectone.pulse.model.event.lifecycle.EnableEvent; import net.flectone.pulse.model.event.lifecycle.ReloadEvent; import com.google.inject.Singleton; @Singleton public class CustomPulseListener implements PulseListener { // Listen to player join with LOWEST priority (runs first) @Pulse(priority = Event.Priority.LOWEST, ignoreCancelled = true) public PlayerJoinEvent onPlayerJoin(PlayerJoinEvent event) { FPlayer player = event.player(); System.out.println(player.name() + " joined the server!"); // Modify and return the event return event.withPlayer(player.withIp("updated-ip")); } // Listen to message send events (default NORMAL priority) @Pulse public void onMessageSend(MessageSendEvent event) { FPlayer receiver = event.receiver(); Component message = event.format(); System.out.println("Sending message to: " + receiver.name()); } // Listen to plugin enable @Pulse public void onEnable(EnableEvent event) { System.out.println("FlectonePulse enabled!"); } // Listen to reload with HIGH priority @Pulse(priority = Event.Priority.HIGH) public ReloadEvent onReload(ReloadEvent event) { System.out.println("FlectonePulse reloading..."); return event; // Return unchanged event } // Cancel an event @Pulse public Event onMessage(MessagePrepareEvent event) { if (shouldCancel(event)) { return event.withCancelled(true); } return event; } } ``` ## ListenerRegistry - Registering Custom Listeners The `ListenerRegistry` manages all Pulse event listeners. You can register permanent listeners that persist across reloads or temporary ones that are cleared on reload. ```java import net.flectone.pulse.platform.registry.ListenerRegistry; import net.flectone.pulse.listener.PulseListener; import net.flectone.pulse.model.event.Event; ListenerRegistry listenerRegistry = flectonePulse.get(ListenerRegistry.class); // Register a listener class (must implement PulseListener) listenerRegistry.register(CustomPulseListener.class); // Register with specific priority listenerRegistry.register(CustomPulseListener.class, Event.Priority.HIGH); // Register a listener instance PulseListener myListener = new CustomPulseListener(); listenerRegistry.register(myListener); // Register permanent listener (persists across reloads) listenerRegistry.registerPermanent(myListener); // Register raw event handler programmatically listenerRegistry.register( PlayerJoinEvent.class, Event.Priority.NORMAL, event -> { System.out.println("Player joined!"); return event; } ); // Unregister all listeners listenerRegistry.unregisterAll(); ``` ## EventDispatcher - Dispatching Events The `EventDispatcher` is used to fire events to all registered listeners. Events are processed through priority levels and can be modified or cancelled by handlers. ```java import net.flectone.pulse.execution.dispatcher.EventDispatcher; import net.flectone.pulse.model.event.player.PlayerJoinEvent; import net.flectone.pulse.model.event.lifecycle.ReloadEvent; EventDispatcher eventDispatcher = flectonePulse.get(EventDispatcher.class); // Dispatch an event and get the result PlayerJoinEvent joinEvent = new PlayerJoinEvent(fPlayer); PlayerJoinEvent result = eventDispatcher.dispatch(joinEvent); // Check if event was cancelled if (result.cancelled()) { System.out.println("Join event was cancelled by a listener"); } // Dispatch with custom listener map Map<Event.Priority, List<UnaryOperator<Event>>> customListeners = getCustomListeners(); ReloadEvent reloadResult = eventDispatcher.dispatch(customListeners, new ReloadEvent(instance, null)); ``` ## MessageDispatcher - Sending Messages to Players The `MessageDispatcher` handles sending formatted messages to players with support for localization, range filtering, sounds, and proxy server synchronization. ```java import net.flectone.pulse.execution.dispatcher.MessageDispatcher; import net.flectone.pulse.model.event.EventMetadata; import net.flectone.pulse.model.entity.FPlayer; import net.flectone.pulse.model.util.Range; import net.flectone.pulse.model.util.Destination; MessageDispatcher messageDispatcher = flectonePulse.get(MessageDispatcher.class); // Create event metadata for a message EventMetadata<Localization.Command.Ball> metadata = EventMetadata.<Localization.Command.Ball>builder() .sender(senderPlayer) .format(loc -> loc.format()) // Get format from localization .message("Hello world!") .destination(Destination.EMPTY_CHAT) .range(Range.get(Range.Type.PLAYER)) .proxy() // Enable proxy sync .integration() // Enable external integrations .build(); // Dispatch message to all receivers messageDispatcher.dispatch(myModule, metadata); // Dispatch to specific receiver list List<FPlayer> receivers = List.of(player1, player2, player3); messageDispatcher.dispatch(receivers, myModule, metadata); // Dispatch with custom module name messageDispatcher.dispatch(ModuleName.COMMAND_BALL, receivers, myModule, metadata); // Create filtered receivers List<FPlayer> filteredReceivers = messageDispatcher.createReceivers(myModule, metadata); ``` ## EventMetadata - Building Message Context `EventMetadata` contains all the context needed for message processing including sender, format, destination, range, sounds, and integration settings. ```java import net.flectone.pulse.model.event.EventMetadata; import net.flectone.pulse.model.util.Destination; import net.flectone.pulse.model.util.Range; import net.flectone.pulse.model.util.Sound; import net.flectone.pulse.util.constant.MessageFlag; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; // Build comprehensive EventMetadata EventMetadata<MyLocalization> metadata = EventMetadata.<MyLocalization>builder() // Required: sender entity .sender(fPlayer) // Required: format function (from localization) .format(loc -> loc.messageFormat()) // Or static format .format("<green><player> says: <message>") // Or player-specific format .format((player, loc) -> player.isConsole() ? loc.consoleFormat() : loc.playerFormat()) // Required: range type .range(Range.get(Range.Type.PLAYER)) // To sender only .range(Range.get(Range.Type.LOCAL)) // Nearby players .range(Range.get(Range.Type.GLOBAL)) // All players .range(Range.get(Range.Type.WORLD)) // Same world // Optional: player message content .message("User's message here") // Optional: destination (chat, action bar, etc.) .destination(Destination.EMPTY_CHAT) // Optional: filter players .filter(player -> !player.isIgnored(sender)) .filterPlayer(senderPlayer, true) // Set color context // Optional: message flags .flag(MessageFlag.PLAYER_MESSAGE, true) .flag(MessageFlag.COLOR_CONTEXT_SENDER, true) // Optional: sound to play .sound(Pair.of(sound, permissionSetting)) // Optional: custom tag resolvers .tagResolvers(player -> new TagResolver[] { Placeholder.parsed("custom", "value") }) // Optional: proxy sync for multi-server .proxy(dataOutputStream -> { dataOutputStream.writeString(customData); dataOutputStream.writeInt(someValue); }) // Optional: integration formatting (Discord/Telegram/Twitch) .integration(rawString -> rawString.replace("<tag>", "value")) // Build the metadata .build(); ``` ## Creating Custom Modules FlectonePulse uses a modular architecture. Modules implement `ModuleSimple` or `ModuleCommand` interfaces and are managed by the `ModuleController`. ```java import net.flectone.pulse.module.ModuleSimple; import net.flectone.pulse.module.ModuleCommand; import net.flectone.pulse.config.setting.EnableSetting; import net.flectone.pulse.config.setting.PermissionSetting; import net.flectone.pulse.util.constant.ModuleName; import com.google.inject.Singleton; import com.google.inject.Inject; @Singleton public class CustomModule implements ModuleSimple { private final FileFacade fileFacade; @Inject public CustomModule(FileFacade fileFacade) { this.fileFacade = fileFacade; } @Override public void onEnable() { // Called when module is enabled System.out.println("Custom module enabled!"); } @Override public void onDisable() { // Called when module is disabled System.out.println("Custom module disabled!"); } @Override public ModuleName name() { return ModuleName.CUSTOM_MODULE; } @Override public EnableSetting config() { return fileFacade.config().module(); } @Override public PermissionSetting permission() { return fileFacade.permission().module(); } } // Command module example (with /ball command pattern) @Singleton public class MyCommandModule implements ModuleCommand<Localization.Command.MyCommand> { private final FileFacade fileFacade; private final MessageDispatcher messageDispatcher; private final ModuleCommandController commandController; private final CommandParserProvider commandParserProvider; @Inject public MyCommandModule(FileFacade fileFacade, MessageDispatcher messageDispatcher, ModuleCommandController commandController, CommandParserProvider commandParserProvider) { this.fileFacade = fileFacade; this.messageDispatcher = messageDispatcher; this.commandController = commandController; this.commandParserProvider = commandParserProvider; } @Override public void onEnable() { // Register command with arguments String messagePrompt = commandController.addPrompt(this, 0, Localization.Command.Prompt::message); commandController.registerCommand(this, builder -> builder .permission(permission().name()) .required(messagePrompt, commandParserProvider.nativeMessageParser()) ); } @Override public void execute(FPlayer player, CommandContext<FPlayer> context) { String message = commandController.getArgument(this, context, 0); messageDispatcher.dispatch(this, EventMetadata.<Localization.Command.MyCommand>builder() .sender(player) .format(loc -> loc.format()) .message(message) .destination(config().destination()) .range(config().range()) .build() ); } @Override public ModuleName name() { return ModuleName.COMMAND_MYCOMMAND; } // ... config, permission, localization methods } ``` ## Integration Modules - Discord, Telegram, Twitch FlectonePulse provides integration modules for external platforms. These modules can be used to sync messages between the game server and external chat platforms. ```java import net.flectone.pulse.module.integration.discord.DiscordModule; import net.flectone.pulse.module.integration.telegram.TelegramModule; import net.flectone.pulse.model.entity.FEntity; // Get integration modules DiscordModule discordModule = flectonePulse.get(DiscordModule.class); TelegramModule telegramModule = flectonePulse.get(TelegramModule.class); // Send message to Discord discordModule.sendMessage( sender, "chat_message", rawString -> rawString.replace("<player>", sender.name()) ); // Send message to Telegram telegramModule.sendMessage( sender, "join_message", rawString -> rawString .replace("<player>", sender.name()) .replace("<server>", "MyServer") ); ``` ## Configuration - YAML Config Structure FlectonePulse uses YAML configuration files. The main config.yml contains database settings, proxy configuration, module toggles, and cache settings. ```yaml # config.yml example version: "1.8.2-SNAPSHOT" language: type: "en_us" by_player: true # Detect player's client language database: ignore_existing_driver: false use_playtime_tracking: true type: "H2" # H2, SQLITE, MYSQL, MARIADB, POSTGRESQL name: "flectonepulse" host: "127.0.0.1" port: "3306" user: "root" password: "1234" parameters: "?autoReconnect=true&useSSL=false" prefix: "" proxy: clusters: [] bungeecord: false velocity: false redis: enable: false host: "127.0.0.1" port: 6379 ssl: false user: "" password: "" module: enable: true use_paper_message_sender: false cache: types: COOLDOWN: invalidate_on_reload: false duration: 5 time_unit: "HOURS" size: 5000 OFFLINE_PLAYERS: duration: 1 time_unit: "HOURS" size: 1000 metrics: enable: true ``` ## Localization - Message Formatting Localization files support MiniMessage formatting, custom placeholders, hover text, click actions, and color gradients. ```yaml # en_us.yml localization example cooldown: "<color:#ff7171><sprite_or:!:gui:icon/chat_modified>Too fast, wait <time>" command: ball: format: "<color:#9370DB>! <display_name> asked: <message><br><color:#9370DB>Ball answered: <u><answer></u>" answers: - "Undeniably" - "No doubt about it" - "Definitely yes" - "Most likely" - "Ask later" - "Very doubtful" ban: server: "<color:#ff7171>! <moderator> banned <display_name> <hover:show_text:\"<fcolor:1>ID: <id><br>Reason: <reason>\">[INFO]</hover>" person: "<color:#ff7171>! BAN !<br><br>Time: <time><br>Reason: <reason>" broadcast: format: "<color:#ffd500>| Message for everyone<br>| Author: <display_name><br>| <fcolor:1><message>" message: join: format: "<color:#98FB98>+ <display_name> joined" quit: format: "<color:#ff7171>- <display_name> left" chat: local: format: "<fcolor:2><display_name><fcolor:3>: <message>" global: format: "<fcolor:2><display_name><fcolor:4>: <message>" ``` ## Text Formatting - MiniMessage Support FlectonePulse supports comprehensive text formatting through MiniMessage tags and legacy color codes. ```yaml # Supported formatting examples examples: # Legacy color codes legacy_colors: "&aGreen &cRed &6Gold" legacy_styles: "&lBold &oItalic &nUnderline &mStrikethrough" # MiniMessage tags colors: "<red>Red <green>Green <blue>Blue" hex_colors: "<#FF5733>Custom Hex Color" gradients: "<gradient:#FF0000:#00FF00>Rainbow Text</gradient>" rainbow: "<rainbow>Rainbow colors!</rainbow>" # Styles bold: "<bold>Bold text</bold>" italic: "<italic>Italic text</italic>" underline: "<underlined>Underlined</underlined>" # Interactive elements hover: "<hover:show_text:'Hover text here'>Hover over me</hover>" click_url: "<click:open_url:'https://example.com'>Click me</click>" click_command: "<click:run_command:'/help'>Run /help</click>" click_suggest: "<click:suggest_command:'/msg '>Suggest command</click>" # Placeholders player_name: "<display_name>" player_head: "<player_head>" custom_texture: "<texture:my_image>" sprite: "<sprite:diamond>" # FlectonePulse custom tags fcolors: "<fcolor:1>Color 1 <fcolor:2>Color 2 <fcolor:3>Color 3" message_tag: "<message>" # Replaced with player's message ``` ## Summary FlectonePulse provides a comprehensive solution for Minecraft server chat customization and management. Its main use cases include: customizing all server messages (join, quit, death, advancement, chat), integrating with external platforms (Discord, Telegram, Twitch), providing moderation commands (ban, mute, warn, kick), implementing fun commands (ball, dice, tictactoe, rockpaperscissors), and creating localized player experiences based on client language. The plugin also supports multi-server setups through BungeeCord, Velocity, and Redis synchronization. For developers, FlectonePulse offers a powerful API built on Google Guice dependency injection. Integration patterns include: getting the `FlectonePulseAPI` instance and using `get()` to access services, working with `FPlayer` objects for player management, registering custom event listeners with the `@Pulse` annotation and `ListenerRegistry`, dispatching messages through `MessageDispatcher` with `EventMetadata`, and creating custom modules implementing `ModuleSimple` or `ModuleCommand`. The event system supports priorities (LOWEST to MONITOR), cancellation, and immutable event modification through `with` methods.