diff --git a/automessage-core/build.gradle.kts b/automessage-core/build.gradle.kts index e542317..e351006 100644 --- a/automessage-core/build.gradle.kts +++ b/automessage-core/build.gradle.kts @@ -2,10 +2,10 @@ dependencies { compileOnlyApi("org.spigotmc:spigot-api:1.21.10-R0.1-SNAPSHOT") implementation("net.kyori:adventure-platform-bukkit:4.4.1") - implementation("net.kyori:adventure-text-minimessage:4.21.0") + implementation("net.kyori:adventure-text-minimessage:4.25.0") - implementation("com.eternalcode:multification-bukkit:1.2.2") - implementation("com.eternalcode:multification-okaeri:1.2.2") + implementation("com.eternalcode:multification-bukkit:1.2.3") + implementation("com.eternalcode:multification-okaeri:1.2.3") api("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.9") implementation("eu.okaeri:okaeri-configs-serdes-commons:5.0.5") @@ -15,9 +15,9 @@ dependencies { implementation("dev.rollczi:litecommands-annotations:3.10.6") testImplementation("org.junit.jupiter:junit-jupiter:6.0.1") - testImplementation("org.assertj:assertj-core:3.25.2") - testImplementation("org.mockito:mockito-core:5.8.0") - testImplementation("org.mockito:mockito-junit-jupiter:5.8.0") + testImplementation("org.assertj:assertj-core:3.27.7") + testImplementation("org.mockito:mockito-core:5.20.0") + testImplementation("org.mockito:mockito-junit-jupiter:5.20.0") testImplementation("org.mockito:mockito-inline:5.2.0") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } \ No newline at end of file diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/AutoMessagePlugin.java b/automessage-core/src/main/java/com/github/imdmk/automessage/AutoMessagePlugin.java index 982b2ae..9583851 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/AutoMessagePlugin.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/AutoMessagePlugin.java @@ -5,11 +5,14 @@ import com.github.imdmk.automessage.command.dispatcher.EnableCommand; import com.github.imdmk.automessage.command.reload.ReloadCommand; import com.github.imdmk.automessage.config.ConfigManager; +import com.github.imdmk.automessage.message.MessageConfig; +import com.github.imdmk.automessage.message.MessageService; import com.github.imdmk.automessage.platform.litecommands.handler.InvalidUsageHandlerImpl; import com.github.imdmk.automessage.platform.litecommands.handler.MissingPermissionsHandlerImpl; import com.github.imdmk.automessage.platform.litecommands.handler.NoticeResultHandlerImpl; import com.github.imdmk.automessage.platform.logger.BukkitPluginLogger; import com.github.imdmk.automessage.platform.logger.PluginLogger; +import com.github.imdmk.automessage.platform.metrics.MetricsService; import com.github.imdmk.automessage.platform.scheduler.BukkitTaskScheduler; import com.github.imdmk.automessage.platform.scheduler.TaskScheduler; import com.github.imdmk.automessage.scheduled.ScheduledMessagesConfig; @@ -17,104 +20,72 @@ import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcher; import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig; import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherTask; -import com.github.imdmk.automessage.scheduled.selector.MessageSelector; import com.github.imdmk.automessage.scheduled.selector.MessageSelectorFactory; -import com.github.imdmk.automessage.shared.message.MessageConfig; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; import dev.rollczi.litecommands.LiteCommands; import dev.rollczi.litecommands.bukkit.LiteBukkitFactory; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import org.bstats.bukkit.Metrics; import org.bukkit.Server; import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; final class AutoMessagePlugin { private static final String PLUGIN_PREFIX = "AutoMessage"; - private static final int PLUGIN_METRICS_ID = 19487; - private final Plugin plugin; - private final Server server; private final PluginLogger logger; + private final ConfigManager configManager; - private ConfigManager configManager; + private final MessageService messageService; + private final TaskScheduler taskScheduler; + private final LiteCommands liteCommands; + private final MetricsService metricsService; - private BukkitAudiences bukkitAudiences; - private MessageService messageService; - private TaskScheduler taskScheduler; + AutoMessagePlugin(Plugin plugin) { + final Server server = plugin.getServer(); + this.logger = new BukkitPluginLogger(plugin.getLogger()); - private LiteCommands liteCommands; - private Metrics metrics; + this.configManager = new ConfigManager(logger, plugin.getDataFolder()); - public AutoMessagePlugin( - @NotNull final Plugin plugin, - @NotNull final Server server, - @NotNull final PluginLogger logger - ) { - this.plugin = Validator.notNull(plugin, "plugin"); - this.server = Validator.notNull(server, "server"); - this.logger = Validator.notNull(logger, "logger"); - } - - AutoMessagePlugin(@NotNull final Plugin plugin) { - this(plugin, plugin.getServer(), new BukkitPluginLogger(plugin)); - } - - void enable(@NotNull PluginSettings settings) { - Validator.notNull(settings, "settings"); - - configManager = new ConfigManager(logger, plugin.getDataFolder()); - configManager.createAll(settings.configs()); - - bukkitAudiences = BukkitAudiences.create(plugin); - messageService = new MessageService(configManager.require(MessageConfig.class), bukkitAudiences); - taskScheduler = new BukkitTaskScheduler(plugin, server.getScheduler()); - - final MessageDispatcherConfig messageDispatcherConfig = configManager.require(MessageDispatcherConfig.class); - final ScheduledMessagesConfig scheduledMessagesConfig = configManager.require(ScheduledMessagesConfig.class); + final MessageConfig messageConfig = configManager.create(MessageConfig.class); + final ScheduledMessagesConfig scheduledMessagesConfig = configManager.create(ScheduledMessagesConfig.class); + final MessageDispatcherConfig dispatcherConfig = configManager.create(MessageDispatcherConfig.class); - final AudienceFilter audienceFilter = AudienceFilter.createDefault(); - final MessageSelector messageSelector = MessageSelectorFactory.create(messageDispatcherConfig.selector); + this.messageService = new MessageService(messageConfig, plugin); + this.taskScheduler = new BukkitTaskScheduler(plugin, server.getScheduler()); final MessageDispatcher messageDispatcher = new MessageDispatcher( messageService, - messageSelector, - audienceFilter, + MessageSelectorFactory.create(dispatcherConfig.selector), + AudienceFilter.ruleFilter(), () -> scheduledMessagesConfig.messages ); - MessageDispatcherTask messageDispatcherTask = new MessageDispatcherTask(server, messageDispatcherConfig, messageDispatcher); - taskScheduler.runTimerAsync(messageDispatcherTask); + final MessageDispatcherTask dispatcherTask = new MessageDispatcherTask(server, dispatcherConfig, messageDispatcher); + taskScheduler.runTimerAsync(dispatcherTask); - liteCommands = LiteBukkitFactory.builder(PLUGIN_PREFIX, plugin, server) + this.liteCommands = LiteBukkitFactory.builder(PLUGIN_PREFIX, plugin, server) .invalidUsage(new InvalidUsageHandlerImpl(messageService)) .missingPermission(new MissingPermissionsHandlerImpl(messageService)) .result(Notice.class, new NoticeResultHandlerImpl(messageService)) .commands( - new DisableCommand(messageDispatcherConfig, messageService), - new EnableCommand(messageDispatcherConfig, messageService), + new DisableCommand(dispatcherConfig, messageService), + new EnableCommand(dispatcherConfig, messageService), new ReloadCommand(logger, configManager, taskScheduler, messageService) ) .build(); - metrics = new Metrics(plugin, PLUGIN_METRICS_ID); + this.metricsService = new MetricsService(plugin); logger.info("%s plugin enabled.", PLUGIN_PREFIX); } void disable() { -// Validator.ifNotNull(configManager, manager -> { -// manager.saveAll(); -// manager.clearAll(); -// }); - Validator.ifNotNull(bukkitAudiences, BukkitAudiences::close); - Validator.ifNotNull(taskScheduler, TaskScheduler::shutdown); - Validator.ifNotNull(liteCommands, LiteCommands::unregister); - Validator.ifNotNull(metrics, Metrics::shutdown); + configManager.saveAll(); + configManager.clearAll(); + messageService.shutdown(); + taskScheduler.shutdown(); + liteCommands.unregister(); + metricsService.shutdown(); logger.info("%s plugin disabled successfully.", PLUGIN_PREFIX); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/PluginSettings.java b/automessage-core/src/main/java/com/github/imdmk/automessage/PluginSettings.java deleted file mode 100644 index 16c8374..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/PluginSettings.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.imdmk.automessage; - -import com.github.imdmk.automessage.config.ConfigSection; - -import java.util.List; - -public interface PluginSettings { - - List> configs(); - -} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/DisableCommand.java b/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/DisableCommand.java index 1e667c3..bae4ba6 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/DisableCommand.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/DisableCommand.java @@ -1,14 +1,12 @@ package com.github.imdmk.automessage.command.dispatcher; +import com.github.imdmk.automessage.message.MessageService; import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; 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.jetbrains.annotations.NotNull; @Command(name = "automessage disable") @Permission("command.automessage.disable") @@ -18,11 +16,11 @@ public final class DisableCommand { private final MessageService messageService; public DisableCommand( - @NotNull MessageDispatcherConfig dispatcherConfig, - @NotNull MessageService messageService + MessageDispatcherConfig dispatcherConfig, + MessageService messageService ) { - this.dispatcherConfig = Validator.notNull(dispatcherConfig, "dispatcherConfig"); - this.messageService = Validator.notNull(messageService, "messageService"); + this.dispatcherConfig = dispatcherConfig; + this.messageService = messageService; } @Execute diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/EnableCommand.java b/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/EnableCommand.java index 1f0730e..ec0c072 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/EnableCommand.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/EnableCommand.java @@ -1,14 +1,12 @@ package com.github.imdmk.automessage.command.dispatcher; +import com.github.imdmk.automessage.message.MessageService; import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; 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.jetbrains.annotations.NotNull; @Command(name = "automessage enable") @Permission("command.automessage.enable") @@ -18,11 +16,11 @@ public final class EnableCommand { private final MessageService messageService; public EnableCommand( - @NotNull MessageDispatcherConfig dispatcherConfig, - @NotNull MessageService messageService + MessageDispatcherConfig dispatcherConfig, + MessageService messageService ) { - this.dispatcherConfig = Validator.notNull(dispatcherConfig, "dispatcherConfig"); - this.messageService = Validator.notNull(messageService, "messageService"); + this.dispatcherConfig = dispatcherConfig; + this.messageService = messageService; } @Execute diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/messages/DispatcherMessagesImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/messages/ENDispatcherMessages.java similarity index 97% rename from automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/messages/DispatcherMessagesImpl.java rename to automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/messages/ENDispatcherMessages.java index 8118737..334ff0a 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/messages/DispatcherMessagesImpl.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/command/dispatcher/messages/ENDispatcherMessages.java @@ -4,7 +4,7 @@ import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; -public final class DispatcherMessagesImpl +public final class ENDispatcherMessages extends OkaeriConfig implements DispatcherMessages { diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/ReloadCommand.java b/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/ReloadCommand.java index a79f9cc..bed12ed 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/ReloadCommand.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/ReloadCommand.java @@ -1,16 +1,14 @@ package com.github.imdmk.automessage.command.reload; import com.github.imdmk.automessage.config.ConfigManager; +import com.github.imdmk.automessage.message.MessageService; import com.github.imdmk.automessage.platform.logger.PluginLogger; import com.github.imdmk.automessage.platform.scheduler.TaskScheduler; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; 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.jetbrains.annotations.NotNull; @Command(name = "automessage reload") @Permission("command.automessage.reload") @@ -22,15 +20,15 @@ public final class ReloadCommand { private final MessageService messageService; public ReloadCommand( - @NotNull PluginLogger logger, - @NotNull ConfigManager configManager, - @NotNull TaskScheduler taskScheduler, - @NotNull MessageService messageService + PluginLogger logger, + ConfigManager configManager, + TaskScheduler taskScheduler, + MessageService messageService ) { - this.logger = Validator.notNull(logger, "logger"); - this.configManager = Validator.notNull(configManager, "configManager"); - this.taskScheduler = Validator.notNull(taskScheduler, "taskScheduler"); - this.messageService = Validator.notNull(messageService, "messageService"); + this.logger = logger; + this.configManager = configManager; + this.taskScheduler = taskScheduler; + this.messageService = messageService; } @Execute diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/messages/ReloadMessagesImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/messages/ENReloadMessages.java similarity index 96% rename from automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/messages/ReloadMessagesImpl.java rename to automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/messages/ENReloadMessages.java index e43251a..57b4dd8 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/messages/ReloadMessagesImpl.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/command/reload/messages/ENReloadMessages.java @@ -4,7 +4,7 @@ import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; -public final class ReloadMessagesImpl +public final class ENReloadMessages extends OkaeriConfig implements ReloadMessages { diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigBinder.java b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigBinder.java index 945883a..3e05f03 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigBinder.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigBinder.java @@ -1,24 +1,14 @@ package com.github.imdmk.automessage.config; -import com.github.imdmk.automessage.shared.validate.Validator; -import eu.okaeri.configs.serdes.OkaeriSerdesPack; import eu.okaeri.configs.serdes.commons.SerdesCommons; -import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; -import org.jetbrains.annotations.NotNull; import java.io.File; final class ConfigBinder { - void bind(@NotNull ConfigSection config, @NotNull File file) { - Validator.notNull(config, "config"); - Validator.notNull(file, "file"); - - final OkaeriSerdesPack serdesPack = config.getSerdesPack(); - final YamlSnakeYamlConfigurer yamlConfigurer = YamlConfigurerFactory.create(); - - config.withConfigurer(yamlConfigurer) - .withSerdesPack(serdesPack) + void bind(ConfigSection config, File file) { + config.withConfigurer(YamlConfigurerFactory.create()) + .withSerdesPack(config.getSerdesPack()) .withSerdesPack(new SerdesCommons()) .withBindFile(file) .withRemoveOrphans(true); diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigFactory.java b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigFactory.java index 2d47557..6652195 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigFactory.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigFactory.java @@ -1,21 +1,15 @@ package com.github.imdmk.automessage.config; -import com.github.imdmk.automessage.shared.validate.Validator; import eu.okaeri.configs.ConfigManager; import eu.okaeri.configs.exception.OkaeriException; -import org.jetbrains.annotations.NotNull; final class ConfigFactory { - @NotNull T instantiate(@NotNull Class type) { - Validator.notNull(type, "type"); - + T create(Class type) { try { return ConfigManager.create(type); } catch (OkaeriException e) { - throw new IllegalStateException( - "Failed to instantiate config: " + type.getName(), e - ); + throw new IllegalStateException("Failed to create config: " + type.getName(), e); } } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigLifecycle.java b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigLifecycle.java index a0a2013..974db4b 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigLifecycle.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigLifecycle.java @@ -1,24 +1,22 @@ package com.github.imdmk.automessage.config; import com.github.imdmk.automessage.platform.logger.PluginLogger; -import com.github.imdmk.automessage.shared.validate.Validator; import eu.okaeri.configs.exception.OkaeriException; -import org.jetbrains.annotations.NotNull; final class ConfigLifecycle { private final PluginLogger logger; - ConfigLifecycle(@NotNull PluginLogger logger) { - this.logger = Validator.notNull(logger, "logger"); + ConfigLifecycle(PluginLogger logger) { + this.logger = logger; } - void initialize(@NotNull ConfigSection config) { + void initialize(ConfigSection config) { config.saveDefaults(); load(config); } - void load(@NotNull ConfigSection config) { + void load(ConfigSection config) { try { config.load(true); } catch (OkaeriException e) { @@ -27,7 +25,7 @@ void load(@NotNull ConfigSection config) { } } - void save(@NotNull ConfigSection config) { + void save(ConfigSection config) { try { config.save(); } catch (Exception e) { diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigManager.java b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigManager.java index 9699ddd..aac3dc5 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigManager.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigManager.java @@ -1,8 +1,6 @@ package com.github.imdmk.automessage.config; import com.github.imdmk.automessage.platform.logger.PluginLogger; -import com.github.imdmk.automessage.shared.validate.Validator; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import java.io.File; @@ -23,16 +21,16 @@ public final class ConfigManager { private final ConfigBinder binder; private final ConfigLifecycle lifecycle; - public ConfigManager(@NotNull PluginLogger logger, @NotNull File dataFolder) { - this.dataFolder = Validator.notNull(dataFolder, "dataFolder"); + public ConfigManager(PluginLogger logger, File dataFolder) { + this.dataFolder = dataFolder; this.factory = new ConfigFactory(); this.binder = new ConfigBinder(); this.lifecycle = new ConfigLifecycle(logger); } - public @NotNull T create(@NotNull Class type) { - final T config = factory.instantiate(type); + public C create(Class type) { + final C config = factory.create(type); final File file = new File(dataFolder, config.getFileName()); binder.bind(config, file); @@ -42,18 +40,17 @@ public ConfigManager(@NotNull PluginLogger logger, @NotNull File dataFolder) { return config; } - public void createAll(@NotNull List> types) { + public void createAll(List> types) { types.forEach(this::create); } @SuppressWarnings("unchecked") - public T get(@NotNull Class type) { - return (T) byType.get(type); + public C get(Class type) { + return (C) byType.get(type); } - public @NotNull T require(@NotNull Class type) { - T config = get(type); - + public C require(Class type) { + final C config = get(type); if (config == null) { throw new IllegalStateException("Config not created: " + type.getName()); } @@ -69,7 +66,8 @@ public void saveAll() { configs.forEach(lifecycle::save); } - public @NotNull @Unmodifiable Set getConfigs() { + @Unmodifiable + public Set getConfigs() { return Collections.unmodifiableSet(configs); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigSection.java b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigSection.java index fc2303f..4c0bf32 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigSection.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/config/ConfigSection.java @@ -2,7 +2,6 @@ import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.serdes.OkaeriSerdesPack; -import org.jetbrains.annotations.NotNull; /** * Abstract base class for configuration sections. @@ -26,12 +25,12 @@ public abstract class ConfigSection extends OkaeriConfig { * * @return non-null serialization/deserialization pack */ - public abstract @NotNull OkaeriSerdesPack getSerdesPack(); + public abstract OkaeriSerdesPack getSerdesPack(); /** * Returns the filename (including extension) used to persist this configuration section. * * @return non-null configuration file name */ - public abstract @NotNull String getFileName(); + public abstract String getFileName(); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/message/MessageConfig.java b/automessage-core/src/main/java/com/github/imdmk/automessage/message/MessageConfig.java similarity index 82% rename from automessage-core/src/main/java/com/github/imdmk/automessage/shared/message/MessageConfig.java rename to automessage-core/src/main/java/com/github/imdmk/automessage/message/MessageConfig.java index fd7d5f8..922b1a8 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/message/MessageConfig.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/message/MessageConfig.java @@ -1,15 +1,14 @@ -package com.github.imdmk.automessage.shared.message; +package com.github.imdmk.automessage.message; import com.eternalcode.multification.notice.resolver.NoticeResolverDefaults; import com.eternalcode.multification.okaeri.MultificationSerdesPack; -import com.github.imdmk.automessage.command.dispatcher.messages.DispatcherMessagesImpl; -import com.github.imdmk.automessage.command.reload.messages.ReloadMessagesImpl; +import com.github.imdmk.automessage.command.dispatcher.messages.ENDispatcherMessages; +import com.github.imdmk.automessage.command.reload.messages.ENReloadMessages; import com.github.imdmk.automessage.config.ConfigSection; -import com.github.imdmk.automessage.platform.litecommands.messages.LiteCommandsMessagesImpl; +import com.github.imdmk.automessage.platform.litecommands.messages.ENLiteCommandsMessages; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.annotation.Header; import eu.okaeri.configs.serdes.OkaeriSerdesPack; -import org.jetbrains.annotations.NotNull; @Header({ "# ============================================================================", @@ -46,14 +45,14 @@ public final class MessageConfig extends ConfigSection { "# Contains permission errors, usage hints, and syntax messages.", "#" }) - public LiteCommandsMessagesImpl liteCommandsMessages = new LiteCommandsMessagesImpl(); + public ENLiteCommandsMessages liteCommandsMessages = new ENLiteCommandsMessages(); @Comment({ "#", "# Messages used by dispatcher-related commands.", "#" }) - public DispatcherMessagesImpl dispatcherMessages = new DispatcherMessagesImpl(); + public ENDispatcherMessages dispatcherMessages = new ENDispatcherMessages(); @Comment({ "#", @@ -61,17 +60,17 @@ public final class MessageConfig extends ConfigSection { "# Includes success and failure notifications.", "#" }) - public ReloadMessagesImpl reloadMessages = new ReloadMessagesImpl(); + public ENReloadMessages reloadMessages = new ENReloadMessages(); @Override - public @NotNull OkaeriSerdesPack getSerdesPack() { + public OkaeriSerdesPack getSerdesPack() { return registry -> { registry.register(new MultificationSerdesPack(NoticeResolverDefaults.createRegistry())); }; } @Override - public @NotNull String getFileName() { + public String getFileName() { return "messages.yml"; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/message/MessageService.java b/automessage-core/src/main/java/com/github/imdmk/automessage/message/MessageService.java new file mode 100644 index 0000000..2c43a5e --- /dev/null +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/message/MessageService.java @@ -0,0 +1,58 @@ +package com.github.imdmk.automessage.message; + +import com.eternalcode.multification.adventure.AudienceConverter; +import com.eternalcode.multification.bukkit.BukkitMultification; +import com.eternalcode.multification.notice.provider.NoticeProvider; +import com.eternalcode.multification.translation.TranslationProvider; +import net.kyori.adventure.platform.AudienceProvider; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +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.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public final class MessageService extends BukkitMultification { + + private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); + + private final MessageConfig messageConfig; + private final AudienceProvider audienceProvider; + + public MessageService( + MessageConfig messageConfig, + Plugin plugin + ) { + this.messageConfig = messageConfig; + this.audienceProvider = BukkitAudiences.create(plugin); + } + + @Override + protected TranslationProvider translationProvider() { + return provider -> messageConfig; + } + + @Override + protected ComponentSerializer serializer() { + return MINI_MESSAGE; + } + + @Override + protected AudienceConverter audienceConverter() { + return sender -> { + if (sender instanceof Player player) { + return audienceProvider.player(player.getUniqueId()); + } + return audienceProvider.console(); + }; + } + + public void send(CommandSender sender, NoticeProvider notice) { + create().viewer(sender).notice(notice).send(); + } + + public void shutdown() { + audienceProvider.close(); + } +} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventureComponents.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventureComponents.java new file mode 100644 index 0000000..8bad948 --- /dev/null +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventureComponents.java @@ -0,0 +1,84 @@ +package com.github.imdmk.automessage.platform.adventure; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class AdventureComponents { + + private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); + + private AdventureComponents() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated."); + } + + public static Component text(CharSequence text) { + return MINI_MESSAGE.deserialize(text.toString()); + } + + public static List text(CharSequence... texts) { + final List out = new ArrayList<>(texts.length); + for (final CharSequence text : texts) { + out.add(MINI_MESSAGE.deserialize(text.toString())); + } + + return List.copyOf(out); + } + + public static List text(Iterable texts) { + final List out = new ArrayList<>(); + for (final CharSequence text : texts) { + out.add(MINI_MESSAGE.deserialize(text.toString())); + } + + return List.copyOf(out); + } + + public static Component withoutItalics(Component component) { + return component.decoration(TextDecoration.ITALIC, false); + } + + public static Component withoutItalics(CharSequence text) { + return withoutItalics(text(text)); + } + + public static Component withoutItalics(ComponentLike like) { + return like.asComponent().decoration(TextDecoration.ITALIC, false); + } + + public static List withoutItalics(String... strings) { + final List out = new ArrayList<>(); + for (final String string : strings) { + out.add(withoutItalics(string)); + } + + return List.copyOf(out); + } + + public static String serialize(Component component) { + return MINI_MESSAGE.serialize(component); + } + + public static List serialize(Collection components) { + final List out = new ArrayList<>(components.size()); + for (final ComponentLike component : components) { + out.add(MINI_MESSAGE.serialize(component.asComponent())); + } + + return List.copyOf(out); + } + + public static String serializeJoined(Collection components, CharSequence delimiter) { + final List serialized = new ArrayList<>(components.size()); + for (final ComponentLike component : components) { + serialized.add(MINI_MESSAGE.serialize(component.asComponent())); + } + + return String.join(delimiter, serialized); + } +} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventureFormatter.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventureFormatter.java new file mode 100644 index 0000000..de91c3a --- /dev/null +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventureFormatter.java @@ -0,0 +1,53 @@ +package com.github.imdmk.automessage.platform.adventure; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextReplacementConfig; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public final class AdventureFormatter { + + private AdventureFormatter() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + + public static Component format(String input, AdventurePlaceholders placeholders) { + return format(AdventureComponents.text(input), placeholders); + } + + + public static List format(List components, AdventurePlaceholders placeholders) { + return components.stream() + .map(component -> format(component, placeholders)) + .collect(Collectors.toList()); + } + + public static Component format(Component input, AdventurePlaceholders placeholders) { + if (placeholders.isEmpty()) { + return input; + } + + // Sort keys by descending length to avoid substring overlap + final List> ordered = placeholders.asMap().entrySet().stream() + .sorted(Comparator.>comparingInt(e -> e.getKey().length()).reversed()) + .toList(); + + Component out = input; + for (final Map.Entry e : ordered) { + final String key = e.getKey(); + final Component replacement = e.getValue(); + + final TextReplacementConfig config = TextReplacementConfig.builder() + .matchLiteral(key) + .replacement(replacement) + .build(); + + out = out.replaceText(config); + } + + return out; + } +} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventurePlaceholders.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventurePlaceholders.java new file mode 100644 index 0000000..8bcf4db --- /dev/null +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/adventure/AdventurePlaceholders.java @@ -0,0 +1,78 @@ +package com.github.imdmk.automessage.platform.adventure; + +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +public final class AdventurePlaceholders { + + private static final AdventurePlaceholders EMPTY = new AdventurePlaceholders(Map.of()); + + private final Map map; + + private AdventurePlaceholders(Map map) { + this.map = Collections.unmodifiableMap(map); + } + + @Unmodifiable + public Map asMap() { + return Map.copyOf(map); + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public static AdventurePlaceholders empty() { + return EMPTY; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + + private final Map entries = new LinkedHashMap<>(); + + @Contract("_,_ -> this") + public Builder with(String key, Component value) { + this.entries.put(key, value); + return this; + } + + @Contract("_,_ -> this") + public Builder with(String key, String value) { + this.entries.put(key, Component.text(value)); + return this; + } + + @Contract("_ -> this") + public Builder with(AdventurePlaceholders other) { + this.entries.putAll(other.asMap()); + return this; + } + + @Contract("_,_ -> this") + public Builder with(String key, Object value) { + this.entries.put(key, Component.text(String.valueOf(value))); + return this; + } + + public AdventurePlaceholders build() { + if (this.entries.isEmpty()) { + return EMPTY; + } + + return new AdventurePlaceholders(new LinkedHashMap<>(this.entries)); + } + } +} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/InvalidUsageHandlerImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/InvalidUsageHandlerImpl.java index b08ffac..9aaf8e3 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/InvalidUsageHandlerImpl.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/InvalidUsageHandlerImpl.java @@ -1,25 +1,27 @@ package com.github.imdmk.automessage.platform.litecommands.handler; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; +import com.github.imdmk.automessage.message.MessageService; import dev.rollczi.litecommands.handler.result.ResultHandlerChain; import dev.rollczi.litecommands.invalidusage.InvalidUsage; import dev.rollczi.litecommands.invalidusage.InvalidUsageHandler; import dev.rollczi.litecommands.invocation.Invocation; import dev.rollczi.litecommands.schematic.Schematic; import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; public final class InvalidUsageHandlerImpl implements InvalidUsageHandler { private final MessageService messageService; - public InvalidUsageHandlerImpl(@NotNull MessageService messageService) { - this.messageService = Validator.notNull(messageService, "messageService cannot be null"); + public InvalidUsageHandlerImpl(MessageService messageService) { + this.messageService = messageService; } @Override - public void handle(Invocation invocation, InvalidUsage result, ResultHandlerChain chain) { + public void handle( + Invocation invocation, + InvalidUsage result, + ResultHandlerChain chain + ) { final CommandSender sender = invocation.sender(); final Schematic schematic = result.getSchematic(); diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/MissingPermissionsHandlerImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/MissingPermissionsHandlerImpl.java index 5e261f7..ac95eeb 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/MissingPermissionsHandlerImpl.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/MissingPermissionsHandlerImpl.java @@ -1,24 +1,26 @@ package com.github.imdmk.automessage.platform.litecommands.handler; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; +import com.github.imdmk.automessage.message.MessageService; import dev.rollczi.litecommands.handler.result.ResultHandlerChain; import dev.rollczi.litecommands.invocation.Invocation; import dev.rollczi.litecommands.permission.MissingPermissions; import dev.rollczi.litecommands.permission.MissingPermissionsHandler; import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; public final class MissingPermissionsHandlerImpl implements MissingPermissionsHandler { private final MessageService messageService; - public MissingPermissionsHandlerImpl(@NotNull MessageService messageService) { - this.messageService = Validator.notNull(messageService, "messageService cannot be null"); + public MissingPermissionsHandlerImpl(MessageService messageService) { + this.messageService = messageService; } @Override - public void handle(Invocation invocation, MissingPermissions permissions, ResultHandlerChain chain) { + public void handle( + Invocation invocation, + MissingPermissions permissions, + ResultHandlerChain chain + ) { messageService.create() .viewer(invocation.sender()) .notice(n -> n.liteCommandsMessages.commandPermissionMissing()) diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/NoticeResultHandlerImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/NoticeResultHandlerImpl.java index ad8ac28..eed61bf 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/NoticeResultHandlerImpl.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/handler/NoticeResultHandlerImpl.java @@ -1,24 +1,26 @@ package com.github.imdmk.automessage.platform.litecommands.handler; import com.eternalcode.multification.notice.Notice; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; +import com.github.imdmk.automessage.message.MessageService; import dev.rollczi.litecommands.handler.result.ResultHandler; import dev.rollczi.litecommands.handler.result.ResultHandlerChain; import dev.rollczi.litecommands.invocation.Invocation; import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; public final class NoticeResultHandlerImpl implements ResultHandler { private final MessageService messageService; - public NoticeResultHandlerImpl(@NotNull MessageService messageService) { - this.messageService = Validator.notNull(messageService, "messageService cannot be null"); + public NoticeResultHandlerImpl(MessageService messageService) { + this.messageService = messageService; } @Override - public void handle(Invocation invocation, Notice notice, ResultHandlerChain chain) { + public void handle( + Invocation invocation, + Notice notice, + ResultHandlerChain chain + ) { messageService.send(invocation.sender(), n -> notice); } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/messages/LiteCommandsMessagesImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/messages/ENLiteCommandsMessages.java similarity index 98% rename from automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/messages/LiteCommandsMessagesImpl.java rename to automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/messages/ENLiteCommandsMessages.java index 3a43b20..a7b1362 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/messages/LiteCommandsMessagesImpl.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/litecommands/messages/ENLiteCommandsMessages.java @@ -4,7 +4,7 @@ import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; -public final class LiteCommandsMessagesImpl +public final class ENLiteCommandsMessages extends OkaeriConfig implements LiteCommandsMessages { diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/BukkitPluginLogger.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/BukkitPluginLogger.java index d85264c..a5bcd48 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/BukkitPluginLogger.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/BukkitPluginLogger.java @@ -1,114 +1,73 @@ package com.github.imdmk.automessage.platform.logger; -import com.github.imdmk.automessage.shared.validate.Validator; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; - import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; -/** - * Bukkit-specific implementation of {@link PluginLogger} delegating to a standard - * {@link java.util.logging.Logger} obtained from a Bukkit {@link Plugin}. - * - *

This class provides formatted and structured logging methods for common log levels - * (INFO, WARNING, DEBUG, SEVERE) with support for formatted messages and throwable logging.

- * - *

Design notes:

- *
    - *
  • Acts as a lightweight adapter to bridge the internal plugin logging interface with Bukkit’s logger.
  • - *
  • Formatting uses {@link String#format(Locale, String, Object...)} with {@link Locale#ROOT} to ensure locale safety.
  • - *
  • Supports overloaded methods for flexible log message creation, including formatted and exception-based variants.
  • - *
- * - *

Thread-safety: Delegates to the underlying {@link Logger}, which is thread-safe for concurrent use.

- * - * @see PluginLogger - * @see Plugin#getLogger() - * @see Logger - */ public final class BukkitPluginLogger implements PluginLogger { - /** Backing {@link java.util.logging.Logger} provided by Bukkit. */ private final Logger logger; - /** - * Creates a new {@code BukkitPluginLogger} wrapping an existing {@link Logger}. - * - * @param logger non-null backing logger instance - * @throws NullPointerException if {@code logger} is null - */ - public BukkitPluginLogger(@NotNull Logger logger) { - this.logger = Validator.notNull(logger, "logger"); - } - - /** - * Creates a new {@code BukkitPluginLogger} bound to the given Bukkit {@link Plugin}. - * - * @param plugin non-null Bukkit plugin instance - * @throws NullPointerException if {@code plugin} is null - */ - public BukkitPluginLogger(@NotNull Plugin plugin) { - this(plugin.getLogger()); + public BukkitPluginLogger(Logger logger) { + this.logger = logger; } @Override - public void info(@NotNull String message) { + public void info(String message) { logger.info(message); } @Override - public void info(@NotNull String message, @NotNull Object... args) { + public void info(String message, Object... args) { logger.log(Level.INFO, format(message, args)); } @Override - public void warn(@NotNull String message) { + public void warn(String message) { logger.warning(message); } @Override - public void warn(@NotNull Throwable throwable) { + public void warn(Throwable throwable) { logger.log(Level.WARNING, "A warning occurred, see stack trace for details.", throwable); } @Override - public void warn(@NotNull Throwable throwable, @NotNull String message, @NotNull Object... args) { + public void warn(Throwable throwable, String message, Object... args) { logger.log(Level.WARNING, format(message, args), throwable); } @Override - public void warn(@NotNull String message, @NotNull Object... args) { + public void warn(String message, Object... args) { logger.log(Level.WARNING, format(message, args)); } @Override - public void error(@NotNull Throwable throwable) { + public void error(Throwable throwable) { logger.log(Level.SEVERE, "An error occurred, see stack trace for details.", throwable); } @Override - public void error(@NotNull String message) { + public void error(String message) { logger.log(Level.SEVERE, message); } @Override - public void error(@NotNull String message, @NotNull Object... args) { + public void error(String message, Object... args) { logger.log(Level.SEVERE, format(message, args)); } @Override - public void error(@NotNull Throwable throwable, @NotNull String message) { + public void error(Throwable throwable, String message) { logger.log(Level.SEVERE, message, throwable); } @Override - public void error(@NotNull Throwable throwable, @NotNull String message, @NotNull Object... args) { + public void error(Throwable throwable, String message, Object... args) { logger.log(Level.SEVERE, format(message, args), throwable); } - private String format(String message, Object... args) { + private static String format(String message, Object... args) { return String.format(Locale.ROOT, message, args); } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/PluginLogger.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/PluginLogger.java index c7c33d4..93ae8ab 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/PluginLogger.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/logger/PluginLogger.java @@ -1,117 +1,20 @@ package com.github.imdmk.automessage.platform.logger; import org.intellij.lang.annotations.PrintFormat; -import org.jetbrains.annotations.NotNull; -/** - * Unified logging abstraction for the PlayTime plugin environment. - * - *

This interface defines a consistent logging API decoupled from the underlying - * logging backend (e.g., Bukkit’s {@link java.util.logging.Logger}, SLF4J, or a custom logger). - * It provides structured, formatted, and throwable-aware logging across multiple log levels.

- * - *

Design goals:

- *
    - *
  • Consistent logging interface across all plugin components.
  • - *
  • Support for message formatting with {@link String#format} syntax.
  • - *
  • Convenient overloads for attaching {@link Throwable}s and stack traces.
  • - *
  • Simple to implement for different backends (e.g., {@link BukkitPluginLogger}).
  • - *
- * - *

Thread-safety: Implementations are expected to be thread-safe and safe - * for concurrent use across async or scheduled tasks.

- * - * @see BukkitPluginLogger - * @see java.util.logging.Logger - */ public interface PluginLogger { - /** - * Logs a general informational message. - * - * @param message message to log (non-null) - */ - void info(@NotNull String message); + void info(String message); + void info(@PrintFormat String message, Object... args); - /** - * Logs a formatted informational message. - * - * @param message format string using {@link String#format} syntax (non-null) - * @param args arguments to format (non-null) - */ - void info(@NotNull @PrintFormat String message, @NotNull Object... args); + void warn(String message); + void warn(@PrintFormat String message, Object... args); + void warn(Throwable throwable); + void warn(Throwable throwable, @PrintFormat String message, Object... args); - /** - * Logs a warning message, indicating a non-fatal issue. - * - * @param message warning message (non-null) - */ - void warn(@NotNull String message); - - /** - * Logs a warning caused by a {@link Throwable}, typically without rethrowing it. - * - * @param throwable the exception or error (non-null) - */ - void warn(@NotNull Throwable throwable); - - /** - * Logs a formatted warning message with an associated {@link Throwable}. - * - * @param throwable cause of the warning (non-null) - * @param message format string (non-null) - * @param args format arguments (non-null) - */ - void warn(@NotNull Throwable throwable, - @NotNull @PrintFormat String message, - @NotNull Object... args); - - /** - * Logs a formatted warning message. - * - * @param message format string (non-null) - * @param args format arguments (non-null) - */ - void warn(@NotNull @PrintFormat String message, @NotNull Object... args); - - /** - * Logs an error with a throwable stack trace. - * - * @param throwable exception or error to log (non-null) - */ - void error(@NotNull Throwable throwable); - - /** - * Logs an error message at the highest severity level. - * - * @param message message to log (non-null) - */ - void error(@NotNull String message); - - /** - * Logs a formatted error message. - * - * @param message format string (non-null) - * @param args format arguments (non-null) - */ - void error(@NotNull @PrintFormat String message, @NotNull Object... args); - - /** - * Logs an error message with the given {@link Throwable}. - * - * @param throwable cause of the error (non-null) - * @param message unformatted message text (non-null) - */ - void error(@NotNull Throwable throwable, @NotNull String message); - - /** - * Logs a formatted error message with the given {@link Throwable}. - * - * @param throwable cause of the error (non-null) - * @param message format string (non-null) - * @param args format arguments (non-null) - */ - void error(@NotNull Throwable throwable, - @NotNull @PrintFormat String message, - @NotNull Object... args); + void error(String message); + void error(@PrintFormat String message, Object... args); + void error(Throwable throwable); + void error(Throwable throwable, String message); + void error(Throwable throwable, @PrintFormat String message, Object... args); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/metrics/MetricsService.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/metrics/MetricsService.java new file mode 100644 index 0000000..d7c66b2 --- /dev/null +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/metrics/MetricsService.java @@ -0,0 +1,18 @@ +package com.github.imdmk.automessage.platform.metrics; + +import org.bstats.bukkit.Metrics; +import org.bukkit.plugin.Plugin; + +public final class MetricsService { + + private static final int METRICS_ID = 19487; + private final Metrics metrics; + + public MetricsService(Plugin plugin) { + this.metrics = new Metrics(plugin, METRICS_ID); + } + + public void shutdown() { + this.metrics.shutdown(); + } +} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/BukkitTaskScheduler.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/BukkitTaskScheduler.java index d2cae1d..149557f 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/BukkitTaskScheduler.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/BukkitTaskScheduler.java @@ -1,123 +1,68 @@ package com.github.imdmk.automessage.platform.scheduler; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; -import org.jetbrains.annotations.NotNull; import java.time.Duration; -/** - * {@link TaskScheduler} implementation backed by the Bukkit {@link BukkitScheduler}. - * - *

Provides a clean, Duration-based API for scheduling synchronous and asynchronous - * tasks, including delayed and repeating executions.

- * - *

All time values are expressed using {@link Duration} and internally converted - * to Minecraft ticks (1 tick = 50 ms).

- * - *

Thread-safety: This class is thread-safe. It holds only immutable - * references to {@link Plugin} and {@link BukkitScheduler}.

- */ public final class BukkitTaskScheduler implements TaskScheduler { - /** Number of milliseconds per Minecraft tick. */ private static final long MILLIS_PER_TICK = 50L; private final Plugin plugin; private final BukkitScheduler scheduler; - public BukkitTaskScheduler(@NotNull Plugin plugin, @NotNull BukkitScheduler scheduler) { - this.plugin = Validator.notNull(plugin, "plugin"); - this.scheduler = Validator.notNull(scheduler, "scheduler"); + public BukkitTaskScheduler(Plugin plugin, BukkitScheduler scheduler) { + this.plugin = plugin; + this.scheduler = scheduler; } @Override - public @NotNull BukkitTask runSync(@NotNull Runnable runnable) { - Validator.notNull(runnable, "runnable cannot be null"); + public BukkitTask runSync(Runnable runnable) { return scheduler.runTask(plugin, runnable); } @Override - public @NotNull BukkitTask runSync(@NotNull PluginTask task) { - Validator.notNull(task, "task cannot be null"); - return scheduler.runTask(plugin, task); - } - - @Override - public @NotNull BukkitTask runAsync(@NotNull Runnable runnable) { - Validator.notNull(runnable, "runnable cannot be null"); + public BukkitTask runAsync(Runnable runnable) { return scheduler.runTaskAsynchronously(plugin, runnable); } @Override - public @NotNull BukkitTask runAsync(@NotNull PluginTask task) { - Validator.notNull(task, "task cannot be null"); - return scheduler.runTaskAsynchronously(plugin, task); - } - - @Override - public @NotNull BukkitTask runLaterAsync(@NotNull Runnable runnable, @NotNull Duration delay) { - Validator.notNull(runnable, "runnable cannot be null"); - Validator.notNull(delay, "delay cannot be null"); + public BukkitTask runLaterAsync(Runnable runnable, Duration delay) { return scheduler.runTaskLaterAsynchronously(plugin, runnable, toTicks(delay)); } @Override - public @NotNull BukkitTask runLaterAsync(@NotNull PluginTask task) { - Validator.notNull(task, "task cannot be null"); - return runLaterAsync(task, task.delay()); - } - - @Override - public @NotNull BukkitTask runLaterSync(@NotNull Runnable runnable, @NotNull Duration delay) { - Validator.notNull(runnable, "runnable cannot be null"); - Validator.notNull(delay, "delay cannot be null"); + public BukkitTask runLaterSync(Runnable runnable, Duration delay) { return scheduler.runTaskLater(plugin, runnable, toTicks(delay)); } @Override - public @NotNull BukkitTask runLaterSync(@NotNull PluginTask task) { - Validator.notNull(task, "task cannot be null"); - return runLaterSync(task, task.delay()); - } - - @Override - public @NotNull BukkitTask runTimerSync( - @NotNull Runnable runnable, - @NotNull Duration delay, - @NotNull Duration period + public BukkitTask runTimerSync( + Runnable runnable, + Duration delay, + Duration period ) { - Validator.notNull(runnable, "runnable cannot be null"); - Validator.notNull(delay, "delay cannot be null"); - Validator.notNull(period, "period cannot be null"); - return scheduler.runTaskTimer(plugin, runnable, toTicks(delay), toTicks(period)); } @Override - public @NotNull BukkitTask runTimerSync(@NotNull PluginTask task) { - Validator.notNull(task, "task cannot be null"); + public BukkitTask runTimerSync(PluginTask task) { return runTimerSync(task, task.delay(), task.period()); } @Override - public @NotNull BukkitTask runTimerAsync( - @NotNull Runnable runnable, - @NotNull Duration delay, - @NotNull Duration period + public BukkitTask runTimerAsync( + Runnable runnable, + Duration delay, + Duration period ) { - Validator.notNull(runnable, "runnable cannot be null"); - Validator.notNull(delay, "delay cannot be null"); - Validator.notNull(period, "period cannot be null"); - return scheduler.runTaskTimerAsynchronously(plugin, runnable, toTicks(delay), toTicks(period)); } @Override - public @NotNull BukkitTask runTimerAsync(@NotNull PluginTask task) { - Validator.notNull(task, "task cannot be null"); + public BukkitTask runTimerAsync(PluginTask task) { return runTimerAsync(task, task.delay(), task.period()); } @@ -131,18 +76,8 @@ public void shutdown() { scheduler.cancelTasks(plugin); } - /** - * Converts the given duration to Minecraft ticks. - *

- * Fractions are truncated. Negative durations return {@code 0}. - * - * @param duration duration to convert; must not be null - * @return number of ticks (≥ 0) - */ - private static int toTicks(@NotNull Duration duration) { - Validator.notNull(duration, "duration cannot be null"); - - long ticks = duration.toMillis() / MILLIS_PER_TICK; + private static int toTicks(Duration duration) { + final long ticks = duration.toMillis() / MILLIS_PER_TICK; return ticks <= 0 ? 0 : (int) ticks; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/PluginTask.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/PluginTask.java index 73f8a28..a12f818 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/PluginTask.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/PluginTask.java @@ -2,61 +2,12 @@ import java.time.Duration; -/** - * Represents a declarative task definition used by the {@link TaskScheduler}. - * - *

A {@code PluginTask} bundles together:

- *
    - *
  • the executable logic ({@link #run()}),
  • - *
  • a delay before the first execution ({@link #delay()}),
  • - *
  • an optional repeating period ({@link #period()}).
  • - *
- * - *

Instances are consumed by scheduler methods that accept {@link PluginTask}, - * allowing tasks to be declared as self-contained objects instead of passing - * raw parameters into every scheduling call.

- * - *

Repeating vs. non-repeating:

- *
    - *
  • If {@link #period()} returns {@code Duration.ZERO}, the task is executed once after the delay.
  • - *
  • If {@link #period()} is greater than zero, the task is executed repeatedly.
  • - *
- * - *

Threading: Whether the task runs synchronously or asynchronously - * depends solely on the {@link TaskScheduler} method used (e.g., {@code runTimerSync}, {@code runTimerAsync}).

- */ public interface PluginTask extends Runnable { - /** - * The task logic to be executed by the scheduler. - *

- * Called either once (if {@link #period()} is zero) or repeatedly - * (if {@link #period()} is greater than zero), depending on how - * the task is scheduled. - *

- */ @Override void run(); - /** - * Returns the delay before the first execution. - * - *

A zero delay means the task should run immediately.

- * - * @return the initial delay, never {@code null} - */ Duration delay(); - - /** - * Returns the repeat period for this task. - * - *

If this returns {@code Duration.ZERO}, the task is treated as - * a one-shot task and will not repeat after the first execution.

- * - *

If the value is greater than zero, the scheduler executes the - * task repeatedly with this interval.

- * - * @return the repeat interval, never {@code null} - */ Duration period(); + } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/TaskScheduler.java b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/TaskScheduler.java index da8b310..bbd23cc 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/TaskScheduler.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/platform/scheduler/TaskScheduler.java @@ -1,152 +1,24 @@ package com.github.imdmk.automessage.platform.scheduler; import org.bukkit.scheduler.BukkitTask; -import org.jetbrains.annotations.NotNull; import java.time.Duration; -/** - * Abstraction layer over the Bukkit {@link org.bukkit.scheduler.BukkitScheduler}, - * providing a clean, consistent API for scheduling synchronous and asynchronous tasks - * using either raw {@link Runnable} instances or declarative {@link PluginTask} objects. - * - *

Threading rules:

- *
    - *
  • Sync methods execute on the main server thread.
  • - *
  • Async methods execute off the main thread and must not access Bukkit API objects that require sync.
  • - *
- * - *

Delay & period units: All {@code Duration} values are converted to - * Minecraft ticks (1 tick = 50ms).

- * - *

PluginTask usage: All overloads accepting {@link PluginTask} - * automatically use the task's declared delay and period.

- */ public interface TaskScheduler { - /** - * Executes the given runnable immediately on the main server thread. - * - * @param runnable non-null logic to execute - * @return the task handle - */ - BukkitTask runSync(@NotNull Runnable runnable); + BukkitTask runSync(Runnable runnable); + BukkitTask runAsync(Runnable runnable); - /** - * Executes the given {@link PluginTask} immediately on the main server thread. - * - *

{@link PluginTask#delay()} and {@link PluginTask#period()} are ignored; - * this method always runs instantly.

- * - * @param task non-null task instance - * @return the task handle - */ - BukkitTask runSync(@NotNull PluginTask task); + BukkitTask runLaterAsync(Runnable runnable, Duration delay); + BukkitTask runLaterSync(Runnable runnable, Duration delay); - /** - * Executes the given runnable immediately on a separate thread. - * - * @param runnable non-null logic to execute asynchronously - * @return the task handle - */ - BukkitTask runAsync(@NotNull Runnable runnable); + BukkitTask runTimerSync(Runnable runnable, Duration delay, Duration period); + BukkitTask runTimerSync(PluginTask task); - /** - * Executes the given {@link PluginTask} immediately on a separate thread. - * - *

{@link PluginTask#delay()} and {@link PluginTask#period()} are ignored; - * this method always runs instantly.

- * - * @param task non-null task instance - * @return the task handle - */ - BukkitTask runAsync(@NotNull PluginTask task); + BukkitTask runTimerAsync(Runnable runnable, Duration delay, Duration period); + BukkitTask runTimerAsync(PluginTask task); - /** - * Executes the runnable asynchronously after the given delay. - * - * @param runnable task logic - * @param delay delay before execution (converted to ticks) - * @return the task handle - */ - BukkitTask runLaterAsync(@NotNull Runnable runnable, @NotNull Duration delay); - - /** - * Executes the {@link PluginTask} asynchronously after {@link PluginTask#delay()}. - * - *

Runs once unless {@link PluginTask#period()} is non-zero.

- * - * @param task task definition - * @return the task handle - */ - BukkitTask runLaterAsync(@NotNull PluginTask task); - - /** - * Executes the runnable synchronously after the given delay. - * - * @param runnable task logic - * @param delay delay before execution (converted to ticks) - * @return the task handle - */ - BukkitTask runLaterSync(@NotNull Runnable runnable, @NotNull Duration delay); - - /** - * Executes the {@link PluginTask} synchronously after {@link PluginTask#delay()}. - * - *

Runs once unless {@link PluginTask#period()} is non-zero.

- * - * @param task task definition - * @return the task handle - */ - BukkitTask runLaterSync(@NotNull PluginTask task); - - /** - * Schedules a synchronous repeating task. - * - * @param runnable logic to execute - * @param delay initial delay before the first run - * @param period time between runs - * @return the created repeating task - */ - BukkitTask runTimerSync(@NotNull Runnable runnable, @NotNull Duration delay, @NotNull Duration period); - - /** - * Schedules a synchronous repeating {@link PluginTask} using its delay/period. - * - * @param task task definition - * @return the created repeating task - */ - BukkitTask runTimerSync(@NotNull PluginTask task); - - /** - * Schedules an asynchronous repeating task. - * - * @param runnable logic to execute - * @param delay initial delay before the first execution - * @param period time between consecutive executions - * @return the created repeating task - */ - BukkitTask runTimerAsync(@NotNull Runnable runnable, @NotNull Duration delay, @NotNull Duration period); - - /** - * Schedules an asynchronous repeating {@link PluginTask} using its delay/period. - * - * @param task task definition - * @return the created repeating task - */ - BukkitTask runTimerAsync(@NotNull PluginTask task); - - /** - * Cancels a scheduled task via its Bukkit ID. - * - * @param taskId scheduler task ID - */ void cancelTask(int taskId); - - /** - * Cancels all tasks created for the associated plugin. - * - *

Called during plugin shutdown.

- */ void shutdown(); + } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessage.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessage.java index 341a39f..42f265b 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessage.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessage.java @@ -2,24 +2,21 @@ import com.eternalcode.multification.notice.Notice; import com.github.imdmk.automessage.scheduled.audience.rule.AudienceRule; -import com.github.imdmk.automessage.shared.validate.Validator; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import java.util.List; +import java.util.Objects; public record ScheduledMessage( - @NotNull String name, - @NotNull @Unmodifiable List notices, - @NotNull @Unmodifiable List rules) { + String name, + @Unmodifiable List notices, + @Unmodifiable List rules) { public ScheduledMessage { - Validator.notNull(name, "name cannot be null"); - Validator.notNull(notices, "notices cannot be null"); - Validator.notNull(rules, "rules cannot be null"); + Objects.requireNonNull(name, "name"); if (notices.isEmpty()) { - throw new IllegalArgumentException("ScheduledMessage must contain at least one Notice"); + throw new IllegalArgumentException("notices must contains at least one notice"); } notices = List.copyOf(notices); diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageBuilder.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageBuilder.java index fc6fcfc..19a8beb 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageBuilder.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageBuilder.java @@ -2,8 +2,6 @@ import com.eternalcode.multification.notice.Notice; import com.github.imdmk.automessage.scheduled.audience.rule.AudienceRule; -import com.github.imdmk.automessage.shared.validate.Validator; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -11,6 +9,7 @@ public final class ScheduledMessageBuilder { private String name; + private final List notices = new ArrayList<>(); private final List rules = new ArrayList<>(); @@ -18,44 +17,40 @@ public static ScheduledMessageBuilder create() { return new ScheduledMessageBuilder(); } - public @NotNull ScheduledMessageBuilder name(@NotNull String name) { - this.name = Validator.notNull(name, "name"); + public ScheduledMessageBuilder name(String name) { + this.name = name; return this; } - public @NotNull ScheduledMessageBuilder addNotice(@NotNull Notice notice) { - this.notices.add(Validator.notNull(notice, "notice")); + public ScheduledMessageBuilder addNotice(Notice notice) { + this.notices.add(notice); return this; } - public @NotNull ScheduledMessageBuilder addNotices(@NotNull List notices) { - Validator.notNull(notices, "notices"); - notices.forEach(n -> this.notices.add(Validator.notNull(n, "notice element"))); + public ScheduledMessageBuilder addNotices(List notices) { + this.notices.addAll(notices); return this; } - public @NotNull ScheduledMessageBuilder addNotices(@NotNull Notice... notices) { + public ScheduledMessageBuilder addNotices(Notice... notices) { return addNotices(List.of(notices)); } - public @NotNull ScheduledMessageBuilder addRule(@NotNull AudienceRule rule) { - this.rules.add(Validator.notNull(rule, "rule")); + public ScheduledMessageBuilder addRule(AudienceRule rule) { + this.rules.add(rule); return this; } - public @NotNull ScheduledMessageBuilder addRules(@NotNull List rules) { - Validator.notNull(rules, "rules"); - rules.forEach(r -> this.rules.add(Validator.notNull(r, "rule element"))); + public ScheduledMessageBuilder addRules(List rules) { + this.rules.addAll(rules); return this; } - public @NotNull ScheduledMessageBuilder addRules(@NotNull AudienceRule... rules) { + public ScheduledMessageBuilder addRules(AudienceRule... rules) { return addRules(List.of(rules)); } - public @NotNull ScheduledMessage build() { - Validator.notNull(this.name, "name is required"); - + public ScheduledMessage build() { return new ScheduledMessage( this.name, List.copyOf(this.notices), diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageSerializer.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageSerializer.java index 02fff8c..e47bb6f 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageSerializer.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessageSerializer.java @@ -18,14 +18,14 @@ public boolean supports(@NotNull Class type) { } @Override - public void serialize(@NotNull ScheduledMessage notice, @NotNull SerializationData data, @NotNull GenericsDeclaration generics) { + public void serialize(ScheduledMessage notice, SerializationData data, @NotNull GenericsDeclaration generics) { data.add("name", notice.name(), String.class); data.addCollection("notices", notice.notices(), Notice.class); data.addCollection("rules", notice.rules(), AudienceRule.class); } @Override - public ScheduledMessage deserialize(@NotNull DeserializationData data, @NotNull GenericsDeclaration generics) { + public ScheduledMessage deserialize(DeserializationData data, @NotNull GenericsDeclaration generics) { String name = data.get("name", String.class); List notices = data.getAsList("notices", Notice.class); List rules = data.getAsList("rules", AudienceRule.class); diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessagesConfig.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessagesConfig.java index 75f47ea..0f571f8 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessagesConfig.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/ScheduledMessagesConfig.java @@ -12,7 +12,6 @@ import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; -import org.jetbrains.annotations.NotNull; import java.time.Duration; import java.util.List; @@ -190,7 +189,7 @@ public final class ScheduledMessagesConfig extends ConfigSection { ); @Override - public @NotNull OkaeriSerdesPack getSerdesPack() { + public OkaeriSerdesPack getSerdesPack() { return registry -> { registry.register(new ScheduledMessageSerializer()); registry.register(new AudienceRuleSerializer()); @@ -199,7 +198,7 @@ public final class ScheduledMessagesConfig extends ConfigSection { } @Override - public @NotNull String getFileName() { + public String getFileName() { return "scheduledMessages.yml"; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilter.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilter.java index c15e357..13140a7 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilter.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilter.java @@ -2,34 +2,12 @@ import com.github.imdmk.automessage.scheduled.ScheduledMessage; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -/** - * Determines whether a given player is allowed to receive a specific {@link ScheduledMessage}. - * - *

Audience filters enable selective delivery based on rules such as permissions, - * groups, worlds, conditions, or any custom logic implemented in {@link AudienceFilterImpl}.

- */ public interface AudienceFilter { - /** - * Evaluates whether the given player should receive the specified scheduled message. - * - * @param player the player being considered (never null) - * @param message the scheduled message evaluated against the player (never null) - * @return true if the player is allowed to receive the message; false otherwise - */ - boolean allows(@NotNull Player player, @NotNull ScheduledMessage message); + boolean allows(Player player, ScheduledMessage message); - /** - * Creates the default audience filter used by the plugin. - * - *

The default implementation respects all {@link com.github.imdmk.automessage.scheduled.audience.rule.AudienceRule} - * entries declared on the scheduled message. It does not introduce any implicit filtering.

- * - * @return a new default {@link AudienceFilter} instance - */ - static AudienceFilter createDefault() { - return new AudienceFilterImpl(); + static AudienceFilter ruleFilter() { + return new RuleAudienceFilter(); } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilterImpl.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilterImpl.java deleted file mode 100644 index 845729e..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/AudienceFilterImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.github.imdmk.automessage.scheduled.audience.filter; - -import com.github.imdmk.automessage.scheduled.ScheduledMessage; -import com.github.imdmk.automessage.shared.validate.Validator; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -final class AudienceFilterImpl implements AudienceFilter { - - @Override - public boolean allows(@NotNull Player player, @NotNull ScheduledMessage message) { - Validator.notNull(player, "player"); - Validator.notNull(message, "message"); - - return message.rules().stream() - .allMatch(rule -> rule.test(player)); - } -} - diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/RuleAudienceFilter.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/RuleAudienceFilter.java new file mode 100644 index 0000000..3a30b47 --- /dev/null +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/filter/RuleAudienceFilter.java @@ -0,0 +1,15 @@ +package com.github.imdmk.automessage.scheduled.audience.filter; + +import com.github.imdmk.automessage.scheduled.ScheduledMessage; +import org.bukkit.entity.Player; + +final class RuleAudienceFilter implements AudienceFilter { + + @Override + public boolean allows(Player player, ScheduledMessage message) { + return message.rules() + .stream() + .allMatch(rule -> rule.test(player)); + } +} + diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceGroupRule.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceGroupRule.java index dde58f8..9e9b42d 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceGroupRule.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceGroupRule.java @@ -1,25 +1,19 @@ package com.github.imdmk.automessage.scheduled.audience.rule; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -public record AudienceGroupRule(@NotNull String group) implements AudienceRule { +public record AudienceGroupRule(String group) implements AudienceRule { private static final String GROUP_PREFIX = "group."; - public AudienceGroupRule { - Validator.notNull(group, "group"); - } - @Override - public boolean test(@NotNull Player player) { - String permission = GROUP_PREFIX + group; + public boolean test(Player player) { + final String permission = GROUP_PREFIX + group; return player.hasPermission(permission); } @Override - public @NotNull Type type() { + public Type type() { return Type.GROUP; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudiencePermissionRule.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudiencePermissionRule.java index e0ca307..c1b561b 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudiencePermissionRule.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudiencePermissionRule.java @@ -1,22 +1,16 @@ package com.github.imdmk.automessage.scheduled.audience.rule; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -public record AudiencePermissionRule(@NotNull String permission) implements AudienceRule { - - public AudiencePermissionRule { - Validator.notNull(permission, "permission"); - } +public record AudiencePermissionRule(String permission) implements AudienceRule { @Override - public boolean test(@NotNull Player player) { + public boolean test(Player player) { return player.hasPermission(permission); } @Override - public @NotNull Type type() { + public Type type() { return Type.PERMISSION; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRule.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRule.java index 2345dab..5e0e283 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRule.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRule.java @@ -1,61 +1,24 @@ package com.github.imdmk.automessage.scheduled.audience.rule; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -/** - * Represents a rule used to determine whether a player is eligible - * to receive a particular scheduled message. - * - *

Each rule implements a single boolean check and is composable. - * The dispatcher evaluates all rules attached to a message; if any rule - * returns {@code false}, the message is not sent to the player.

- * - *

This interface is sealed: only built-in rule types are permitted.

- */ public sealed interface AudienceRule permits AudiencePermissionRule, AudienceGroupRule { - /** - * Creates a rule that allows only players belonging to a specific group. - * - * @param group the required group identifier (not null) - * @return a new group-based audience rule - */ - static @NotNull AudienceGroupRule group(@NotNull String group) { + static AudienceGroupRule group(String group) { return new AudienceGroupRule(group); } - /** - * Creates a rule that allows only players having a specific permission node. - * - * @param permission the required permission (not null) - * @return a new permission-based audience rule - */ - static @NotNull AudiencePermissionRule permission(@NotNull String permission) { + static AudiencePermissionRule permission(String permission) { return new AudiencePermissionRule(permission); } - /** - * Evaluates whether the player satisfies this rule. - * - * @param player the player being evaluated (never null) - * @return true if the rule allows the player; false otherwise - */ - boolean test(@NotNull Player player); + boolean test(Player player); - /** - * Enumeration of supported audience rule types. - */ enum Type { PERMISSION, GROUP } - /** - * Returns the type of this rule. - * - * @return the rule type (never null) - */ - @NotNull Type type(); + Type type(); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRuleSerializer.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRuleSerializer.java index 8bdbb58..0c7e94a 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRuleSerializer.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/audience/rule/AudienceRuleSerializer.java @@ -14,17 +14,17 @@ public boolean supports(@NotNull Class type) { } @Override - public void serialize(@NotNull AudienceRule rule, @NotNull SerializationData data, @NotNull GenericsDeclaration generics) { + public void serialize(AudienceRule rule, SerializationData data, @NotNull GenericsDeclaration generics) { data.add("type", rule.type(), AudienceRule.Type.class); switch (rule) { - case AudienceGroupRule audienceGroupRule -> data.add("group", audienceGroupRule.group(), String.class); - case AudiencePermissionRule audiencePermissionRule -> data.add("permission", audiencePermissionRule.permission(), String.class); + case AudienceGroupRule group -> data.add("group", group.group(), String.class); + case AudiencePermissionRule permission -> data.add("permission", permission.permission(), String.class); } } @Override - public AudienceRule deserialize(@NotNull DeserializationData data, @NotNull GenericsDeclaration generics) { + public AudienceRule deserialize(DeserializationData data, @NotNull GenericsDeclaration generics) { final AudienceRule.Type type = data.get("type", AudienceRule.Type.class); return switch (type) { diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchFilteredTarget.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchFilteredTarget.java index f3a938f..523f8b6 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchFilteredTarget.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchFilteredTarget.java @@ -1,30 +1,17 @@ package com.github.imdmk.automessage.scheduled.dispatcher; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.function.Predicate; -/** - * Dispatch target representing a collection of players filtered by a predicate. - * - *

Filtering is performed on each call to {@link #recipients()}, ensuring the - * result always reflects the current online player state and rule logic.

- */ public record DispatchFilteredTarget( - @NotNull Collection players, - @NotNull Predicate predicate + Collection players, + Predicate predicate ) implements DispatchTarget { - public DispatchFilteredTarget { - Validator.notNull(players, "players cannot be null"); - Validator.notNull(predicate, "predicate cannot be null"); - } - @Override - public @NotNull Collection recipients() { + public Collection recipients() { return players.stream() .filter(predicate) .toList(); // safe: creates an immutable snapshot view diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchPlayersTarget.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchPlayersTarget.java index 4d4aae5..e9f5c81 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchPlayersTarget.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchPlayersTarget.java @@ -1,27 +1,15 @@ package com.github.imdmk.automessage.scheduled.dispatcher; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import java.util.Collection; -/** - * Simple dispatch target representing a predefined collection of recipient players. - * - *

This implementation performs no filtering or transformation. - * The provided collection is used as-is when dispatching messages.

- */ public record DispatchPlayersTarget( - @NotNull Collection players + Collection players ) implements DispatchTarget { - public DispatchPlayersTarget { - Validator.notNull(players, "players cannot be null"); - } - @Override - public @NotNull Collection recipients() { + public Collection recipients() { return players; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchTarget.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchTarget.java index 321402f..4fbba5f 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchTarget.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/DispatchTarget.java @@ -1,68 +1,26 @@ package com.github.imdmk.automessage.scheduled.dispatcher; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.List; import java.util.function.Predicate; -/** - * Represents a group of players to whom a scheduled message should be dispatched. - * - *

This abstraction allows the dispatcher to target:

- *
    - *
  • a single player,
  • - *
  • a fixed collection of players,
  • - *
  • or a dynamically filtered subset of players.
  • - *
- * - *

Implementations are expected to be immutable and lightweight.

- */ public interface DispatchTarget { - /** - * Returns the collection of players who should receive the message. - *

This method never returns null, but may return an empty collection.

- * - * @return a non-null collection of target recipients - */ - @NotNull Collection recipients(); + Collection recipients(); - /** - * Creates a dispatch target consisting of a single player. - * - * @param player a non-null player - * @return a dispatch target containing exactly this player - */ - static @NotNull DispatchTarget player(@NotNull Player player) { + static DispatchTarget player(Player player) { return new DispatchPlayersTarget(List.of(player)); } - /** - * Creates a dispatch target from a provided collection of players. - * - * @param players a non-null collection of players - * @return a dispatch target for these players - */ - static @NotNull DispatchTarget players(@NotNull Collection players) { + static DispatchTarget players(Collection players) { return new DispatchPlayersTarget(players); } - /** - * Creates a dispatch target based on a collection of players filtered by a predicate. - * - *

The filter is evaluated lazily by the target implementation whenever - * {@link #recipients()} is invoked. This allows the dispatcher to handle - * dynamic state changes (permissions, groups, world, AFK status, etc.).

- * - * @param players a non-null base collection of players - * @param filter a non-null predicate used to determine eligibility - * @return a filtered dispatch target - */ - static @NotNull DispatchTarget filtered( - @NotNull Collection players, - @NotNull Predicate filter + static DispatchTarget filtered( + Collection players, + Predicate filter ) { return new DispatchFilteredTarget(players, filter); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcher.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcher.java index c0af866..6a8a334 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcher.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcher.java @@ -1,83 +1,54 @@ package com.github.imdmk.automessage.scheduled.dispatcher; import com.eternalcode.multification.notice.Notice; +import com.github.imdmk.automessage.message.MessageService; import com.github.imdmk.automessage.scheduled.ScheduledMessage; import com.github.imdmk.automessage.scheduled.audience.filter.AudienceFilter; import com.github.imdmk.automessage.scheduled.selector.MessageSelector; -import com.github.imdmk.automessage.shared.message.MessageService; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import java.util.List; -import java.util.Optional; import java.util.function.Supplier; -/** - * Coordinates selecting and dispatching scheduled messages to an audience. - * - *

This class is stateless and thread-safe under the assumption that: - *

    - *
  • {@link MessageSelector} is thread-safe or externally synchronized.
  • - *
  • {@link Supplier} provides a thread-safe messages source.
  • - *
- *

- */ public final class MessageDispatcher { private final MessageService messageService; private final MessageSelector selector; private final AudienceFilter filter; - private final Supplier> messagesSupplier; + private final Supplier> messages; public MessageDispatcher( - @NotNull MessageService messageService, - @NotNull MessageSelector selector, - @NotNull AudienceFilter filter, - @NotNull Supplier> messagesSupplier + MessageService messageService, + MessageSelector selector, + AudienceFilter filter, + Supplier> messages ) { - this.messageService = Validator.notNull(messageService, "messageService"); - this.selector = Validator.notNull(selector, "selector"); - this.filter = Validator.notNull(filter, "filter"); - this.messagesSupplier = Validator.notNull(messagesSupplier, "messagesSupplier"); + this.messageService = messageService; + this.selector = selector; + this.filter = filter; + this.messages = messages; } - /** - * Selects the next scheduled message and dispatches it to the target audience. - * The selector index is automatically advanced. - */ - public void dispatchNext(@NotNull DispatchTarget target) { + public void dispatchNext(DispatchTarget target) { dispatchNext(target, true); } - /** - * Selects the next scheduled message and dispatches it to the provided audience. - * - * @param target the recipients wrapper - * @param advanceSelectorIndex whether the selector should advance its internal index - */ public void dispatchNext( - @NotNull DispatchTarget target, + DispatchTarget target, boolean advanceSelectorIndex ) { - final List messages = messagesSupplier.get(); + final List messages = this.messages.get(); if (messages.isEmpty()) { return; } - final Optional next = selector.selectNext(messages, advanceSelectorIndex); - next.ifPresent(message -> dispatch(message, target)); + selector.selectNext(messages, advanceSelectorIndex) + .ifPresent(message -> dispatch(message, target)); } - /** - * Dispatches a specific message to all players permitted by the audience filter. - * - * @param message the message to send - * @param target the target audience - */ public void dispatch( - @NotNull ScheduledMessage message, - @NotNull DispatchTarget target + ScheduledMessage message, + DispatchTarget target ) { for (final Player player : target.recipients()) { if (filter.allows(player, message)) { @@ -86,12 +57,9 @@ public void dispatch( } } - /** - * Sends all message notices to a single player asynchronously. - */ private void sendToPlayer( - @NotNull Player player, - @NotNull ScheduledMessage message + Player player, + ScheduledMessage message ) { for (final Notice notice : message.notices()) { messageService.create() diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherConfig.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherConfig.java index 3b93fdb..9143b7d 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherConfig.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherConfig.java @@ -5,7 +5,6 @@ import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.annotation.Header; import eu.okaeri.configs.serdes.OkaeriSerdesPack; -import org.jetbrains.annotations.NotNull; import java.time.Duration; @@ -79,12 +78,12 @@ public boolean isEnabled() { } @Override - public @NotNull OkaeriSerdesPack getSerdesPack() { + public OkaeriSerdesPack getSerdesPack() { return registry -> {}; } @Override - public @NotNull String getFileName() { + public String getFileName() { return "messagesDispatcher.yml"; } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherTask.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherTask.java index fc554b1..5a08e14 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherTask.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/dispatcher/MessageDispatcherTask.java @@ -1,10 +1,8 @@ package com.github.imdmk.automessage.scheduled.dispatcher; import com.github.imdmk.automessage.platform.scheduler.PluginTask; -import com.github.imdmk.automessage.shared.validate.Validator; import org.bukkit.Server; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; import java.time.Duration; import java.util.Collection; @@ -16,13 +14,13 @@ public final class MessageDispatcherTask implements PluginTask { private final MessageDispatcher messageDispatcher; public MessageDispatcherTask( - @NotNull Server server, - @NotNull MessageDispatcherConfig dispatcherConfig, - @NotNull MessageDispatcher messageDispatcher + Server server, + MessageDispatcherConfig dispatcherConfig, + MessageDispatcher messageDispatcher ) { - this.server = Validator.notNull(server, "server"); - this.dispatcherConfig = Validator.notNull(dispatcherConfig, "dispatcherConfig"); - this.messageDispatcher = Validator.notNull(messageDispatcher, "messageDispatcher"); + this.server = server; + this.dispatcherConfig = dispatcherConfig; + this.messageDispatcher = messageDispatcher; } @Override @@ -31,12 +29,12 @@ public void run() { return; } - Collection onlinePlayers = server.getOnlinePlayers(); + final Collection onlinePlayers = server.getOnlinePlayers(); if (onlinePlayers.isEmpty()) { return; } - DispatchTarget target = DispatchTarget.players(onlinePlayers); + final DispatchTarget target = DispatchTarget.players(onlinePlayers); messageDispatcher.dispatchNext(target); } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelector.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelector.java index ebdd057..c2cc274 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelector.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelector.java @@ -1,16 +1,15 @@ package com.github.imdmk.automessage.scheduled.selector; import com.github.imdmk.automessage.scheduled.ScheduledMessage; -import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Optional; public interface MessageSelector { - Optional selectNext(@NotNull List messages, boolean advanceIndex); + Optional selectNext(List messages, boolean advanceIndex); - default Optional selectNext(@NotNull List messages) { + default Optional selectNext(List messages) { return selectNext(messages, true); } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelectorFactory.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelectorFactory.java index 5a2c862..08e9158 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelectorFactory.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/MessageSelectorFactory.java @@ -1,14 +1,12 @@ package com.github.imdmk.automessage.scheduled.selector; -import org.jetbrains.annotations.NotNull; - public final class MessageSelectorFactory { private MessageSelectorFactory() { throw new UnsupportedOperationException("This is a utility class and cannot be instantiated."); } - public static @NotNull MessageSelector create(@NotNull MessageSelectorType type) { + public static MessageSelector create(MessageSelectorType type) { return switch (type) { case RANDOM -> new RandomMessageSelector(); case SEQUENTIAL -> new SequentialMessageSelector(); diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/RandomMessageSelector.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/RandomMessageSelector.java index 9ffe6a8..fb63fa2 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/RandomMessageSelector.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/RandomMessageSelector.java @@ -1,7 +1,6 @@ package com.github.imdmk.automessage.scheduled.selector; import com.github.imdmk.automessage.scheduled.ScheduledMessage; -import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Optional; @@ -10,12 +9,12 @@ final class RandomMessageSelector implements MessageSelector { @Override - public Optional selectNext(@NotNull List messages, boolean advanceIndex) { + public Optional selectNext(List messages, boolean advanceIndex) { if (messages.isEmpty()) { return Optional.empty(); } - int index = ThreadLocalRandom.current().nextInt(messages.size()); + final int index = ThreadLocalRandom.current().nextInt(messages.size()); return Optional.of(messages.get(index)); } } diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/SequentialMessageSelector.java b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/SequentialMessageSelector.java index 4a9d543..9c09051 100644 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/SequentialMessageSelector.java +++ b/automessage-core/src/main/java/com/github/imdmk/automessage/scheduled/selector/SequentialMessageSelector.java @@ -1,7 +1,6 @@ package com.github.imdmk.automessage.scheduled.selector; import com.github.imdmk.automessage.scheduled.ScheduledMessage; -import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Optional; @@ -14,7 +13,7 @@ final class SequentialMessageSelector implements MessageSelector { @Override public Optional selectNext( - @NotNull List messages, + List messages, boolean advanceIndex ) { final int size = messages.size(); diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentSerializer.java b/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentSerializer.java deleted file mode 100644 index e7e08d9..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentSerializer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.imdmk.automessage.shared.adventure; - -import eu.okaeri.configs.schema.GenericsDeclaration; -import eu.okaeri.configs.serdes.DeserializationData; -import eu.okaeri.configs.serdes.ObjectSerializer; -import eu.okaeri.configs.serdes.SerializationData; -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.NotNull; - -public final class AdventureComponentSerializer implements ObjectSerializer { - - @Override - public boolean supports(@NotNull Class type) { - return Component.class.isAssignableFrom(type); - } - - @Override - public void serialize(@NotNull Component component, @NotNull SerializationData data, @NotNull GenericsDeclaration generics) { - data.setValue(AdventureComponents.serialize(component)); - } - - @Override - public Component deserialize(@NotNull DeserializationData data, @NotNull GenericsDeclaration generics) { - return AdventureComponents.text(data.getValue(String.class)); - } -} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureComponents.java b/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureComponents.java deleted file mode 100644 index f712d2e..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureComponents.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.github.imdmk.automessage.shared.adventure; - -import com.github.imdmk.automessage.shared.validate.Validator; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.ComponentLike; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.minimessage.MiniMessage; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Utilities for working with Adventure {@link Component}s via MiniMessage. - * Platform-agnostic (no Bukkit types). Thread-safe and stateless. - * - *

Notes: - *

    - *
  • All returned collections are unmodifiable.
  • - *
  • Accepts {@link CharSequence} for flexibility.
  • - *
- * - *
- *   Component c = AdventureComponents.text("<red>Hello");
- *   Component plain = AdventureComponents.withoutItalics(c);
- * 
- */ -public final class AdventureComponents { - - private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); - - private AdventureComponents() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated."); - } - - /** - * Deserializes a MiniMessage-formatted text into a {@link Component}. - * - * @param text the MiniMessage-formatted text - * @return the deserialized component - */ - public static @NotNull Component text(@NotNull CharSequence text) { - Validator.notNull(text, "text"); - return MINI_MESSAGE.deserialize(text.toString()); - } - - /** - * Deserializes multiple MiniMessage-formatted texts into a list of {@link Component}s. - * - * @param texts array of MiniMessage-formatted texts - * @return an unmodifiable list of deserialized components - */ - public static @NotNull List text(@NotNull CharSequence... texts) { - Validator.notNull(texts, "texts"); - - final List out = new ArrayList<>(texts.length); - for (CharSequence text : texts) { - out.add(MINI_MESSAGE.deserialize(text.toString())); - } - - return List.copyOf(out); - } - - /** - * Deserializes a collection of MiniMessage-formatted texts into {@link Component}s. - * - * @param texts iterable of MiniMessage-formatted texts - * @return an unmodifiable list of deserialized components - */ - public static @NotNull List text(@NotNull Iterable texts) { - Validator.notNull(texts, "texts"); - - final List out = new ArrayList<>(); - for (CharSequence text : texts) { - Validator.notNull(text, "texts contains null element"); - out.add(MINI_MESSAGE.deserialize(text.toString())); - } - - return List.copyOf(out); - } - - /** - * Returns a copy of the given component with italics disabled. - * - * @param component the source component - * @return a new component without italics - */ - public static @NotNull Component withoutItalics(@NotNull Component component) { - Validator.notNull(component, "component"); - return component.decoration(TextDecoration.ITALIC, false); - } - - /** - * Deserializes a MiniMessage-formatted text and removes italics. - * - * @param text the MiniMessage-formatted text - * @return a deserialized component without italics - */ - public static @NotNull Component withoutItalics(@NotNull CharSequence text) { - return withoutItalics(text(text)); - } - - /** - * Converts a {@link ComponentLike} into a {@link Component} and removes italics. - * - * @param like the source component-like object - * @return a new component without italics - */ - public static @NotNull Component withoutItalics(@NotNull ComponentLike like) { - Validator.notNull(like, "component"); - return like.asComponent().decoration(TextDecoration.ITALIC, false); - } - - /** - * Disables italics for all given components. - * - * @param strings iterable of strings objects - * @return an unmodifiable list of components with italics disabled - */ - public static @NotNull List withoutItalics(@NotNull String... strings) { - Validator.notNull(strings, "components"); - - final List out = new ArrayList<>(); - for (final String string : strings) { - Validator.notNull(string, "components contains null element"); - out.add(withoutItalics(string)); - } - - return List.copyOf(out); - } - - /** - * Serializes a {@link Component} into a MiniMessage-formatted string. - * - * @param component the component to serialize - * @return the serialized MiniMessage string - */ - public static @NotNull String serialize(@NotNull Component component) { - Validator.notNull(component, "component"); - return MINI_MESSAGE.serialize(component); - } - - /** - * Serializes multiple components into MiniMessage-formatted strings. - * - * @param components collection of component-like objects - * @return an unmodifiable list of serialized strings - */ - public static @NotNull List serialize(@NotNull Collection components) { - Validator.notNull(components, "components"); - - final List out = new ArrayList<>(components.size()); - for (final ComponentLike component : components) { - Validator.notNull(component, "components contains null element"); - out.add(MINI_MESSAGE.serialize(component.asComponent())); - } - - return List.copyOf(out); - } - - /** - * Serializes multiple components and joins them with the given delimiter. - * - * @param components collection of component-like objects - * @param delimiter string separator between serialized components - * @return a single joined MiniMessage string - */ - public static @NotNull String serializeJoined(@NotNull Collection components, - @NotNull CharSequence delimiter) { - Validator.notNull(components, "components"); - Validator.notNull(delimiter, "delimiter"); - - final List serialized = new ArrayList<>(components.size()); - for (final ComponentLike component : components) { - Validator.notNull(component, "components contains null element"); - serialized.add(MINI_MESSAGE.serialize(component.asComponent())); - } - - return String.join(delimiter, serialized); - } -} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatter.java b/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatter.java deleted file mode 100644 index 6f782c1..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatter.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.github.imdmk.automessage.shared.adventure; - -import com.github.imdmk.automessage.shared.validate.Validator; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextReplacementConfig; -import org.jetbrains.annotations.NotNull; - -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Utility for applying {@link AdventurePlaceholders} to {@link Component} trees or plain strings. - *

Stateless and thread-safe.

- */ -public final class AdventureFormatter { - - private AdventureFormatter() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - /** - * Applies placeholders to a plain string and returns a formatted {@link Component}. - * - * @param input plain text input - * @param placeholders placeholders to apply - * @return formatted component - */ - public static @NotNull Component format(@NotNull String input, @NotNull AdventurePlaceholders placeholders) { - Validator.notNull(input, "input cannot be null"); - return format(AdventureComponents.text(input), placeholders); - } - - /** - * Applies placeholders to each {@link Component} in a list. - * - * @param components list of components - * @param placeholders placeholders to apply - * @return formatted components - */ - public static @NotNull List format(@NotNull List components, @NotNull AdventurePlaceholders placeholders) { - Validator.notNull(components, "components cannot be null"); - return components.stream() - .map(component -> format(component, placeholders)) - .collect(Collectors.toList()); - } - - /** - * Applies placeholders to a single {@link Component}. - * - * @param input component to format - * @param placeholders placeholders to apply - * @return formatted component - */ - public static @NotNull Component format(@NotNull Component input, @NotNull AdventurePlaceholders placeholders) { - Validator.notNull(input, "input cannot be null"); - Validator.notNull(placeholders, "placeholders cannot be null"); - - if (placeholders.isEmpty()) { - return input; - } - - // Sort keys by descending length to avoid substring overlap - List> ordered = placeholders.asMap().entrySet().stream() - .sorted(Comparator.>comparingInt(e -> e.getKey().length()).reversed()) - .collect(Collectors.toList()); - - Component out = input; - for (final Map.Entry e : ordered) { - var key = e.getKey(); - var replacement = e.getValue(); - - var config = TextReplacementConfig.builder() - .matchLiteral(key) - .replacement(replacement) - .build(); - - out = out.replaceText(config); - } - - return out; - } -} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholders.java b/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholders.java deleted file mode 100644 index 70a085a..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholders.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.github.imdmk.automessage.shared.adventure; - -import com.github.imdmk.automessage.shared.validate.Validator; -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Unmodifiable; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Immutable container mapping literal placeholder keys to Adventure {@link Component} values. - *

- * Instances are created via the {@link Builder}. Once built, the mapping is read-only. - *

- * Thread-safety: Fully immutable and safe for concurrent use. - */ -public final class AdventurePlaceholders { - - private static final AdventurePlaceholders EMPTY = new AdventurePlaceholders(Map.of()); - - private final Map map; - - private AdventurePlaceholders(@NotNull Map map) { - Validator.notNull(map, "map cannot be null"); - this.map = Collections.unmodifiableMap(map); - } - - /** - * Returns an unmodifiable view of all placeholder mappings. - * - * @return unmodifiable placeholder map - */ - @Unmodifiable - @NotNull - public Map asMap() { - return map; - } - - /** - * Returns the number of registered placeholders. - * - * @return placeholder count - */ - public int size() { - return map.size(); - } - - /** - * Checks if the placeholder map is empty. - * - * @return {@code true} if no placeholders are defined - */ - public boolean isEmpty() { - return map.isEmpty(); - } - - /** - * Returns a shared immutable empty instance. - * - * @return empty placeholder container - */ - public static @NotNull AdventurePlaceholders empty() { - return EMPTY; - } - - /** - * Creates a new builder for {@link AdventurePlaceholders}. - * - * @return new builder instance - */ - public static @NotNull Builder builder() { - return new Builder(); - } - - /** - * Fluent builder for {@link AdventurePlaceholders}. - */ - public static final class Builder { - - private final Map entries = new LinkedHashMap<>(); - - /** - * Adds a literal → component mapping. - * - * @param key literal placeholder key - * @param value replacement component - * @return this builder for chaining - */ - @Contract("_,_ -> this") - public @NotNull Builder with(@NotNull String key, @NotNull Component value) { - Validator.notNull(key, "key cannot be null"); - Validator.notNull(value, "value cannot be null"); - this.entries.put(key, value); - return this; - } - - /** - * Adds a literal → plain text mapping (converted to {@link Component#text(String)}). - * - * @param key literal placeholder key - * @param value replacement text - * @return this builder for chaining - */ - @Contract("_,_ -> this") - public @NotNull Builder with(@NotNull String key, @NotNull String value) { - Validator.notNull(key, "key cannot be null"); - Validator.notNull(value, "value cannot be null"); - this.entries.put(key, Component.text(value)); - return this; - } - - /** - * Adds all entries from another {@link AdventurePlaceholders}. - * - * @param other another placeholder container - * @return this builder for chaining - */ - @Contract("_ -> this") - public @NotNull Builder with(@NotNull AdventurePlaceholders other) { - Validator.notNull(other, "other cannot be null"); - this.entries.putAll(other.asMap()); - return this; - } - - /** - * Adds a placeholder using any object value. - * The value is converted to plain text via {@link String#valueOf(Object)}. - * - * @param key placeholder key - * @param value object to convert and insert - * @return this builder for chaining - * @throws NullPointerException if key or value is null - */ - @Contract("_,_ -> this") - public @NotNull Builder with(@NotNull String key, @NotNull Object value) { - Validator.notNull(key, "key cannot be null"); - Validator.notNull(value, "value cannot be null"); - this.entries.put(key, Component.text(String.valueOf(value))); - return this; - } - - /** - * Builds an immutable {@link AdventurePlaceholders} instance. - * - * @return immutable placeholder container - */ - public @NotNull AdventurePlaceholders build() { - if (this.entries.isEmpty()) { - return EMPTY; - } - - return new AdventurePlaceholders(new LinkedHashMap<>(this.entries)); - } - } -} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/message/MessageService.java b/automessage-core/src/main/java/com/github/imdmk/automessage/shared/message/MessageService.java deleted file mode 100644 index c2783cc..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/message/MessageService.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.github.imdmk.automessage.shared.message; - -import com.eternalcode.multification.adventure.AudienceConverter; -import com.eternalcode.multification.bukkit.BukkitMultification; -import com.eternalcode.multification.notice.provider.NoticeProvider; -import com.eternalcode.multification.translation.TranslationProvider; -import com.github.imdmk.automessage.shared.validate.Validator; -import net.kyori.adventure.platform.AudienceProvider; -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.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public final class MessageService extends BukkitMultification { - - private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); - - private final MessageConfig messageConfig; - private final AudienceProvider audienceProvider; - - public MessageService( - @NotNull MessageConfig messageConfig, - @NotNull AudienceProvider audienceProvider - ) { - this.messageConfig = Validator.notNull(messageConfig, "messageConfig cannot be null"); - this.audienceProvider = Validator.notNull(audienceProvider, "audienceProvider cannot be null"); - } - - /** - * Returns a translation provider that always returns the same {@link MessageConfig} instance, - * ignoring locale differences. - * - * @return locale-agnostic translation provider - */ - @Override - protected @NotNull TranslationProvider translationProvider() { - return provider -> messageConfig; - } - - /** - * Returns the {@link MiniMessage}-based component serializer. - * - * @return component serializer for text serialization/deserialization - */ - @Override - protected @NotNull ComponentSerializer serializer() { - return MINI_MESSAGE; - } - - /** - * Converts Bukkit {@link CommandSender}s into Adventure audiences - * using the configured {@link AudienceProvider}. - * - *

Players are mapped to player audiences, while other senders - * (e.g., console or command blocks) are mapped to {@link AudienceProvider#console()}.

- * - * @return non-null audience converter - */ - @Override - protected @NotNull AudienceConverter audienceConverter() { - return sender -> { - if (sender instanceof Player player) { - return audienceProvider.player(player.getUniqueId()); - } - return audienceProvider.console(); - }; - } - - /** - * Sends a localized or static notice message to the specified Bukkit {@link CommandSender}. - * - *

The notice is resolved through the active {@link MessageConfig} - * and rendered using {@link MiniMessage} formatting.

- * - * @param sender non-null Bukkit command sender (player, console, etc.) - * @param notice non-null notice provider bound to {@link MessageConfig} - * @throws NullPointerException if {@code sender} or {@code notice} is null - */ - public void send(@NotNull CommandSender sender, @NotNull NoticeProvider notice) { - Validator.notNull(sender, "sender cannot be null"); - Validator.notNull(notice, "notice cannot be null"); - create().viewer(sender).notice(notice).send(); - } -} diff --git a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/validate/Validator.java b/automessage-core/src/main/java/com/github/imdmk/automessage/shared/validate/Validator.java deleted file mode 100644 index 2e20606..0000000 --- a/automessage-core/src/main/java/com/github/imdmk/automessage/shared/validate/Validator.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.github.imdmk.automessage.shared.validate; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; - -/** - * Utility class for common validation checks. - *

- * Provides null-safety guards used throughout the codebase. - */ -public final class Validator { - - private Validator() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - /** - * Ensures the given object is not {@code null}. - *

- * This method is typically used to validate constructor arguments and - * configuration values. If the supplied object is non-null, it is returned - * unchanged; otherwise a {@link NullPointerException} is thrown with the - * provided message. - * - * @param obj the value to validate; may be null - * @param context exception context used when {@code obj} is null - * @param type of the validated object - * @return the non-null value of {@code obj} - * @throws NullPointerException if {@code obj} is null - */ - public static T notNull(@Nullable T obj, @NotNull String context) { - if (obj == null) { - throw new NullPointerException(context + " cannot be null"); - } - return obj; - } - - /** - * Executes the given {@link Consumer} only if the supplied object is not {@code null}. - *

- * This helper is especially useful during shutdown or cleanup phases where - * optional components may or may not be initialized. The consumer itself - * must be non-null; however, it will only be invoked when {@code obj} is non-null. - * - *

Example usage: - *

-     * Validator.ifNotNull(taskScheduler, TaskScheduler::shutdown);
-     * Validator.ifNotNull(messageService, MessageService::shutdown);
-     * 
- * - * @param obj the object to check before executing the consumer; may be null - * @param consumer operation to execute when {@code obj} is non-null (never null) - * @param type of the object passed to the consumer - * @throws NullPointerException if {@code consumer} is null - */ - public static void ifNotNull(@Nullable T obj, @NotNull Consumer consumer) { - Validator.notNull(consumer, "consumer is null"); - if (obj != null) { - consumer.accept(obj); - } - } - -} \ No newline at end of file diff --git a/automessage-core/src/test/java/com/github/imdmk/automessage/config/ConfigManagerTest.java b/automessage-core/src/test/java/com/github/imdmk/automessage/config/ConfigManagerTest.java index 9eb08e7..054cc88 100644 --- a/automessage-core/src/test/java/com/github/imdmk/automessage/config/ConfigManagerTest.java +++ b/automessage-core/src/test/java/com/github/imdmk/automessage/config/ConfigManagerTest.java @@ -48,7 +48,7 @@ void setUp() { void create_shouldInstantiateBindInitializeAndRegister() { // given SampleConfig config = new SampleConfig(); - when(factory.instantiate(SampleConfig.class)).thenReturn(config); + when(factory.create(SampleConfig.class)).thenReturn(config); // when SampleConfig result = manager.create(SampleConfig.class); @@ -56,7 +56,7 @@ void create_shouldInstantiateBindInitializeAndRegister() { // then assertSame(config, result); - verify(factory).instantiate(SampleConfig.class); + verify(factory).create(SampleConfig.class); verify(binder).bind(eq(config), any(File.class)); verify(lifecycle).initialize(config); @@ -67,11 +67,11 @@ void create_shouldInstantiateBindInitializeAndRegister() { @Test @DisplayName("createAll(): should call create() for each provided config class") void createAll_shouldCreateEachConfig() { - when(factory.instantiate(SampleConfig.class)).thenReturn(new SampleConfig()); + when(factory.create(SampleConfig.class)).thenReturn(new SampleConfig()); manager.createAll(List.of(SampleConfig.class)); - verify(factory).instantiate(SampleConfig.class); + verify(factory).create(SampleConfig.class); } @Test @@ -84,7 +84,7 @@ void require_shouldThrowWhenNotCreated() { @DisplayName("loadAll(): should delegate loading to lifecycle") void loadAll_shouldDelegateToLifecycle() { SampleConfig config = new SampleConfig(); - when(factory.instantiate(SampleConfig.class)).thenReturn(config); + when(factory.create(SampleConfig.class)).thenReturn(config); manager.create(SampleConfig.class); manager.loadAll(); @@ -96,7 +96,7 @@ void loadAll_shouldDelegateToLifecycle() { @DisplayName("saveAll(): should delegate saving to lifecycle") void saveAll_shouldDelegateToLifecycle() { SampleConfig config = new SampleConfig(); - when(factory.instantiate(SampleConfig.class)).thenReturn(config); + when(factory.create(SampleConfig.class)).thenReturn(config); manager.create(SampleConfig.class); manager.saveAll(); @@ -107,7 +107,7 @@ void saveAll_shouldDelegateToLifecycle() { @Test @DisplayName("clearAll(): should remove all configs from registry") void clearAll_shouldRemoveAllConfigs() { - when(factory.instantiate(SampleConfig.class)).thenReturn(new SampleConfig()); + when(factory.create(SampleConfig.class)).thenReturn(new SampleConfig()); manager.create(SampleConfig.class); manager.clearAll(); diff --git a/automessage-core/src/test/java/com/github/imdmk/automessage/config/SampleConfig.java b/automessage-core/src/test/java/com/github/imdmk/automessage/config/SampleConfig.java index e0c9562..c826ec3 100644 --- a/automessage-core/src/test/java/com/github/imdmk/automessage/config/SampleConfig.java +++ b/automessage-core/src/test/java/com/github/imdmk/automessage/config/SampleConfig.java @@ -1,19 +1,18 @@ package com.github.imdmk.automessage.config; import eu.okaeri.configs.serdes.OkaeriSerdesPack; -import org.jetbrains.annotations.NotNull; public class SampleConfig extends ConfigSection { public int value = 5; @Override - public @NotNull OkaeriSerdesPack getSerdesPack() { + public OkaeriSerdesPack getSerdesPack() { return registry -> {}; } @Override - public @NotNull String getFileName() { + public String getFileName() { return "sample.yml"; } } diff --git a/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentsTest.java b/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentsTest.java index 7523efd..fa1e690 100644 --- a/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentsTest.java +++ b/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureComponentsTest.java @@ -1,5 +1,6 @@ package com.github.imdmk.automessage.shared.adventure; +import com.github.imdmk.automessage.platform.adventure.AdventureComponents; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextDecoration; import org.junit.jupiter.api.Test; diff --git a/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatterTest.java b/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatterTest.java index d64e0bf..578bed5 100644 --- a/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatterTest.java +++ b/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventureFormatterTest.java @@ -1,5 +1,7 @@ package com.github.imdmk.automessage.shared.adventure; +import com.github.imdmk.automessage.platform.adventure.AdventureFormatter; +import com.github.imdmk.automessage.platform.adventure.AdventurePlaceholders; import net.kyori.adventure.text.Component; import org.junit.jupiter.api.Test; diff --git a/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholdersTest.java b/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholdersTest.java index e61d49f..bec7ee0 100644 --- a/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholdersTest.java +++ b/automessage-core/src/test/java/com/github/imdmk/automessage/shared/adventure/AdventurePlaceholdersTest.java @@ -1,5 +1,6 @@ package com.github.imdmk.automessage.shared.adventure; +import com.github.imdmk.automessage.platform.adventure.AdventurePlaceholders; import net.kyori.adventure.text.Component; import org.junit.jupiter.api.Test; diff --git a/automessage-plugin/build.gradle.kts b/automessage-loader/build.gradle.kts similarity index 100% rename from automessage-plugin/build.gradle.kts rename to automessage-loader/build.gradle.kts diff --git a/automessage-loader/src/main/java/com/github/imdmk/automessage/AutoMessagePluginLoader.java b/automessage-loader/src/main/java/com/github/imdmk/automessage/AutoMessagePluginLoader.java new file mode 100644 index 0000000..e95d404 --- /dev/null +++ b/automessage-loader/src/main/java/com/github/imdmk/automessage/AutoMessagePluginLoader.java @@ -0,0 +1,21 @@ +package com.github.imdmk.automessage; + +import org.bukkit.plugin.java.JavaPlugin; + +public final class AutoMessagePluginLoader extends JavaPlugin { + + private AutoMessagePlugin plugin; + + @Override + public void onEnable() { + this.plugin = new AutoMessagePlugin(this); + } + + @Override + public void onDisable() { + if (this.plugin != null) { + this.plugin.disable(); + this.plugin = null; + } + } +} diff --git a/automessage-plugin/src/main/java/com/github/imdmk/automessage/AutoMessagePluginLoader.java b/automessage-plugin/src/main/java/com/github/imdmk/automessage/AutoMessagePluginLoader.java deleted file mode 100644 index 35128ea..0000000 --- a/automessage-plugin/src/main/java/com/github/imdmk/automessage/AutoMessagePluginLoader.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.github.imdmk.automessage; - -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; - -public final class AutoMessagePluginLoader extends JavaPlugin { - - private volatile AutoMessagePlugin pluginCore; - - @Override - public void onEnable() { - final Plugin plugin = this; - - pluginCore = new AutoMessagePlugin(plugin); - pluginCore.enable(new DefaultPluginSettings()); - } - - @Override - public void onDisable() { - if (pluginCore != null) { - pluginCore.disable(); - pluginCore = null; - } - } -} diff --git a/automessage-plugin/src/main/java/com/github/imdmk/automessage/DefaultPluginSettings.java b/automessage-plugin/src/main/java/com/github/imdmk/automessage/DefaultPluginSettings.java deleted file mode 100644 index 2a30160..0000000 --- a/automessage-plugin/src/main/java/com/github/imdmk/automessage/DefaultPluginSettings.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.imdmk.automessage; - -import com.github.imdmk.automessage.config.ConfigSection; -import com.github.imdmk.automessage.scheduled.ScheduledMessagesConfig; -import com.github.imdmk.automessage.scheduled.dispatcher.MessageDispatcherConfig; -import com.github.imdmk.automessage.shared.message.MessageConfig; - -import java.util.List; - -public final class DefaultPluginSettings implements PluginSettings { - - @Override - public List> configs() { - return List.of( - MessageConfig.class, - ScheduledMessagesConfig.class, - MessageDispatcherConfig.class - ); - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index bd3a62b..bc2c9cd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,3 @@ rootProject.name = "AutoMessage" include("automessage-core") -include("automessage-plugin") \ No newline at end of file +include("automessage-loader") \ No newline at end of file