From 6fa27144fc961d6e6952b27c0c1403dbbf399c59 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sat, 10 Jan 2026 19:43:32 +0100 Subject: [PATCH 1/7] Add `multification-paper` module with Paper platform support and examples. --- README.md | 150 ++++++++++++++---- .../multification-repositories.gradle.kts | 2 +- examples/paper/build.gradle.kts | 60 +++++++ .../example/paper/ExamplePaperPlugin.java | 47 ++++++ .../example/paper/command/FlyCommand.java | 56 +++++++ .../example/paper/command/GiveCommand.java | 52 ++++++ .../example/paper/command/ReloadCommand.java | 39 +++++ .../paper/command/TeleportCommand.java | 31 ++++ .../paper/command/timer/TimerCommand.java | 22 +++ .../paper/command/timer/TimerManager.java | 37 +++++ .../paper/config/ConfigurationManager.java | 42 +++++ .../example/paper/config/MessagesConfig.java | 45 ++++++ .../multification/ExampleMultification.java | 37 +++++ multification-paper/build.gradle.kts | 17 ++ .../paper/PaperLocaleProvider.java | 20 +++ .../paper/PaperMultification.java | 36 +++++ .../paper/PaperViewerProvider.java | 60 +++++++ settings.gradle.kts | 3 +- 18 files changed, 726 insertions(+), 30 deletions(-) create mode 100644 examples/paper/build.gradle.kts create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/ExamplePaperPlugin.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/command/FlyCommand.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/command/GiveCommand.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/command/ReloadCommand.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/command/TeleportCommand.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerCommand.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerManager.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/config/ConfigurationManager.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java create mode 100644 examples/paper/src/main/java/com/eternalcode/example/paper/multification/ExampleMultification.java create mode 100644 multification-paper/build.gradle.kts create mode 100644 multification-paper/src/com/eternalcode/multification/paper/PaperLocaleProvider.java create mode 100644 multification-paper/src/com/eternalcode/multification/paper/PaperMultification.java create mode 100644 multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java diff --git a/README.md b/README.md index 8808aed..55a4ce4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@
- + ![Multification Banner](/assets/readme-banner.png) + ### Multification + Powerful library for sending custom notifications based on adventure. [![Patreon](https://raw.githubusercontent.com/intergrav/devins-badges/v3/assets/cozy/donate/patreon-plural_vector.svg)](https://www.patreon.com/eternalcode) @@ -15,7 +17,9 @@ Powerful library for sending custom notifications based on adventure. ## About -Multification makes it simple to create customizable notifications and messages within large plugins that require handling a high volume of messages (while the setup may not be easy, **it’s worthwhile for extensive plugins**). It offers a range of features, including: +Multification makes it simple to create customizable notifications and messages within large plugins that require +handling a high volume of messages (while the setup may not be easy, **it’s worthwhile for extensive plugins**). It +offers a range of features, including: - πŸ’­ Chat messages - πŸ“• Title & Subtitle @@ -28,23 +32,55 @@ Multification makes it simple to create customizable notifications and messages - πŸ› οΈ Formatter support - 🌎 Flexible messages providing (easy to implement i18n) - πŸ“¦ Configuration support (CDN, Okaeri Configs) -- Cross-platform support (currently we support Bukkit, but it's easy to add support for other adventure-based platforms) +- πŸš€ Cross-platform support (Bukkit, Paper) Messages can be sent to any audience, such as players or the console. +## Supported Platforms + +| Platform | Module | Java Version | Adventure API | Status | +|-------------------|------------------------|--------------|-----------------------|------------------------| +| **Paper** | `multification-paper` | Java 21 | Native (built-in) | βœ… Recommended | +| **Bukkit/Spigot** | `multification-bukkit` | Java 8+ | External adapter | βœ… Supported | +| **Velocity** | `multification-bukkit` | Java 21+ | Native | ❌ Soon | +| **Core** | `multification-core` | Java 8+ | Custom implementation | βœ… For custom platforms | + +> **πŸ’‘ Recommendation:** Use `multification-paper` for Paper servers (1.19.4+) to leverage native Adventure API without +> external dependencies. + ## Getting Started -To use the library, you need to add the following repository and dependency to your `build.gradle` file: +### For Paper Servers (Recommended) + +Add the following repository and dependency to your `build.gradle.kts`: ```kts -maven("https://repo.eternalcode.pl/releases") +repositories { + maven("https://repo.eternalcode.pl/releases") + maven("https://repo.papermc.io/repository/maven-public/") +} + +dependencies { + implementation("com.eternalcode:multification-paper:1.2.3") +} ``` +### For Bukkit/Spigot Servers + ```kts -implementation("com.eternalcode:multification-bukkit:1.2.2") +repositories { + maven("https://repo.eternalcode.pl/releases") +} + +dependencies { + implementation("com.eternalcode:multification-bukkit:1.2.3") +} ``` -> **Note:** If you want to use the library with other platforms, then you need to use the `multification-core` dependency. +> **Note:** For custom platforms or other Adventure-based servers, use `multification-core` and implement your own +> platform adapter. + +## Quick Example Then create a new instance of the `Multification` class and use it to send notifications: @@ -55,7 +91,10 @@ public class YourMultification extends BukkitMultification { private final AudienceProvider audienceProvider; private final MiniMessage miniMessage; - public YourMultification(MessagesConfig messagesConfig, AudienceProvider audienceProvider, MiniMessage miniMessage) { + public YourMultification( + MessagesConfig messagesConfig, + AudienceProvider audienceProvider, + MiniMessage miniMessage) { this.messagesConfig = messagesConfig; this.audienceProvider = audienceProvider; this.miniMessage = miniMessage; @@ -73,7 +112,7 @@ public class YourMultification extends BukkitMultification { @Override protected @NotNull AudienceConverter audienceConverter() { - return commandSender -> { + return commandSender -> { if (commandSender instanceof Player player) { return this.audienceProvider.player(player.getUniqueId()); } @@ -81,7 +120,6 @@ public class YourMultification extends BukkitMultification { return this.audienceProvider.console(); }; } - } ``` @@ -100,28 +138,38 @@ After that, you can use the `multification` instance to send notifications: ```java multification.create() - .player(player.getUniqueId()) - .notice(messages -> messages.yourMessage) - .send(); + . + +player(player.getUniqueId()) + . + +notice(messages ->messages.yourMessage) + . + +send(); ``` ## Configuration Support Multification currently supports two configuration libraries: + - [CDN](https://github.com/dzikoysk/cdn) _Simple and fast property-based configuration library for JVM apps_ -- [Okaeri Configs](https://github.com/OkaeriPoland/okaeri-configs) _Simple Java/POJO config library written with love and Lombok_ +- [Okaeri Configs](https://github.com/OkaeriPoland/okaeri-configs) _Simple Java/POJO config library written with love + and Lombok_ To use the Multification library with one of the configuration libraries, you need to: ### [CDN](https://github.com/dzikoysk/cdn) #### (CDN) 1. Add dependency to your `build.gradle` file: + ```gradle implementation("com.eternalcode:multification-cdn:1.1.4") implementation("net.dzikoysk:cdn:1.14.5") ``` #### (CDN) 2. Create configuration class: + ```java public class MessagesConfig { @Description("# My first message") @@ -130,11 +178,12 @@ public class MessagesConfig { ``` #### (CDN) 3. Create a new instance of the `Cdn` with the `MultificationNoticeCdnComposer`: + ```java Cdn cdn = CdnFactory.createYamlLike() - .getSettings() - .withComposer(Notice.class, new MultificationNoticeCdnComposer(multification.getNoticeRegistry())) - .build(); + .getSettings() + .withComposer(Notice.class, new MultificationNoticeCdnComposer(multification.getNoticeRegistry())) + .build(); ``` #### (CDN) 4. Load the configuration: @@ -145,14 +194,23 @@ To load and create the config file, use the following code in the init method su MessagesConfig messages = new MessagesConfig(); Resource resource = Source.of(this.dataFolder, "messages.yml"); -cdn.load(resource, messages) - .orThrow(cause -> cause); +cdn. + +load(resource, messages) + . + +orThrow(cause ->cause); -cdn.render(config, resource) - .orThrow(cause -> cause); + cdn. + +render(config, resource) + . + +orThrow(cause ->cause); ``` -Checkout example with CDN! [example plugin](https://github.com/EternalCodeTeam/multification/tree/master/examples/bukkit). +Checkout example with +CDN! [example plugin](https://github.com/EternalCodeTeam/multification/tree/master/examples/bukkit). ### [Okaeri Configs](https://github.com/OkaeriPoland/okaeri-configs) @@ -163,11 +221,13 @@ implementation("com.eternalcode:multification-okaeri:1.1.4") ``` Probably also you will need to add additional dependencies for your platform, e.g. : + ```gradle implementation("eu.okaeri:okaeri-configs-serdes-commons:5.0.5") implementation("eu.okaeri:okaeri-configs-serdes-bukkit:5.0.5") implementation("eu.okaeri:okaeri-configs-yaml-bukkit:5.0.5") ``` + See [Okaeri Configs](https://github.com/OkaeriPoland/okaeri-configs) for more information. #### (Okaeri) 2. Create configuration class: @@ -183,11 +243,45 @@ public class MessagesConfig extends OkaeriConfig { ```java MessagesConfig config = (MessagesConfig) ConfigManager.create(MessagesConfig.class) - .withConfigurer(new MultificationSerdesPack(multification.getNoticeRegistry())) - .withConfigurer(new SerdesCommons(), new YamlBukkitConfigurer(), new SerdesBukkit()) // specify configurers for your platform - .withBindFile(new File(dataFolder, "messages.yml")) - .withRemoveOrphans(true) // automatic removal of undeclared keys - .saveDefaults() // save file if does not exists - .load(true); + .withConfigurer(new MultificationSerdesPack(multification.getNoticeRegistry())) + .withConfigurer( + new SerdesCommons(), + new YamlBukkitConfigurer(), + new SerdesBukkit()) // specify configurers for your platform + .withBindFile(new File(dataFolder, "messages.yml")) + .withRemoveOrphans(true) // automatic removal of undeclared keys + .saveDefaults() // save file if does not exists + .load(true); ``` +## πŸ“š Documentation + +For complete documentation, guides, and examples, visit our [documentation](/docs): + +- **[Getting Started](/docs/installation)** - Installation and setup +- **[Basic Usage](/docs/basic-usage)** - Learn the fundamentals +- **[Configuration](/docs/configuration)** - CDN & Okaeri integration +- **[Advanced Features](/docs/advanced)** - i18n, custom formatters, platform adapters +- **[Platform Comparison](/docs/platform-comparison)** - Paper vs Bukkit +- **[API Reference](/docs/api-reference)** - Complete API documentation +- **[Examples](/docs/examples)** - Working code examples +- **[FAQ](/docs/faq)** - Common questions and troubleshooting + +## 🀝 Contributing + +We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. + +## πŸ“„ License + +This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. + +## πŸ”— Links + +- [GitHub Repository](https://github.com/EternalCodeTeam/multification) +- [Discord Community](https://discord.gg/FQ7jmGBd6c) +- [EternalCode Website](https://eternalcode.pl/) +- [Issue Tracker](https://github.com/EternalCodeTeam/multification/issues) + +--- + +Made with ❀️ by [EternalCode Team](https://github.com/EternalCodeTeam) diff --git a/buildSrc/src/main/kotlin/multification-repositories.gradle.kts b/buildSrc/src/main/kotlin/multification-repositories.gradle.kts index 2726e38..88a0d2d 100644 --- a/buildSrc/src/main/kotlin/multification-repositories.gradle.kts +++ b/buildSrc/src/main/kotlin/multification-repositories.gradle.kts @@ -5,7 +5,7 @@ plugins { repositories { mavenCentral() - maven("https://papermc.io/repo/repository/maven-public/") // paper, adventure, velocity + maven("https://repo.papermc.io/repository/maven-public/") // paper, adventure, velocity (NOWY URL) maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // spigot maven("https://repo.panda-lang.org/releases/") // expressible maven("https://repo.stellardrift.ca/repository/snapshots/") diff --git a/examples/paper/build.gradle.kts b/examples/paper/build.gradle.kts new file mode 100644 index 0000000..56521dc --- /dev/null +++ b/examples/paper/build.gradle.kts @@ -0,0 +1,60 @@ +plugins { + id("java") + id("com.gradleup.shadow") version "9.0.0-beta4" + id("net.minecrell.plugin-yml.paper") version "0.6.0" + id("xyz.jpenilla.run-paper") version "2.3.1" +} + +version = "1.0.0-SNAPSHOT" + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +repositories { + mavenCentral() + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://repo.panda-lang.org/releases/") +} + +dependencies { + compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") + + implementation("dev.rollczi:litecommands-bukkit:3.4.1") + // implementation("com.eternalcode:multification-paper:1.2.3") // <-- uncomment in your project + // implementation("com.eternalcode:multification-cdn:1.2.3") // <-- uncomment in your project + + implementation(project(":multification-paper")) // don't use this line in your build.gradle + implementation(project(":multification-cdn")) // don't use this line in your build.gradle +} + +val pluginName = "ExamplePaperPlugin" +val packageName = "com.eternalcode.example.paper" + +paper { + main = "$packageName.$pluginName" + apiVersion = "1.21" + author = "EternalCode" + name = pluginName + version = "${project.version}" +} + +tasks.shadowJar { + archiveFileName.set("$pluginName v${project.version}.jar") + + listOf( + "dev.rollczi.litecommands", + "panda.std", + "panda.utilities", + ).forEach { relocate(it, "$packageName.libs.$it") } +} + +sourceSets.test { + java.setSrcDirs(emptyList()) + resources.setSrcDirs(emptyList()) +} + +tasks.runServer { + minecraftVersion("1.21.11") +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/ExamplePaperPlugin.java b/examples/paper/src/main/java/com/eternalcode/example/paper/ExamplePaperPlugin.java new file mode 100644 index 0000000..e061e59 --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/ExamplePaperPlugin.java @@ -0,0 +1,47 @@ +package com.eternalcode.example.paper; + +import com.eternalcode.example.paper.command.FlyCommand; +import com.eternalcode.example.paper.command.GiveCommand; +import com.eternalcode.example.paper.command.ReloadCommand; +import com.eternalcode.example.paper.command.TeleportCommand; +import com.eternalcode.example.paper.command.timer.TimerCommand; +import com.eternalcode.example.paper.command.timer.TimerManager; +import com.eternalcode.example.paper.config.ConfigurationManager; +import com.eternalcode.example.paper.config.MessagesConfig; +import com.eternalcode.example.paper.multification.ExampleMultification; +import dev.rollczi.litecommands.LiteCommands; +import dev.rollczi.litecommands.bukkit.LiteBukkitFactory; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; + +public class ExamplePaperPlugin extends JavaPlugin { + + private LiteCommands liteCommands; + + @Override + public void onEnable() { + // Config & Multification + MessagesConfig messagesConfig = new MessagesConfig(); + ExampleMultification multification = new ExampleMultification(messagesConfig); + + ConfigurationManager configurationManager = new ConfigurationManager(this.getDataFolder(), + multification.getNoticeRegistry()); + configurationManager.load(messagesConfig, "messages.yml"); + + this.liteCommands = LiteBukkitFactory.builder() + .commands( + new TeleportCommand(multification), + new FlyCommand(multification), + new GiveCommand(multification), + new ReloadCommand(configurationManager, multification), + new TimerCommand(new TimerManager(this.getServer().getScheduler(), this, multification))) + .build(); + } + + @Override + public void onDisable() { + if (this.liteCommands != null) { + this.liteCommands.unregister(); + } + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/command/FlyCommand.java b/examples/paper/src/main/java/com/eternalcode/example/paper/command/FlyCommand.java new file mode 100644 index 0000000..a7d4065 --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/command/FlyCommand.java @@ -0,0 +1,56 @@ +package com.eternalcode.example.paper.command; + +import com.eternalcode.example.paper.multification.ExampleMultification; +import dev.rollczi.litecommands.annotations.argument.Arg; +import dev.rollczi.litecommands.annotations.command.Command; +import dev.rollczi.litecommands.annotations.context.Context; +import dev.rollczi.litecommands.annotations.execute.Execute; +import dev.rollczi.litecommands.annotations.permission.Permission; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@Command(name = "fly", aliases = { "f" }) +@Permission("example.fly") +public class FlyCommand { + + private final ExampleMultification multification; + + public FlyCommand(ExampleMultification multification) { + this.multification = multification; + } + + @Execute + void execute(@Context Player sender) { + sender.setAllowFlight(!sender.getAllowFlight()); + multification.create() + .player(sender.getUniqueId()) + .notice(messages -> messages.selfFlyCommandMessage) + .placeholder("{state}", sender.getAllowFlight() ? "enabled" : "disabled") + .send(); + } + + @Execute + void executeOther(@Context CommandSender sender, @Arg Player target) { + target.setAllowFlight(!target.getAllowFlight()); + + multification.create() + .player(target.getUniqueId()) + .notice(messages -> messages.selfFlyCommandMessage) + .placeholder("{state}", target.getAllowFlight() ? "enabled" : "disabled") + .send(); + + multification.create() + .viewer(sender) + .notice(messages -> messages.otherFlyCommandMessage) + .placeholder("{state}", target.getAllowFlight() ? "enabled" : "disabled") + .placeholder("{player}", target.getName()) + .send(); + + multification.create() + .player(target.getUniqueId()) + .notice(messages -> messages.otherFlyCommandMessageTarget) + .placeholder("{state}", target.getAllowFlight() ? "enabled" : "disabled") + .placeholder("{player}", sender.getName()) + .send(); + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/command/GiveCommand.java b/examples/paper/src/main/java/com/eternalcode/example/paper/command/GiveCommand.java new file mode 100644 index 0000000..791aff8 --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/command/GiveCommand.java @@ -0,0 +1,52 @@ +package com.eternalcode.example.paper.command; + +import com.eternalcode.example.paper.multification.ExampleMultification; +import dev.rollczi.litecommands.annotations.argument.Arg; +import dev.rollczi.litecommands.annotations.command.Command; +import dev.rollczi.litecommands.annotations.context.Context; +import dev.rollczi.litecommands.annotations.execute.Execute; +import dev.rollczi.litecommands.annotations.optional.OptionalArg; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +@Command(name = "give") +public class GiveCommand { + + private final ExampleMultification multification; + + public GiveCommand(ExampleMultification multification) { + this.multification = multification; + } + + @Execute + public void execute( + @Context CommandSender commandSender, + @Arg("nick") Player target, + @Arg("item") Material item, + @OptionalArg("amount") Integer amount) { + if (amount == null) { + amount = 1; + } + + multification.create() + .player(target.getUniqueId()) + .notice(messages -> messages.receiverGiveCommandMessage) + .placeholder("{player}", commandSender.getName()) + .placeholder("{amount}", amount.toString()) + .placeholder("{item}", item.name()) + .send(); + + multification + .create() + .viewer(commandSender) + .notice(messages -> messages.senderGiveCommandMessage) + .placeholder("{player}", target.getName()) + .placeholder("{amount}", amount.toString()) + .placeholder("{item}", item.name()) + .send(); + + target.getInventory().addItem(new ItemStack(item, amount)); + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/command/ReloadCommand.java b/examples/paper/src/main/java/com/eternalcode/example/paper/command/ReloadCommand.java new file mode 100644 index 0000000..718d61b --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/command/ReloadCommand.java @@ -0,0 +1,39 @@ +package com.eternalcode.example.paper.command; + +import com.eternalcode.example.paper.config.ConfigurationManager; +import com.eternalcode.example.paper.multification.ExampleMultification; +import dev.rollczi.litecommands.annotations.command.Command; +import dev.rollczi.litecommands.annotations.context.Context; +import dev.rollczi.litecommands.annotations.execute.Execute; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@Command(name = "reload-config") +public class ReloadCommand { + + private final ConfigurationManager configurationManager; + private final ExampleMultification multification; + + public ReloadCommand(ConfigurationManager configurationManager, ExampleMultification multification) { + this.configurationManager = configurationManager; + this.multification = multification; + } + + @Execute + public void execute(@Context CommandSender sender) { + this.configurationManager.reload(); + + if (sender instanceof Player player) { + this.multification.create() + .player(player.getUniqueId()) + .notice(messagesConfig -> messagesConfig.reloadMessage) + .send(); + return; + } + + this.multification.create() + .console() + .notice(messagesConfig -> messagesConfig.reloadMessage) + .send(); + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/command/TeleportCommand.java b/examples/paper/src/main/java/com/eternalcode/example/paper/command/TeleportCommand.java new file mode 100644 index 0000000..654ddff --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/command/TeleportCommand.java @@ -0,0 +1,31 @@ +package com.eternalcode.example.paper.command; + +import com.eternalcode.example.paper.multification.ExampleMultification; +import dev.rollczi.litecommands.annotations.argument.Arg; +import dev.rollczi.litecommands.annotations.context.Context; +import dev.rollczi.litecommands.annotations.execute.Execute; +import dev.rollczi.litecommands.annotations.permission.Permission; +import dev.rollczi.litecommands.annotations.command.Command; +import org.bukkit.entity.Player; + +@Command(name = "teleport", aliases = "tp") +@Permission("example.teleport") +public class TeleportCommand { + + private final ExampleMultification multification; + + public TeleportCommand(ExampleMultification multification) { + this.multification = multification; + } + + @Execute + public void teleportSelf(@Context Player sender, @Arg Player to) { + multification.create() + .player(sender.getUniqueId()) + .notice(messages -> messages.selfTeleportCommandMessage) + .placeholder("{player}", to.getName()) + .send(); + + sender.teleport(to.getLocation()); + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerCommand.java b/examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerCommand.java new file mode 100644 index 0000000..61867bf --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerCommand.java @@ -0,0 +1,22 @@ +package com.eternalcode.example.paper.command.timer; + +import dev.rollczi.litecommands.annotations.command.Command; +import dev.rollczi.litecommands.annotations.execute.Execute; +import dev.rollczi.litecommands.annotations.permission.Permission; +import java.time.Duration; + +@Command(name = "timer") +@Permission("example.timer") +public class TimerCommand { + + private final TimerManager timerManager; + + public TimerCommand(TimerManager timerManager) { + this.timerManager = timerManager; + } + + @Execute + public void execute() { + this.timerManager.startTimer(Duration.ofSeconds(5)); + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerManager.java b/examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerManager.java new file mode 100644 index 0000000..9968db3 --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/command/timer/TimerManager.java @@ -0,0 +1,37 @@ +package com.eternalcode.example.paper.command.timer; + +import com.eternalcode.example.paper.multification.ExampleMultification; +import java.time.Duration; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitScheduler; + +public class TimerManager { + + private final BukkitScheduler bukkitScheduler; + private final Plugin plugin; + private final ExampleMultification multification; + + public TimerManager(BukkitScheduler bukkitScheduler, Plugin plugin, ExampleMultification multification) { + this.bukkitScheduler = bukkitScheduler; + this.plugin = plugin; + this.multification = multification; + } + + public void startTimer(Duration duration) { + tickTimer(duration.toSeconds()); + } + + private void tickTimer(long seconds) { + if (seconds == 0) { + return; + } + + this.multification.create() + .all() + .notice(messages -> messages.bossbarTimer) + .placeholder("{time}", String.valueOf(seconds)) + .send(); + + this.bukkitScheduler.runTaskLater(plugin, () -> tickTimer(seconds - 1), 20L); + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/config/ConfigurationManager.java b/examples/paper/src/main/java/com/eternalcode/example/paper/config/ConfigurationManager.java new file mode 100644 index 0000000..0551707 --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/config/ConfigurationManager.java @@ -0,0 +1,42 @@ +package com.eternalcode.example.paper.config; + +import com.eternalcode.multification.cdn.MultificationNoticeCdnComposer; +import com.eternalcode.multification.notice.Notice; +import com.eternalcode.multification.notice.resolver.NoticeResolverRegistry; +import net.dzikoysk.cdn.Cdn; +import net.dzikoysk.cdn.CdnFactory; +import net.dzikoysk.cdn.source.Source; + +import java.io.File; + +public class ConfigurationManager { + + private final File dataFolder; + private final Cdn cdn; + private MessagesConfig messagesConfig; + + public ConfigurationManager(File dataFolder, NoticeResolverRegistry noticeRegistry) { + this.dataFolder = dataFolder; + this.cdn = CdnFactory.createYamlLike() + .getSettings() + .withComposer(Notice.class, new MultificationNoticeCdnComposer(noticeRegistry)) + .build(); + } + + public void load(MessagesConfig config, String fileName) { + this.messagesConfig = config; + File file = new File(this.dataFolder, fileName); + + this.cdn.load(Source.of(file), config) + .orThrow(cause -> cause); + + this.cdn.render(config, Source.of(file)) + .orThrow(cause -> cause); + } + + public void reload() { + if (this.messagesConfig != null) { + load(this.messagesConfig, "messages.yml"); + } + } +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java b/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java new file mode 100644 index 0000000..081b602 --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java @@ -0,0 +1,45 @@ +package com.eternalcode.example.paper.config; + +import com.eternalcode.multification.notice.Notice; +import net.dzikoysk.cdn.entity.Description; +import net.kyori.adventure.bossbar.BossBar; + +import java.time.Duration; + +public class MessagesConfig { + + @Description("# Fly command message") + public Notice selfFlyCommandMessage = Notice + .chat("You have toggled fly mode. It is now {state}."); + public Notice otherFlyCommandMessage = Notice.chat( + "You have toggled fly mode for {player}. It is now {state}."); + public Notice otherFlyCommandMessageTarget = Notice.builder() + .chat("Your fly mode has been toggled by {player}. It is now {state}.") + .sound("minecraft:entity.item.pickup") + .build(); + + @Description("# Give command message") + public Notice senderGiveCommandMessage = Notice + .title("You have given {amount}x {item} to {player}."); + public Notice receiverGiveCommandMessage = Notice.builder() + .title("You have received {amount}x {item} from {player}.") + .subtitle("Remember to say thank you!") + .sound("minecraft:entity.item.pickup") + .build(); + + @Description("# Teleport command message") + public Notice selfTeleportCommandMessage = Notice.builder() + .actionBar("You have been teleported to {player}.") + .sound("minecraft:entity.enderman.teleport", 2.0F, 2.0F) + .build(); + + @Description("# Epic bossbar timer!!!") + public Notice bossbarTimer = Notice.builder() + .bossBar(BossBar.Color.RED, Duration.ofSeconds(1), "Timer: {time}") + .build(); + + public Notice reloadMessage = Notice.builder() + .chat("Configuration has been reloaded!") + .sound("minecraft:ambient.basalt_deltas.additions", 1.0F, 1.0F) + .build(); +} diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/multification/ExampleMultification.java b/examples/paper/src/main/java/com/eternalcode/example/paper/multification/ExampleMultification.java new file mode 100644 index 0000000..4aa774a --- /dev/null +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/multification/ExampleMultification.java @@ -0,0 +1,37 @@ +package com.eternalcode.example.paper.multification; + +import com.eternalcode.example.paper.config.MessagesConfig; +import com.eternalcode.multification.adventure.AudienceConverter; +import com.eternalcode.multification.paper.PaperMultification; +import com.eternalcode.multification.translation.TranslationProvider; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.ComponentSerializer; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class ExampleMultification extends PaperMultification { + + private final MessagesConfig messagesConfig; + private final MiniMessage miniMessage; + + public ExampleMultification(MessagesConfig messagesConfig) { + this.messagesConfig = messagesConfig; + this.miniMessage = MiniMessage.miniMessage(); + } + + @Override + protected @NotNull TranslationProvider translationProvider() { + return locale -> this.messagesConfig; + } + + @Override + protected @NotNull ComponentSerializer serializer() { + return this.miniMessage; + } + + @Override + protected @NotNull AudienceConverter audienceConverter() { + return commandSender -> commandSender; + } +} diff --git a/multification-paper/build.gradle.kts b/multification-paper/build.gradle.kts new file mode 100644 index 0000000..39cfa39 --- /dev/null +++ b/multification-paper/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `multification-java` + `multification-java-17` + `multification-repositories` + `multification-publish` +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +dependencies { + api(project(":multification-core")) + compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") + testImplementation("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") +} diff --git a/multification-paper/src/com/eternalcode/multification/paper/PaperLocaleProvider.java b/multification-paper/src/com/eternalcode/multification/paper/PaperLocaleProvider.java new file mode 100644 index 0000000..a4998ed --- /dev/null +++ b/multification-paper/src/com/eternalcode/multification/paper/PaperLocaleProvider.java @@ -0,0 +1,20 @@ +package com.eternalcode.multification.paper; + +import com.eternalcode.multification.locate.LocaleProvider; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Locale; +import org.jspecify.annotations.NonNull; + +class PaperLocaleProvider implements LocaleProvider { + + @Override + public @NonNull Locale provide(CommandSender viewer) { + if (viewer instanceof Player player) { + return player.locale(); + } + + return Locale.ROOT; + } +} diff --git a/multification-paper/src/com/eternalcode/multification/paper/PaperMultification.java b/multification-paper/src/com/eternalcode/multification/paper/PaperMultification.java new file mode 100644 index 0000000..8df8fc2 --- /dev/null +++ b/multification-paper/src/com/eternalcode/multification/paper/PaperMultification.java @@ -0,0 +1,36 @@ +package com.eternalcode.multification.paper; + +import com.eternalcode.multification.Multification; +import com.eternalcode.multification.executor.AsyncExecutor; +import com.eternalcode.multification.locate.LocaleProvider; +import com.eternalcode.multification.viewer.ViewerProvider; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +public abstract class PaperMultification extends Multification { + + public static final ViewerProvider DEFAULT_VIEWER_PROVIDER = new PaperViewerProvider(); + public static final LocaleProvider DEFAULT_LOCALE_PROVIDER = new PaperLocaleProvider(); + + protected PaperMultification() { + super(); + } + + @Override + protected @NotNull ViewerProvider viewerProvider() { + return DEFAULT_VIEWER_PROVIDER; + } + + @Override + protected @NotNull LocaleProvider localeProvider() { + return DEFAULT_LOCALE_PROVIDER; + } + + @Override + protected @NotNull AsyncExecutor asyncExecutor() { + return (runnable) -> Bukkit.getScheduler() + .runTaskAsynchronously(JavaPlugin.getProvidingPlugin(PaperMultification.class), runnable); + } +} diff --git a/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java b/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java new file mode 100644 index 0000000..955a1fd --- /dev/null +++ b/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java @@ -0,0 +1,60 @@ +package com.eternalcode.multification.paper; + +import com.eternalcode.multification.viewer.ViewerProvider; +import java.util.Collection; +import java.util.UUID; +import java.util.stream.Collectors; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +class PaperViewerProvider implements ViewerProvider { + + @Override + public CommandSender console() { + return Bukkit.getConsoleSender(); + } + + @Override + public CommandSender player(UUID uuid) { + Player player = Bukkit.getPlayer(uuid); + + if (player == null || !player.isOnline()) { + return null; + } + + return player; + } + + @Override + public Collection all() { + return Bukkit.getOnlinePlayers() + .stream() + .filter(Player::isOnline) + .map(player -> (CommandSender) player) + .collect(Collectors.toList()); + } + + @Override + public Collection onlinePlayers() { + return Bukkit.getOnlinePlayers() + .stream() + .filter(Player::isOnline) + .map(player -> (CommandSender) player) + .collect(Collectors.toList()); + } + + @Override + public Collection onlinePlayers(String permission) { + if (permission == null || permission.isEmpty()) { + return onlinePlayers(); + } + + return Bukkit.getOnlinePlayers() + .stream() + .filter(Player::isOnline) + .filter(player -> player.hasPermission(permission)) + .map(player -> (CommandSender) player) + .collect(Collectors.toList()); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index f85e277..487047b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,5 +4,6 @@ include("multification-core") include("multification-cdn") include("multification-okaeri") include("multification-bukkit") - +include("multification-paper") include("examples:bukkit") +include("examples:paper") From 692872512cf32d836b0871f3487216e6a9c69786 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sat, 10 Jan 2026 20:43:35 +0100 Subject: [PATCH 2/7] Update GitHub workflows to refine CI/CD setup --- .github/{workflows => }/CODEOWNERS | 0 .github/workflows/gradle.yml | 37 ++++++++++----------------- .github/workflows/publish-release.yml | 20 ++++++++------- 3 files changed, 25 insertions(+), 32 deletions(-) rename .github/{workflows => }/CODEOWNERS (100%) diff --git a/.github/workflows/CODEOWNERS b/.github/CODEOWNERS similarity index 100% rename from .github/workflows/CODEOWNERS rename to .github/CODEOWNERS diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 086d8f7..a9c3635 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,4 +1,4 @@ -name: Java CI with Gradle +name: CI on: push: @@ -8,29 +8,20 @@ on: jobs: build: + name: Build runs-on: ubuntu-latest - strategy: - matrix: - java: - - 17 - fail-fast: false steps: - name: Checkout - uses: actions/checkout@v4.3.1 - - name: 'Set up JDK ${{ matrix.java }}' - uses: actions/setup-java@v4.8.0 - with: - distribution: adopt - java-version: '${{ matrix.java }}' - - name: Cache Gradle - uses: actions/cache@v4.3.0 + uses: actions/checkout@v5 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 with: - path: ~/.gradle/caches - key: >- - ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', - '**/gradle-wrapper.properties') }} - restore-keys: '${{ runner.os }}-gradle-' - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Build the Jar - run: './gradlew clean test build' \ No newline at end of file + distribution: 'temurin' + java-version: 21 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + + - name: Build with Gradle + run: ./gradlew build \ No newline at end of file diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index ba81f0d..accc452 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -1,25 +1,27 @@ name: Publish Multification + on: release: - branches: [ master ] + types: [published] + jobs: publish: + name: Publish runs-on: ubuntu-latest environment: deployment steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - - name: Set up JDK - uses: actions/setup-java@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v5 with: distribution: 'temurin' - java-version: 17 - cache: 'gradle' - - - name: Grant execute permission for gradlew - run: chmod +x gradlew + java-version: 21 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + - name: Publish with Gradle run: ./gradlew publish env: From 067b6edc84b43715f4e61e51ac7859197544d0fb Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sat, 10 Jan 2026 20:45:05 +0100 Subject: [PATCH 3/7] ci: make gradlew executable in CI workflows --- .github/workflows/gradle.yml | 3 +++ .github/workflows/publish-release.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a9c3635..ddf6578 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -22,6 +22,9 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v5 + + - name: Make gradlew executable + run: chmod +x gradlew - name: Build with Gradle run: ./gradlew build \ No newline at end of file diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index accc452..158db5b 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -21,6 +21,9 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v5 + + - name: Make gradlew executable + run: chmod +x gradlew - name: Publish with Gradle run: ./gradlew publish From 32fe51336559d4743cb2b250d137a5f3a63a71bc Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sat, 10 Jan 2026 21:09:57 +0100 Subject: [PATCH 4/7] Refactor README examples for cleaner code and update Maven repository comments. --- README.md | 27 ++++--------------- .../multification-repositories.gradle.kts | 2 +- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 55a4ce4..03e518c 100644 --- a/README.md +++ b/README.md @@ -138,15 +138,9 @@ After that, you can use the `multification` instance to send notifications: ```java multification.create() - . - -player(player.getUniqueId()) - . - -notice(messages ->messages.yourMessage) - . - -send(); + .player(player.getUniqueId()) + .notice(messages ->messages.yourMessage) + .send(); ``` ## Configuration Support @@ -194,19 +188,8 @@ To load and create the config file, use the following code in the init method su MessagesConfig messages = new MessagesConfig(); Resource resource = Source.of(this.dataFolder, "messages.yml"); -cdn. - -load(resource, messages) - . - -orThrow(cause ->cause); - - cdn. - -render(config, resource) - . - -orThrow(cause ->cause); +cdn.load(resource, messages).orThrow(cause ->cause); +cdn.render(config, resource).orThrow(cause ->cause); ``` Checkout example with diff --git a/buildSrc/src/main/kotlin/multification-repositories.gradle.kts b/buildSrc/src/main/kotlin/multification-repositories.gradle.kts index 88a0d2d..dc1e440 100644 --- a/buildSrc/src/main/kotlin/multification-repositories.gradle.kts +++ b/buildSrc/src/main/kotlin/multification-repositories.gradle.kts @@ -5,7 +5,7 @@ plugins { repositories { mavenCentral() - maven("https://repo.papermc.io/repository/maven-public/") // paper, adventure, velocity (NOWY URL) + maven("https://repo.papermc.io/repository/maven-public/") // paper, adventure, velocity maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // spigot maven("https://repo.panda-lang.org/releases/") // expressible maven("https://repo.stellardrift.ca/repository/snapshots/") From 3d6af95ba5aa4dc77cf1d236d8099f99650bbfe0 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sun, 11 Jan 2026 20:25:45 +0100 Subject: [PATCH 5/7] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakub KΔ™dziora <77227023+Jakubk15@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 03e518c..7a872bb 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Messages can be sent to any audience, such as players or the console. |-------------------|------------------------|--------------|-----------------------|------------------------| | **Paper** | `multification-paper` | Java 21 | Native (built-in) | βœ… Recommended | | **Bukkit/Spigot** | `multification-bukkit` | Java 8+ | External adapter | βœ… Supported | -| **Velocity** | `multification-bukkit` | Java 21+ | Native | ❌ Soon | +| **Velocity** | `multification-velocity` | Java 21+ | Native | ❌ Soon | | **Core** | `multification-core` | Java 8+ | Custom implementation | βœ… For custom platforms | > **πŸ’‘ Recommendation:** Use `multification-paper` for Paper servers (1.19.4+) to leverage native Adventure API without From 3d5351cf361beff29899f2fbc88bd75ccc24e142 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sun, 11 Jan 2026 20:29:46 +0100 Subject: [PATCH 6/7] Clean up code examples in README, streamline viewer provider logic, and improve formatting. --- README.md | 30 ++++--------------- .../paper/PaperViewerProvider.java | 3 -- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7a872bb..4360d91 100644 --- a/README.md +++ b/README.md @@ -175,9 +175,9 @@ public class MessagesConfig { ```java Cdn cdn = CdnFactory.createYamlLike() - .getSettings() - .withComposer(Notice.class, new MultificationNoticeCdnComposer(multification.getNoticeRegistry())) - .build(); + .getSettings() + .withComposer(Notice.class, new MultificationNoticeCdnComposer(multification.getNoticeRegistry())) + .build(); ``` #### (CDN) 4. Load the configuration: @@ -227,33 +227,13 @@ public class MessagesConfig extends OkaeriConfig { ```java MessagesConfig config = (MessagesConfig) ConfigManager.create(MessagesConfig.class) .withConfigurer(new MultificationSerdesPack(multification.getNoticeRegistry())) - .withConfigurer( - new SerdesCommons(), - new YamlBukkitConfigurer(), - new SerdesBukkit()) // specify configurers for your platform + .withConfigurer(new SerdesCommons(), new YamlBukkitConfigurer(), new SerdesBukkit()) // specify configurers for your platform .withBindFile(new File(dataFolder, "messages.yml")) .withRemoveOrphans(true) // automatic removal of undeclared keys .saveDefaults() // save file if does not exists .load(true); ``` -## πŸ“š Documentation - -For complete documentation, guides, and examples, visit our [documentation](/docs): - -- **[Getting Started](/docs/installation)** - Installation and setup -- **[Basic Usage](/docs/basic-usage)** - Learn the fundamentals -- **[Configuration](/docs/configuration)** - CDN & Okaeri integration -- **[Advanced Features](/docs/advanced)** - i18n, custom formatters, platform adapters -- **[Platform Comparison](/docs/platform-comparison)** - Paper vs Bukkit -- **[API Reference](/docs/api-reference)** - Complete API documentation -- **[Examples](/docs/examples)** - Working code examples -- **[FAQ](/docs/faq)** - Common questions and troubleshooting - -## 🀝 Contributing - -We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. - ## πŸ“„ License This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. @@ -267,4 +247,4 @@ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENS --- -Made with ❀️ by [EternalCode Team](https://github.com/EternalCodeTeam) +Made with ❀️ by [EternalCodeTeam](https://github.com/EternalCodeTeam) diff --git a/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java b/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java index 955a1fd..957a665 100644 --- a/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java +++ b/multification-paper/src/com/eternalcode/multification/paper/PaperViewerProvider.java @@ -30,7 +30,6 @@ public CommandSender player(UUID uuid) { public Collection all() { return Bukkit.getOnlinePlayers() .stream() - .filter(Player::isOnline) .map(player -> (CommandSender) player) .collect(Collectors.toList()); } @@ -39,7 +38,6 @@ public Collection all() { public Collection onlinePlayers() { return Bukkit.getOnlinePlayers() .stream() - .filter(Player::isOnline) .map(player -> (CommandSender) player) .collect(Collectors.toList()); } @@ -52,7 +50,6 @@ public Collection onlinePlayers(String permission) { return Bukkit.getOnlinePlayers() .stream() - .filter(Player::isOnline) .filter(player -> player.hasPermission(permission)) .map(player -> (CommandSender) player) .collect(Collectors.toList()); From a59b2064cd0a1a0116b9630522ff3f6b20fdcf1f Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Sun, 11 Jan 2026 20:31:16 +0100 Subject: [PATCH 7/7] Update examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../com/eternalcode/example/paper/config/MessagesConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java b/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java index 081b602..7cc9a7d 100644 --- a/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java +++ b/examples/paper/src/main/java/com/eternalcode/example/paper/config/MessagesConfig.java @@ -38,6 +38,7 @@ public class MessagesConfig { .bossBar(BossBar.Color.RED, Duration.ofSeconds(1), "Timer: {time}") .build(); + @Description("# Reload command message") public Notice reloadMessage = Notice.builder() .chat("Configuration has been reloaded!") .sound("minecraft:ambient.basalt_deltas.additions", 1.0F, 1.0F)