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 extends CharSequence> 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 extends ComponentLike> 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 extends ComponentLike> 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 super ScheduledMessage> 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 super AudienceRule> 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 extends Player> players,
- @NotNull Predicate predicate
+ Collection extends Player> 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 extends Player> recipients() {
+ public Collection extends Player> 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 extends Player> players
+ Collection extends Player> players
) implements DispatchTarget {
- public DispatchPlayersTarget {
- Validator.notNull(players, "players cannot be null");
- }
-
@Override
- public @NotNull Collection extends Player> recipients() {
+ public Collection extends Player> 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 extends Player> recipients();
+ Collection extends Player> 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 extends Player> players) {
+ static DispatchTarget players(Collection extends Player> 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 extends Player> players,
- @NotNull Predicate filter
+ static DispatchTarget filtered(
+ Collection extends Player> 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 extends Player> onlinePlayers = server.getOnlinePlayers();
+ final Collection extends Player> 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 super Component> 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 extends CharSequence> 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 extends ComponentLike> 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 extends ComponentLike> 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