diff --git a/playtime-api/build.gradle.kts b/playtime-api/build.gradle.kts index 7982ff6..84917f6 100644 --- a/playtime-api/build.gradle.kts +++ b/playtime-api/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { - compileOnly("org.jetbrains:annotations:26.0.2-1") + compileOnlyApi("org.jetbrains:annotations:26.0.2-1") testImplementation("org.junit.jupiter:junit-jupiter:6.0.1") testImplementation("org.assertj:assertj-core:3.25.2") diff --git a/playtime-api/src/main/java/com/github/imdmk/playtime/user/UserTime.java b/playtime-api/src/main/java/com/github/imdmk/playtime/user/UserTime.java index e9db527..2dc8502 100644 --- a/playtime-api/src/main/java/com/github/imdmk/playtime/user/UserTime.java +++ b/playtime-api/src/main/java/com/github/imdmk/playtime/user/UserTime.java @@ -109,7 +109,7 @@ public record UserTime(long millis) implements Comparable, Serializabl */ @Contract("_ -> new") public static @NotNull UserTime from(@NotNull Duration duration) { - Objects.requireNonNull(duration, "duration is null"); + Objects.requireNonNull(duration, "duration cannot be null"); return new UserTime(duration.toMillis()); } diff --git a/playtime-bukkit-api/build.gradle.kts b/playtime-bukkit-api/build.gradle.kts index db40f8c..962ee86 100644 --- a/playtime-bukkit-api/build.gradle.kts +++ b/playtime-bukkit-api/build.gradle.kts @@ -1,6 +1,4 @@ dependencies { api(project(":playtime-api")) - - compileOnly("org.jetbrains:annotations:26.0.2-1") - compileOnly("org.spigotmc:spigot-api:1.21.10-R0.1-SNAPSHOT") -} \ No newline at end of file + compileOnlyApi("org.spigotmc:spigot-api:1.21.10-R0.1-SNAPSHOT") +} diff --git a/playtime-bukkit-api/src/main/java/com/github/imdmk/playtime/UserDeleteEvent.java b/playtime-bukkit-api/src/main/java/com/github/imdmk/playtime/UserDeleteEvent.java index 0a269dd..4459b8b 100644 --- a/playtime-bukkit-api/src/main/java/com/github/imdmk/playtime/UserDeleteEvent.java +++ b/playtime-bukkit-api/src/main/java/com/github/imdmk/playtime/UserDeleteEvent.java @@ -29,7 +29,7 @@ public final class UserDeleteEvent extends Event { */ public UserDeleteEvent(@NotNull UserDeleteResult result) { super(ASYNC); - this.result = Objects.requireNonNull(result, "result cannot be null");; + this.result = Objects.requireNonNull(result, "result cannot be null"); } /** diff --git a/playtime-core/build.gradle.kts b/playtime-core/build.gradle.kts index e2bc481..918ecdb 100644 --- a/playtime-core/build.gradle.kts +++ b/playtime-core/build.gradle.kts @@ -1,8 +1,7 @@ dependencies { - compileOnly("org.spigotmc:spigot-api:1.21.10-R0.1-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.11.7") - implementation(project(":playtime-bukkit-api")) + api(project(":playtime-bukkit-api")) // DI implementation("org.panda-lang.utilities:di:1.8.0") @@ -25,7 +24,7 @@ dependencies { // Okaeri configs api("eu.okaeri:okaeri-configs-yaml-snakeyaml:5.0.9") - api("eu.okaeri:okaeri-configs-serdes-commons:5.0.5") + implementation("eu.okaeri:okaeri-configs-serdes-commons:5.0.5") // GUI, metrics, commands implementation("dev.triumphteam:triumph-gui:3.1.13") diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimeCoreBinder.java b/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimeBinder.java similarity index 78% rename from playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimeCoreBinder.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimeBinder.java index 35f6535..1bacd48 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimeCoreBinder.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimeBinder.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime; -import com.github.imdmk.playtime.infrastructure.di.BindCore; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.infrastructure.injector.Bind; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.Injector; import org.panda_lang.utilities.inject.Resources; @@ -10,14 +10,14 @@ import java.lang.reflect.Modifier; /** - * Discovers fields in {@link PlayTimePlugin} annotated with {@link BindCore} + * Discovers fields in {@link PlayTimePlugin} annotated with {@link Bind} * and registers their instances into the DI {@link Resources}. *

* This approach keeps {@link PlayTimePlugin} focused on lifecycle/bootstrap logic * while delegating dependency wiring to a dedicated, reflection-based binder. - * Only non-static fields with {@code @BindCore} are processed. + * Only non-static fields with {@code @Bind} are processed. */ -final class PlayTimeCoreBinder { +final class PlayTimeBinder { private final PlayTimePlugin core; @@ -26,25 +26,25 @@ final class PlayTimeCoreBinder { * * @param core the plugin root object providing core dependencies */ - PlayTimeCoreBinder(@NotNull PlayTimePlugin core) { - this.core = Validator.notNull(core, "core cannot be null"); + PlayTimeBinder(@NotNull PlayTimePlugin core) { + this.core = Validator.notNull(core, "core"); } /** * Scans the {@link PlayTimePlugin} class hierarchy, locates fields annotated with - * {@link BindCore}, reads their values, and registers them into the provided + * {@link Bind}, reads their values, and registers them into the provided * {@link Resources} instance. * * @param resources DI container resources to bind into */ void bind(@NotNull Resources resources) { - Validator.notNull(resources, "resources cannot be null"); + Validator.notNull(resources, "resources"); Class type = core.getClass(); while (type != null && type != Object.class) { for (Field field : type.getDeclaredFields()) { - if (!field.isAnnotationPresent(BindCore.class)) { + if (!field.isAnnotationPresent(Bind.class)) { continue; } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimePlugin.java b/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimePlugin.java index f5f2f4e..a6311bf 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimePlugin.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/PlayTimePlugin.java @@ -1,40 +1,39 @@ package com.github.imdmk.playtime; import com.eternalcode.multification.notice.Notice; +import com.github.imdmk.playtime.config.ConfigManager; +import com.github.imdmk.playtime.config.ConfigSection; +import com.github.imdmk.playtime.config.InjectorConfigBinder; +import com.github.imdmk.playtime.config.PluginConfig; import com.github.imdmk.playtime.infrastructure.database.DatabaseConfig; -import com.github.imdmk.playtime.infrastructure.database.DatabaseConnector; -import com.github.imdmk.playtime.infrastructure.database.driver.dependency.DriverDependencyLoader; +import com.github.imdmk.playtime.infrastructure.database.DatabaseManager; import com.github.imdmk.playtime.infrastructure.database.repository.RepositoryContext; import com.github.imdmk.playtime.infrastructure.database.repository.RepositoryManager; -import com.github.imdmk.playtime.infrastructure.di.BindCore; +import com.github.imdmk.playtime.infrastructure.injector.Bind; import com.github.imdmk.playtime.infrastructure.module.Module; import com.github.imdmk.playtime.infrastructure.module.ModuleContext; import com.github.imdmk.playtime.infrastructure.module.ModuleInitializer; import com.github.imdmk.playtime.infrastructure.module.ModuleRegistry; +import com.github.imdmk.playtime.message.MessageConfig; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.platform.events.BukkitEventCaller; import com.github.imdmk.playtime.platform.events.BukkitListenerRegistrar; import com.github.imdmk.playtime.platform.gui.GuiRegistry; import com.github.imdmk.playtime.platform.litecommands.InvalidUsageHandlerImpl; import com.github.imdmk.playtime.platform.litecommands.MissingPermissionsHandlerImpl; import com.github.imdmk.playtime.platform.litecommands.NoticeResultHandlerImpl; -import com.github.imdmk.playtime.platform.litecommands.configurer.BukkitLiteCommandsRegistrar; -import com.github.imdmk.playtime.platform.litecommands.configurer.LiteCommandsRegistrar; import com.github.imdmk.playtime.platform.logger.BukkitPluginLogger; import com.github.imdmk.playtime.platform.logger.PluginLogger; import com.github.imdmk.playtime.platform.placeholder.adapter.PlaceholderAdapter; import com.github.imdmk.playtime.platform.placeholder.adapter.PlaceholderAdapterFactory; import com.github.imdmk.playtime.platform.scheduler.BukkitTaskScheduler; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.config.ConfigBinder; -import com.github.imdmk.playtime.shared.config.ConfigManager; -import com.github.imdmk.playtime.shared.config.ConfigSection; -import com.github.imdmk.playtime.shared.config.PluginConfig; -import com.github.imdmk.playtime.shared.message.MessageConfig; -import com.github.imdmk.playtime.shared.message.MessageService; import com.github.imdmk.playtime.shared.time.Durations; +import com.github.imdmk.playtime.shared.validate.Validator; import com.google.common.base.Stopwatch; import dev.rollczi.litecommands.LiteCommands; +import dev.rollczi.litecommands.LiteCommandsBuilder; +import dev.rollczi.litecommands.bukkit.LiteBukkitFactory; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bstats.bukkit.Metrics; import org.bukkit.Server; @@ -58,28 +57,28 @@ final class PlayTimePlugin { private static final String PREFIX = "AdvancedPlayTime"; private static final int PLUGIN_METRICS_ID = 19362; - @BindCore private final ModuleRegistry moduleRegistry = new ModuleRegistry(); + @Bind private final ModuleRegistry moduleRegistry = new ModuleRegistry(); - @BindCore private final Plugin plugin; - @BindCore private final PluginLogger logger; - @BindCore private final Server server; - @BindCore private final ExecutorService executor; + @Bind private final Plugin plugin; + @Bind private final PluginLogger logger; + @Bind private final Server server; + @Bind private final ExecutorService executor; - @BindCore private ConfigManager configManager; + @Bind private ConfigManager configManager; - @BindCore private DatabaseConnector databaseConnector; - @BindCore private RepositoryContext repositoryContext; - @BindCore private RepositoryManager repositoryManager; + @Bind private DatabaseManager databaseManager; + @Bind private RepositoryContext repositoryContext; + @Bind private RepositoryManager repositoryManager; - @BindCore private MessageService messageService; - @BindCore private TaskScheduler taskScheduler; - @BindCore private BukkitEventCaller eventCaller; - @BindCore private BukkitListenerRegistrar listenerRegistrar; - @BindCore private GuiRegistry guiRegistry; - @BindCore private PlaceholderAdapter placeholderAdapter; + @Bind private MessageService messageService; + @Bind private TaskScheduler taskScheduler; + @Bind private BukkitEventCaller eventCaller; + @Bind private BukkitListenerRegistrar listenerRegistrar; + @Bind private GuiRegistry guiRegistry; + @Bind private PlaceholderAdapter placeholderAdapter; - @BindCore private LiteCommandsRegistrar LiteCommandsRegistrar; - private LiteCommands liteCommands; + @Bind private LiteCommandsBuilder liteCommandsBuilder; + @Bind private LiteCommands liteCommands; private Metrics metrics; @@ -89,11 +88,12 @@ final class PlayTimePlugin { @NotNull Plugin plugin, @NotNull Server server, @NotNull PluginLogger logger, - @NotNull ExecutorService executor) { - this.plugin = Validator.notNull(plugin, "plugin cannot be null"); - this.server = Validator.notNull(server, "server cannot be null"); - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.executor = Validator.notNull(executor, "executorService cannot be null"); + @NotNull ExecutorService executor + ) { + this.plugin = Validator.notNull(plugin, "plugin"); + this.server = Validator.notNull(server, "server"); + this.logger = Validator.notNull(logger, "logger"); + this.executor = Validator.notNull(executor, "executorService"); } PlayTimePlugin(@NotNull Plugin plugin, @NotNull ExecutorService executor) { @@ -102,14 +102,15 @@ final class PlayTimePlugin { void enable( @NotNull List> enabledConfigs, - @NotNull List> enabledModules) { - Validator.notNull(enabledConfigs, "enabledConfigs cannot be null"); - Validator.notNull(enabledModules, "enabled modules cannot be null"); + @NotNull List> enabledModules + ) { + Validator.notNull(enabledConfigs, "enabledConfigs"); + Validator.notNull(enabledModules, "enabled modules"); final Stopwatch stopwatch = Stopwatch.createStarted(); // Configuration - configManager = new ConfigManager(logger, executor, plugin.getDataFolder()); + configManager = new ConfigManager(logger, plugin.getDataFolder()); configManager.createAll(enabledConfigs); // Duration format style @@ -118,18 +119,15 @@ void enable( // Database final DatabaseConfig databaseConfig = configManager.require(DatabaseConfig.class); + databaseManager = new DatabaseManager(plugin, logger, databaseConfig); - logger.info("Resolving database driver..."); - final DriverDependencyLoader databaseDependencyLoader = new DriverDependencyLoader(plugin); - databaseDependencyLoader.loadDriverFor(databaseConfig.databaseMode); - - logger.info("Connecting to database..."); - databaseConnector = new DatabaseConnector(logger, databaseConfig); + databaseManager.loadDriver(); try { - databaseConnector.connect(plugin.getDataFolder()); + databaseManager.connect(); } catch (SQLException e) { - logger.error(e, "Failed to connect database."); - throw new IllegalStateException("Database initialization failed", e); + logger.error(e, "An error occurred while trying to start all repositories. Disabling plugin..."); + plugin.getPluginLoader().disablePlugin(plugin); + throw new IllegalStateException("Repository startup failed", e); } // Infrastructure services @@ -145,17 +143,16 @@ void enable( guiRegistry = new GuiRegistry(); placeholderAdapter = PlaceholderAdapterFactory.createFor(plugin, server, logger); - LiteCommandsRegistrar = new BukkitLiteCommandsRegistrar(); - LiteCommandsRegistrar.configure(builder -> { - builder.invalidUsage(new InvalidUsageHandlerImpl(messageService)); - builder.missingPermission(new MissingPermissionsHandlerImpl(messageService)); - builder.result(Notice.class, new NoticeResultHandlerImpl(messageService)); - }); + liteCommandsBuilder = LiteBukkitFactory.builder(PREFIX, plugin, server); + liteCommandsBuilder + .invalidUsage(new InvalidUsageHandlerImpl(messageService)) + .missingPermission(new MissingPermissionsHandlerImpl(messageService)) + .result(Notice.class, new NoticeResultHandlerImpl(messageService)); // Dependency Injection injector = DependencyInjection.createInjector(resources -> { - new PlayTimeCoreBinder(this).bind(resources); - ConfigBinder.bind(resources, configManager.getConfigs()); + new PlayTimeBinder(this).bind(resources); + InjectorConfigBinder.bind(resources, configManager.getConfigs()); }); // Module initialization @@ -168,7 +165,7 @@ void enable( initializer.registerRepositories(); // Start repositories - Validator.ifNotNull(databaseConnector.getConnectionSource(), connection -> { + Validator.ifNotNull(databaseManager.getConnection(), connection -> { try { repositoryManager.startAll(connection); } catch (SQLException e) { @@ -181,8 +178,8 @@ void enable( // Activate all feature modules initializer.activateFeatures(); - // Build and register commands - liteCommands = LiteCommandsRegistrar.create(PREFIX, plugin, server); + // Build commands + liteCommands = liteCommandsBuilder.build(); // Metrics metrics = new Metrics(plugin, PLUGIN_METRICS_ID); @@ -197,11 +194,11 @@ void enable( void disable() { Validator.ifNotNull(configManager, (manager) -> { - manager.saveAllSync(); - manager.shutdown(); + manager.saveAll(); + manager.clearAll(); }); Validator.ifNotNull(repositoryManager, RepositoryManager::close); - Validator.ifNotNull(databaseConnector, DatabaseConnector::close); + Validator.ifNotNull(databaseManager, DatabaseManager::shutdown); Validator.ifNotNull(messageService, MessageService::shutdown); Validator.ifNotNull(taskScheduler, TaskScheduler::shutdown); Validator.ifNotNull(liteCommands, LiteCommands::unregister); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigAccessException.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigAccessException.java new file mode 100644 index 0000000..4acb9e5 --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigAccessException.java @@ -0,0 +1,17 @@ +package com.github.imdmk.playtime.config; + +public class ConfigAccessException extends RuntimeException { + + public ConfigAccessException(String message) { + super(message); + } + + public ConfigAccessException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigAccessException(Throwable cause) { + super(cause); + } +} + diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigBinder.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigBinder.java new file mode 100644 index 0000000..f0b2f6f --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigBinder.java @@ -0,0 +1,26 @@ +package com.github.imdmk.playtime.config; + +import com.github.imdmk.playtime.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) + .withSerdesPack(new SerdesCommons()) + .withBindFile(file) + .withRemoveOrphans(true); + } +} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigFactory.java new file mode 100644 index 0000000..2327c7a --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigFactory.java @@ -0,0 +1,22 @@ +package com.github.imdmk.playtime.config; + +import com.github.imdmk.playtime.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"); + + try { + return ConfigManager.create(type); + } catch (OkaeriException e) { + throw new IllegalStateException( + "Failed to instantiate config: " + type.getName(), e + ); + } + } +} + diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigLifecycle.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigLifecycle.java new file mode 100644 index 0000000..78097f8 --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigLifecycle.java @@ -0,0 +1,39 @@ +package com.github.imdmk.playtime.config; + +import com.github.imdmk.playtime.platform.logger.PluginLogger; +import com.github.imdmk.playtime.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"); + } + + void initialize(@NotNull ConfigSection config) { + config.saveDefaults(); + load(config); + } + + void load(@NotNull ConfigSection config) { + try { + config.load(true); + } catch (OkaeriException e) { + logger.error(e, "Failed to load config %s", config.getClass().getSimpleName()); + throw new ConfigAccessException(e); + } + } + + void save(@NotNull ConfigSection config) { + try { + config.save(); + } catch (Exception e) { + logger.error(e, "Failed to save config %s", config.getClass().getSimpleName()); + throw new ConfigAccessException(e); + } + } +} + diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigManager.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigManager.java new file mode 100644 index 0000000..017ac9c --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigManager.java @@ -0,0 +1,85 @@ +package com.github.imdmk.playtime.config; + +import com.github.imdmk.playtime.platform.logger.PluginLogger; +import com.github.imdmk.playtime.shared.validate.Validator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public final class ConfigManager { + + private final Set configs = ConcurrentHashMap.newKeySet(); + private final Map, ConfigSection> byType = new ConcurrentHashMap<>(); + + private final File dataFolder; + + private final ConfigFactory factory; + private final ConfigBinder binder; + private final ConfigLifecycle lifecycle; + + public ConfigManager(@NotNull PluginLogger logger, @NotNull File dataFolder) { + this.dataFolder = Validator.notNull(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); + final File file = new File(dataFolder, config.getFileName()); + + binder.bind(config, file); + lifecycle.initialize(config); + + register(type, config); + return config; + } + + public void createAll(@NotNull List> types) { + types.forEach(this::create); + } + + @SuppressWarnings("unchecked") + public T get(@NotNull Class type) { + return (T) byType.get(type); + } + + public @NotNull T require(@NotNull Class type) { + T config = get(type); + + if (config == null) { + throw new IllegalStateException("Config not created: " + type.getName()); + } + + return config; + } + + public void loadAll() { + configs.forEach(lifecycle::load); + } + + public void saveAll() { + configs.forEach(lifecycle::save); + } + + public @NotNull @Unmodifiable Set getConfigs() { + return Collections.unmodifiableSet(configs); + } + + public void clearAll() { + configs.clear(); + byType.clear(); + } + + private void register(Class type, ConfigSection config) { + configs.add(config); + byType.put(type, config); + } +} \ No newline at end of file diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigRepresenter.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigRepresenter.java similarity index 93% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigRepresenter.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigRepresenter.java index f7ef2e5..0dd3c67 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigRepresenter.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigRepresenter.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.shared.config; +package com.github.imdmk.playtime.config; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.nodes.Node; @@ -11,9 +11,9 @@ import java.util.LinkedHashMap; import java.util.Map; -public final class ConfigRepresenter extends Representer { +final class ConfigRepresenter extends Representer { - public ConfigRepresenter(DumperOptions options) { + ConfigRepresenter(DumperOptions options) { super(options); this.representers.put(String.class, new RepresentString()); this.representers.put(Boolean.class, new RepresentBoolean()); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigSection.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigSection.java similarity index 95% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigSection.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigSection.java index 9abbcda..8aa1d87 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigSection.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/ConfigSection.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.shared.config; +package com.github.imdmk.playtime.config; import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.serdes.OkaeriSerdesPack; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/InjectorConfigBinder.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/InjectorConfigBinder.java new file mode 100644 index 0000000..c1ce395 --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/InjectorConfigBinder.java @@ -0,0 +1,53 @@ +package com.github.imdmk.playtime.config; + +import eu.okaeri.configs.OkaeriConfig; +import org.jetbrains.annotations.NotNull; +import org.panda_lang.utilities.inject.Resources; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; + +public final class InjectorConfigBinder { + + private InjectorConfigBinder() { + throw new UnsupportedOperationException("This is utility class and cannot be instantiated."); + } + + public static void bind(@NotNull Resources resources, @NotNull Set sections) { + final Set visited = Collections.newSetFromMap(new IdentityHashMap<>()); + for (final var section : sections) { + bindRecursive(resources, section, visited); + } + } + + private static void bindRecursive(@NotNull Resources resources, @NotNull Object object, @NotNull Set visited) { + if (!visited.add(object)) { + return; + } + + resources.on(object.getClass()).assignInstance(object); + + for (Class clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { + for (Field field : clazz.getDeclaredFields()) { + int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) { + continue; + } + + try { + field.setAccessible(true); + Object value = field.get(object); + if (value instanceof OkaeriConfig nested) { + bindRecursive(resources, nested, visited); + } + } catch (IllegalAccessException e) { + throw new IllegalStateException("Failed to bind config field: " + + clazz.getSimpleName() + "#" + field.getName(), e); + } + } + } + } +} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/PluginConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/PluginConfig.java similarity index 95% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/PluginConfig.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/config/PluginConfig.java index 3fc784f..b135f37 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/PluginConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/PluginConfig.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.shared.config; +package com.github.imdmk.playtime.config; import com.github.imdmk.playtime.shared.time.DurationFormatStyle; import eu.okaeri.configs.annotation.Comment; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/config/YamlConfigurerFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/config/YamlConfigurerFactory.java new file mode 100644 index 0000000..a00409a --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/config/YamlConfigurerFactory.java @@ -0,0 +1,36 @@ +package com.github.imdmk.playtime.config; + +import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.representer.Representer; +import org.yaml.snakeyaml.resolver.Resolver; + +final class YamlConfigurerFactory { + + private YamlConfigurerFactory() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated."); + } + + static YamlSnakeYamlConfigurer create() { + final LoaderOptions loader = new LoaderOptions(); + loader.setAllowRecursiveKeys(false); + loader.setMaxAliasesForCollections(50); + + final Constructor constructor = new Constructor(loader); + + final DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setIndent(2); + options.setSplitLines(false); + + final Representer representer = new ConfigRepresenter(options); + final Resolver resolver = new Resolver(); + + final Yaml yaml = new Yaml(constructor, representer, options, loader, resolver); + return new YamlSnakeYamlConfigurer(yaml); + } +} + diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationConfig.java index f4ebfae..7386c46 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationConfig.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.feature.migration; -import com.github.imdmk.playtime.shared.config.ConfigSection; +import com.github.imdmk.playtime.config.ConfigSection; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationModule.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationModule.java index bb0b71c..9e02c03 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationModule.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/MigrationModule.java @@ -31,8 +31,8 @@ public void afterRegister(@NotNull Plugin plugin, @NotNull Server server, @NotNu this.migrator = injector.newInstance(RepositoryPlayerMigrator.class); this.provider = injector.newInstance(BukkitPlayerProvider.class); - var blockingRunner = injector.newInstance(BlockingMigrationRunner.class); - blockingRunner.execute(); + final BlockingMigrationRunner migrationRunner = injector.newInstance(BlockingMigrationRunner.class); + migrationRunner.execute(); } @Override diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/ConfigMigrationListener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/ConfigMigrationListener.java index 637c3a0..2285ee5 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/ConfigMigrationListener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/ConfigMigrationListener.java @@ -2,7 +2,7 @@ import com.github.imdmk.playtime.feature.migration.MigrationConfig; import com.github.imdmk.playtime.feature.migration.MigrationResult; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; public final class ConfigMigrationListener implements MigrationListener { diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/LoggerMigrationListener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/LoggerMigrationListener.java index dfbda86..6a7b97f 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/LoggerMigrationListener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/LoggerMigrationListener.java @@ -2,7 +2,7 @@ import com.github.imdmk.playtime.feature.migration.MigrationResult; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/MigrationListener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/MigrationListener.java index 6d87115..6fcd36a 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/MigrationListener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/listener/MigrationListener.java @@ -5,42 +5,44 @@ import org.jetbrains.annotations.NotNull; /** - * Listener interface receiving callbacks about the lifecycle of a migration run. + * Listener interface for receiving callbacks during a playtime data migration process. * - *

Implementations may use these callbacks to provide progress logging, - * UI updates, console output, or metrics tracking.

+ *

This listener allows external components to observe and react to the + * lifecycle of a migration operation – from start, through per-player + * results, to the final completion summary.

* - *

All callbacks are invoked synchronously by the {@code MigrationRunner}, - * unless explicitly documented otherwise.

+ *

All methods are optional; implementations may override only the events + * they are interested in.

*/ public interface MigrationListener { /** - * Called once when the migration process begins. + * Called when the migration process begins. * * @param total total number of players scheduled for migration */ default void onStart(int total) {} /** - * Called when a single player has been migrated successfully. + * Called when a player's data has been migrated successfully. * - * @param player the player that was successfully migrated + * @param player the offline player whose migration completed successfully */ default void onSuccess(@NotNull OfflinePlayer player) {} /** - * Called when migration of a player fails. + * Called when a player's migration fails due to an unexpected error. * - * @param player the player for whom migration failed - * @param throwable the error describing the reason for failure + * @param player the offline player whose migration failed + * @param throwable the exception that caused the failure */ default void onFailed(@NotNull OfflinePlayer player, @NotNull Throwable throwable) {} /** - * Called once when the entire migration process has finished. + * Called when the migration process has completed for all players. * - * @param result aggregated migration summary, including statistics and duration + * @param result summary of the migration, including counts of successes, failures, + * and total processed players */ default void onEnd(@NotNull MigrationResult result) {} } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/PlayerMigrator.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/PlayerMigrator.java index e51509b..7dbffd6 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/PlayerMigrator.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/PlayerMigrator.java @@ -7,16 +7,20 @@ import java.util.concurrent.CompletableFuture; /** - * Functional abstraction responsible for migrating playtime data - * for a single {@link OfflinePlayer} into the plugin’s {@link User} - * domain model. + * Strategy interface responsible for migrating playtime data for a single + * {@link OfflinePlayer} into the plugin’s internal {@link User} domain model. * - *

This interface is typically implemented by migration strategies - * used during the initial setup or data import from legacy systems - * (e.g., Bukkit statistics API, flat files, other plugins, external databases).

+ *

Implementations of this interface define how legacy or external data sources + * (e.g., Bukkit statistics API, flat files, third-party plugins, SQL tables) + * are translated into the unified User format used by the PlayTime system.

* - *

The migration is asynchronous and must never block the server thread. - * Implementations should perform I/O or heavy operations on background executors.

+ *

Async contract:
+ * The migration operation must be non-blocking and executed asynchronously. + * All heavy computation and I/O must run off the main server thread. + * The returned {@link CompletableFuture} represents the result of the migration.

+ * + *

This interface is commonly used by bulk migration processes that iterate + * through all stored players and invoke this migrator per user.

*/ @FunctionalInterface public interface PlayerMigrator { @@ -25,8 +29,8 @@ public interface PlayerMigrator { * Migrates playtime data for the given {@link OfflinePlayer}. * * @param player the offline player whose data should be migrated (never null) - * @return a future completing with the migrated {@link User}, - * or completing exceptionally if migration fails + * @return a future completing with the migrated {@link User} instance, + * or completing exceptionally if the migration fails */ CompletableFuture migrate(@NotNull OfflinePlayer player); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/RepositoryPlayerMigrator.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/RepositoryPlayerMigrator.java index 21e564b..fbaaba5 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/RepositoryPlayerMigrator.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/migrator/RepositoryPlayerMigrator.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.feature.migration.migrator; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserFactory; import com.github.imdmk.playtime.user.repository.UserRepository; @@ -16,7 +16,10 @@ public final class RepositoryPlayerMigrator implements PlayerMigrator { private final UserFactory userFactory; @Inject - public RepositoryPlayerMigrator(@NotNull UserRepository userRepository, @NotNull UserFactory userFactory) { + public RepositoryPlayerMigrator( + @NotNull UserRepository userRepository, + @NotNull UserFactory userFactory + ) { this.userRepository = Validator.notNull(userRepository, "userRepository cannot be null"); this.userFactory = Validator.notNull(userFactory, "userFactory cannot be null"); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/provider/BukkitPlayerProvider.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/provider/BukkitPlayerProvider.java index 2fb4003..2381519 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/provider/BukkitPlayerProvider.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/provider/BukkitPlayerProvider.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.feature.migration.provider; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/AsyncMigrationRunner.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/AsyncMigrationRunner.java index c4dd082..f961edf 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/AsyncMigrationRunner.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/AsyncMigrationRunner.java @@ -8,7 +8,7 @@ import com.github.imdmk.playtime.feature.migration.migrator.PlayerMigrator; import com.github.imdmk.playtime.feature.migration.provider.PlayerProvider; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.annotations.Inject; import org.panda_lang.utilities.inject.annotations.PostConstruct; @@ -41,7 +41,8 @@ public AsyncMigrationRunner( @NotNull PluginLogger logger, @NotNull MigrationConfig config, @NotNull PlayerProvider provider, - @NotNull PlayerMigrator migrator) { + @NotNull PlayerMigrator migrator + ) { this.logger = Validator.notNull(logger, "logger cannot be null"); this.config = Validator.notNull(config, "config cannot be null"); this.provider = Validator.notNull(provider, "provider cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/BlockingMigrationRunner.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/BlockingMigrationRunner.java index b0cdf9a..5a2ae6c 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/BlockingMigrationRunner.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/BlockingMigrationRunner.java @@ -8,7 +8,7 @@ import com.github.imdmk.playtime.feature.migration.migrator.PlayerMigrator; import com.github.imdmk.playtime.feature.migration.provider.PlayerProvider; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.annotations.Inject; @@ -26,7 +26,8 @@ public BlockingMigrationRunner( @NotNull PluginLogger logger, @NotNull MigrationConfig config, @NotNull PlayerProvider provider, - @NotNull PlayerMigrator migrator) { + @NotNull PlayerMigrator migrator + ) { this.logger = Validator.notNull(logger, "logger cannot be null"); this.config = Validator.notNull(config, "config cannot be null"); this.provider = Validator.notNull(provider, "provider cannot be null"); @@ -35,7 +36,7 @@ public BlockingMigrationRunner( @Override public MigrationResult execute() { - var runner = new MigrationRunnerImpl(config, provider, migrator, listeners()); + final var runner = new MigrationRunnerImpl(config, provider, migrator, listeners()); return runner.execute(); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/MigrationRunnerImpl.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/MigrationRunnerImpl.java index 9f33e7a..e463420 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/MigrationRunnerImpl.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/migration/runner/MigrationRunnerImpl.java @@ -5,7 +5,7 @@ import com.github.imdmk.playtime.feature.migration.listener.MigrationListener; import com.github.imdmk.playtime.feature.migration.migrator.PlayerMigrator; import com.github.imdmk.playtime.feature.migration.provider.PlayerProvider; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.google.common.base.Stopwatch; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; @@ -30,7 +30,8 @@ final class MigrationRunnerImpl { @NotNull MigrationConfig config, @NotNull PlayerProvider provider, @NotNull PlayerMigrator migrator, - @NotNull List listeners) { + @NotNull List listeners + ) { this.config = Validator.notNull(config, "config cannot be null"); this.provider = Validator.notNull(provider, "provider cannot be null"); this.migrator = Validator.notNull(migrator, "migrator cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/BukkitPlayTimeService.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/BukkitPlayTimeService.java index c4aac27..f9d48c2 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/BukkitPlayTimeService.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/BukkitPlayTimeService.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.feature.playtime; import com.github.imdmk.playtime.PlaytimeService; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.UserTime; import org.bukkit.OfflinePlayer; import org.bukkit.Server; @@ -34,7 +34,7 @@ final class BukkitPlayTimeService implements PlaytimeService { @Inject BukkitPlayTimeService(@NotNull Server server) { - this.server = Validator.notNull(server, "server cannot be null"); + this.server = Validator.notNull(server, "server"); } /** diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeModule.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeModule.java index 995faa5..bad056f 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeModule.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeModule.java @@ -39,7 +39,7 @@ public void init(@NotNull Injector injector) { @Override public CommandPhase commands(@NotNull Injector injector) { - return configurer -> configurer.registerCommands( + return builder -> builder.commands( injector.newInstance(TimeCommand.class), injector.newInstance(TimeSetCommand.class), injector.newInstance(TimeTopCommand.class), @@ -51,7 +51,7 @@ public CommandPhase commands(@NotNull Injector injector) { @Override public ListenerPhase listeners(@NotNull Injector injector) { - return configurer -> configurer.register( + return builder -> builder.register( injector.newInstance(PlayTimeSaveListener.class) ); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeUserFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeUserFactory.java index 412ee56..03b7552 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeUserFactory.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/PlayTimeUserFactory.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.feature.playtime; import com.github.imdmk.playtime.PlaytimeService; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserFactory; import com.github.imdmk.playtime.user.UserTime; @@ -35,7 +35,7 @@ public final class PlayTimeUserFactory implements UserFactory { @Inject public PlayTimeUserFactory(@NotNull PlaytimeService playtimeService) { - this.playtimeService = Validator.notNull(playtimeService, "playtimeService cannot be null"); + this.playtimeService = Validator.notNull(playtimeService, "playtimeService"); } /** diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeCommand.java index b2f64fa..b97e2f0 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeCommand.java @@ -1,9 +1,9 @@ package com.github.imdmk.playtime.feature.playtime.command; import com.github.imdmk.playtime.PlaytimeService; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.shared.time.Durations; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserTime; import dev.rollczi.litecommands.annotations.argument.Arg; @@ -23,7 +23,10 @@ public final class TimeCommand { private final PlaytimeService playtimeService; @Inject - public TimeCommand(@NotNull MessageService messageService, @NotNull PlaytimeService playtimeService) { + public TimeCommand( + @NotNull MessageService messageService, + @NotNull PlaytimeService playtimeService + ) { this.messageService = Validator.notNull(messageService, "messageService cannot be null"); this.playtimeService = Validator.notNull(playtimeService, "playtimeService cannot be null"); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetAllCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetAllCommand.java index 2608811..734463e 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetAllCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetAllCommand.java @@ -1,10 +1,10 @@ package com.github.imdmk.playtime.feature.playtime.command; import com.github.imdmk.playtime.PlaytimeService; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.platform.logger.PluginLogger; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserSaveReason; import com.github.imdmk.playtime.user.UserService; @@ -45,7 +45,8 @@ public TimeResetAllCommand( @NotNull PlaytimeService playtimeService, @NotNull UserService userService, @NotNull UserRepository userRepository, - @NotNull TaskScheduler taskScheduler) { + @NotNull TaskScheduler taskScheduler + ) { this.server = Validator.notNull(server, "server cannot be null"); this.logger = Validator.notNull(logger, "logger cannot be null"); this.messageService = Validator.notNull(messageService, "messageService cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetCommand.java index 5c8df58..a48e233 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeResetCommand.java @@ -1,8 +1,8 @@ package com.github.imdmk.playtime.feature.playtime.command; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserSaveReason; import com.github.imdmk.playtime.user.UserService; @@ -31,7 +31,8 @@ public final class TimeResetCommand { public TimeResetCommand( @NotNull PluginLogger logger, @NotNull MessageService messageService, - @NotNull UserService userService) { + @NotNull UserService userService + ) { this.logger = Validator.notNull(logger, "logger cannot be null"); this.messageService = Validator.notNull(messageService, "messageService cannot be null"); this.userService = Validator.notNull(userService, "userService cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeSetCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeSetCommand.java index 0ce88ec..4b01fa6 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeSetCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeSetCommand.java @@ -1,9 +1,9 @@ package com.github.imdmk.playtime.feature.playtime.command; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; import com.github.imdmk.playtime.shared.time.Durations; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserSaveReason; import com.github.imdmk.playtime.user.UserService; @@ -29,7 +29,11 @@ public final class TimeSetCommand { private final UserService userService; @Inject - public TimeSetCommand(@NotNull PluginLogger logger, @NotNull MessageService messageService, @NotNull UserService userService) { + public TimeSetCommand( + @NotNull PluginLogger logger, + @NotNull MessageService messageService, + @NotNull UserService userService + ) { this.logger = Validator.notNull(logger, "logger cannot be null"); this.messageService = Validator.notNull(messageService, "messageService cannot be null"); this.userService = Validator.notNull(userService, "userService cannot be null"); @@ -43,7 +47,7 @@ void setPlaytime(@Context CommandSender sender, @Arg @Async User target, @Arg Du target.setPlaytime(newTime); userService.save(target, UserSaveReason.SET_COMMAND) - .thenAccept(r -> messageService.create() + .thenAccept(v -> messageService.create() .notice(n -> n.playtimeMessages.playerPlaytimeUpdated()) .placeholder("{PLAYER_NAME}", target.getName()) .placeholder("{PLAYER_PLAYTIME}", Durations.format(normalizedTime)) diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopCommand.java index e4e77b7..6c2ca89 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopCommand.java @@ -1,10 +1,10 @@ package com.github.imdmk.playtime.feature.playtime.command; import com.github.imdmk.playtime.feature.playtime.gui.PlayTimeTopGui; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.platform.gui.view.GuiOpener; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.UserService; import dev.rollczi.litecommands.annotations.command.Command; import dev.rollczi.litecommands.annotations.context.Context; @@ -30,7 +30,8 @@ public TimeTopCommand( @NotNull PluginLogger logger, @NotNull MessageService messageService, @NotNull UserService userService, - @NotNull GuiOpener guiOpener) { + @NotNull GuiOpener guiOpener + ) { this.logger = Validator.notNull(logger, "logger cannot be null"); this.messageService = Validator.notNull(messageService, "messageService cannot be null"); this.userService = Validator.notNull(userService, "userService cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopInvalidateCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopInvalidateCommand.java index 37ffb53..78f5dc9 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopInvalidateCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/command/TimeTopInvalidateCommand.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.feature.playtime.command; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.top.TopUsersCache; import dev.rollczi.litecommands.annotations.command.Command; import dev.rollczi.litecommands.annotations.context.Context; @@ -19,7 +19,10 @@ public final class TimeTopInvalidateCommand { private final TopUsersCache topUsersCache; @Inject - public TimeTopInvalidateCommand(@NotNull MessageService messageService, @NotNull TopUsersCache topUsersCache) { + public TimeTopInvalidateCommand( + @NotNull MessageService messageService, + @NotNull TopUsersCache topUsersCache + ) { this.messageService = Validator.notNull(messageService, "messageService cannot be null"); this.topUsersCache = Validator.notNull(topUsersCache, "topUsersCache cannot be null"); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGui.java index 085ddb1..004cc9e 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGui.java @@ -1,5 +1,9 @@ package com.github.imdmk.playtime.feature.playtime.gui; +import com.github.imdmk.playtime.message.MessageService; +import com.github.imdmk.playtime.platform.adventure.AdventureFormatter; +import com.github.imdmk.playtime.platform.adventure.AdventurePlaceholders; +import com.github.imdmk.playtime.platform.gui.GuiType; import com.github.imdmk.playtime.platform.gui.config.NavigationBarConfig; import com.github.imdmk.playtime.platform.gui.factory.GuiFactory; import com.github.imdmk.playtime.platform.gui.item.ItemGui; @@ -13,12 +17,8 @@ import com.github.imdmk.playtime.platform.gui.view.AbstractGui; import com.github.imdmk.playtime.platform.gui.view.ParameterizedGui; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.adventure.AdventureFormatter; -import com.github.imdmk.playtime.shared.adventure.AdventurePlaceholders; -import com.github.imdmk.playtime.shared.gui.GuiType; -import com.github.imdmk.playtime.shared.message.MessageService; import com.github.imdmk.playtime.shared.time.Durations; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserSaveReason; import com.github.imdmk.playtime.user.UserService; @@ -40,6 +40,7 @@ public final class PlayTimeTopGui implements ParameterizedGui> { private static final String GUI_IDENTIFIER = "playtime-top"; + private static final UserSaveReason SAVE_REASON = UserSaveReason.GUI_RESET_CLICK; private static final GuiRenderer GUI_RENDERER = TriumphGuiRenderer.newRenderer(); private static final RenderOptions RENDER_OPTIONS = RenderOptions.defaultHide(); @@ -57,9 +58,10 @@ public PlayTimeTopGui( @NotNull PlayTimeTopGuiConfig topGuiConfig, @NotNull TaskScheduler taskScheduler, @NotNull MessageService messageService, - @NotNull UserService userService) { + @NotNull UserService userService + ) { super(navigationBarConfig, taskScheduler, GUI_RENDERER, RENDER_OPTIONS); - this.server = Validator.notNull(server, "server cannot be null"); + this.server = Validator.notNull(server, "server"); this.topGuiConfig = Validator.notNull(topGuiConfig, "playtimeTopGuiConfig cannot be null"); this.messageService = Validator.notNull(messageService, "messageService cannot be null"); this.userService = Validator.notNull(userService, "userService cannot be null"); @@ -107,8 +109,8 @@ public void prepareItems(@NotNull BaseGui gui, @NotNull Player viewer, @NotNull gui.close(viewer); user.setPlaytime(UserTime.ZERO); - userService.save(user, UserSaveReason.GUI_RESET_CLICK) - .thenAccept(result -> messageService.send(viewer, n -> n.playtimeMessages.playerPlaytimeReset)) + userService.save(user, SAVE_REASON) + .thenAccept(result -> messageService.send(viewer, n -> n.playtimeMessages.playerPlaytimeReset())) .exceptionally(e -> { messageService.send(viewer, n -> n.actionExecutionError); return null; @@ -144,13 +146,6 @@ private AdventurePlaceholders createPlaceholders(User topUser, int position) { .build(); } - private void resetPlayTimeFor(Player viewer, User user) { - viewer.closeInventory(); - - user.setPlaytime(UserTime.ZERO); - userService.save(user, UserSaveReason.GUI_RESET_CLICK); - } - @Override public @NotNull String getId() { return GUI_IDENTIFIER; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGuiConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGuiConfig.java index d562b14..fd0bab0 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGuiConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/gui/PlayTimeTopGuiConfig.java @@ -1,9 +1,9 @@ package com.github.imdmk.playtime.feature.playtime.gui; +import com.github.imdmk.playtime.platform.adventure.AdventureComponents; +import com.github.imdmk.playtime.platform.gui.GuiType; import com.github.imdmk.playtime.platform.gui.config.ConfigurableGui; import com.github.imdmk.playtime.platform.gui.item.ItemGui; -import com.github.imdmk.playtime.shared.adventure.AdventureComponents; -import com.github.imdmk.playtime.shared.gui.GuiType; import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; import net.kyori.adventure.text.Component; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/listener/PlayTimeSaveListener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/listener/PlayTimeSaveListener.java index 3ee418e..d1d0a78 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/listener/PlayTimeSaveListener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/listener/PlayTimeSaveListener.java @@ -3,7 +3,7 @@ import com.github.imdmk.playtime.PlaytimeService; import com.github.imdmk.playtime.UserPreSaveEvent; import com.github.imdmk.playtime.UserSaveEvent; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserSaveReason; import com.github.imdmk.playtime.user.UserTime; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/messages/ENPlayTimeMessages.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/messages/ENPlayTimeMessages.java index 29373e9..b4e1ff4 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/messages/ENPlayTimeMessages.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/messages/ENPlayTimeMessages.java @@ -14,7 +14,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# {PLAYER_PLAYTIME} - formatted playtime of the player (e.g. 5h 32m).", "#" }) - public Notice playerPlaytimeSelf = Notice.chat( + Notice playerPlaytimeSelf = Notice.chat( "You have spent {PLAYER_PLAYTIME} on this server." ); @@ -27,7 +27,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# {PLAYER_PLAYTIME} - formatted playtime of the target player.", "#" }) - public Notice playerPlaytimeTarget = Notice.chat( + Notice playerPlaytimeTarget = Notice.chat( "Player {PLAYER_NAME} has spent {PLAYER_PLAYTIME} on this server." ); @@ -40,7 +40,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# {PLAYER_PLAYTIME} - new formatted playtime value.", "#" }) - public Notice playerPlaytimeUpdated = Notice.chat( + Notice playerPlaytimeUpdated = Notice.chat( "Updated playtime for player {PLAYER_NAME} to {PLAYER_PLAYTIME}." ); @@ -52,7 +52,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# {PLAYER_NAME} - target player's nickname.", "#" }) - public Notice playerPlaytimeReset = Notice.chat( + Notice playerPlaytimeReset = Notice.chat( "Playtime for player {PLAYER_NAME} has been reset to ZERO." ); @@ -61,7 +61,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# Sent when a global reset of all players' playtime is triggered.", "#" }) - public Notice playerPlaytimeResetAllStarted = Notice.chat( + Notice playerPlaytimeResetAllStarted = Notice.chat( "Global playtime reset started... Please wait." ); @@ -70,7 +70,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# Sent to the executor if the global playtime reset fails.", "#" }) - public Notice playerPlaytimeResetAllFailed = Notice.chat( + Notice playerPlaytimeResetAllFailed = Notice.chat( "An error occurred while resetting playtime for all players. " + "Check console for details." ); @@ -80,7 +80,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# Sent when the global playtime reset finishes successfully.", "#" }) - public Notice playerPlaytimeResetAllFinished = Notice.chat( + Notice playerPlaytimeResetAllFinished = Notice.chat( "Successfully reset playtime for all stored players." ); @@ -89,7 +89,7 @@ public final class ENPlayTimeMessages extends OkaeriConfig implements PlayTimeMe "# Sent after invalidating the Top users playtime cache.", "#" }) - public Notice topUsersCacheInvalidated = Notice.chat( + Notice topUsersCacheInvalidated = Notice.chat( "Successfully invalidated the PlayTime Top cache." ); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/placeholder/PlayTimePlaceholder.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/placeholder/PlayTimePlaceholder.java index 1fa960f..1f3a1f3 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/placeholder/PlayTimePlaceholder.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/playtime/placeholder/PlayTimePlaceholder.java @@ -2,8 +2,8 @@ import com.github.imdmk.playtime.PlaytimeService; import com.github.imdmk.playtime.platform.placeholder.PluginPlaceholder; -import com.github.imdmk.playtime.shared.Validator; import com.github.imdmk.playtime.shared.time.Durations; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadCommand.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadCommand.java index 9b83cf1..8819020 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadCommand.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadCommand.java @@ -1,13 +1,15 @@ package com.github.imdmk.playtime.feature.reload; +import com.github.imdmk.playtime.config.ConfigManager; +import com.github.imdmk.playtime.message.MessageService; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.config.ConfigManager; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; +import com.github.imdmk.playtime.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 eu.okaeri.configs.exception.OkaeriException; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.annotations.Inject; @@ -18,23 +20,32 @@ public final class ReloadCommand { private final PluginLogger logger; private final ConfigManager configManager; + private final TaskScheduler taskScheduler; private final MessageService messageService; @Inject - public ReloadCommand(@NotNull PluginLogger logger, @NotNull ConfigManager configManager, @NotNull MessageService messageService) { - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.configManager = Validator.notNull(configManager, "configManager cannot be null"); - this.messageService = Validator.notNull(messageService, "messageService cannot be null"); + public ReloadCommand( + @NotNull PluginLogger logger, + @NotNull ConfigManager configManager, + @NotNull TaskScheduler taskScheduler, + @NotNull 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"); } @Execute void reload(@Context CommandSender sender) { - configManager.loadAll() - .thenRun(() -> messageService.send(sender, n -> n.reloadMessages.configReloadedSuccess())) - .exceptionally(e -> { - logger.error(e, "Failed to reload plugin configuration files"); - messageService.send(sender, n -> n.reloadMessages.configReloadFailed()); - return null; - }); + taskScheduler.runAsync(() -> { + try { + configManager.loadAll(); + messageService.send(sender, n -> n.reloadMessages.configReloadedSuccess()); + } catch (OkaeriException e) { + logger.error(e, "Failed to reload plugin configuration files"); + messageService.send(sender, n -> n.reloadMessages.configReloadFailed()); + } + }); } } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadModule.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadModule.java index 4ab1f4e..d3b6dbc 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadModule.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/ReloadModule.java @@ -16,6 +16,6 @@ public void init(@NotNull Injector injector) {} @Override public CommandPhase commands(@NotNull Injector injector) { - return configurer -> configurer.registerCommands(injector.newInstance(ReloadCommand.class)); + return builder -> builder.commands(injector.newInstance(ReloadCommand.class)); } } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/messages/ENReloadMessages.java b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/messages/ENReloadMessages.java index cace384..1cacaa0 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/messages/ENReloadMessages.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/feature/reload/messages/ENReloadMessages.java @@ -10,7 +10,7 @@ public final class ENReloadMessages extends OkaeriConfig implements ReloadMessag "# Sent when configuration files for the PlayTime plugin have been reloaded successfully.", "# Used after a reload command is executed." }) - public Notice configReloadedSuccess = Notice.chat( + Notice configReloadedSuccess = Notice.chat( "PlayTime configuration has been reloaded successfully." ); @@ -20,7 +20,7 @@ public final class ENReloadMessages extends OkaeriConfig implements ReloadMessag "# ", "# Note: No placeholders." }) - public Notice configReloadFailed = Notice.chat( + Notice configReloadFailed = Notice.chat( "Failed to reload PlayTime configuration files. " + "Disable the plugin and verify your config files." ); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConfig.java index 6bd54e5..58c6d18 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConfig.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.infrastructure.database; -import com.github.imdmk.playtime.shared.config.ConfigSection; +import com.github.imdmk.playtime.config.ConfigSection; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConnector.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConnector.java index 91fb732..5da685e 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConnector.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseConnector.java @@ -3,7 +3,7 @@ import com.github.imdmk.playtime.infrastructure.database.driver.configurer.DriverConfigurer; import com.github.imdmk.playtime.infrastructure.database.driver.configurer.DriverConfigurerFactory; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.j256.ormlite.jdbc.DataSourceConnectionSource; import com.j256.ormlite.support.ConnectionSource; import com.zaxxer.hikari.HikariDataSource; @@ -15,30 +15,12 @@ import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Level; -/** - * Provides a unified connection management layer between HikariCP and ORMLite. - *

- * This class is responsible for: - *

    - *
  • creating and configuring a shared {@link HikariDataSource} with sane defaults,
  • - *
  • delegating engine-specific JDBC configuration to a {@link DriverConfigurer},
  • - *
  • exposing an ORMLite {@link ConnectionSource} to repository code,
  • - *
  • managing a clean connecting → use → close lifecycle.
  • - *
- *

- * The selection of JDBC driver and engine-specific URL/flags is handled externally - * by {@link DriverConfigurer} implementations and {@link DriverConfigurerFactory}, - * keeping this class focused purely on connection management. - * - *

Thread-safety: {@link #connect(File)} and {@link #close()} are synchronized. - * Concurrent read access via {@link #getConnectionSource()} is safe.

- */ -public final class DatabaseConnector { +final class DatabaseConnector { private static final String POOL_NAME = "playtime-db-pool"; - private static final int DEFAULT_MAX_POOL_SIZE = 5; - private static final int DEFAULT_MIN_IDLE = 1; + private static final int DEFAULT_MAX_POOL_SIZE = 4; + private static final int DEFAULT_MIN_IDLE = 0; private static final long DEFAULT_CONNECTION_TIMEOUT_MS = 10_000L; private static final long DEFAULT_IDLE_TIMEOUT_MS = 60_000L; @@ -66,7 +48,7 @@ public final class DatabaseConnector { * @param config the database configuration (never null) * @param driverConfigurer strategy used to configure the underlying JDBC driver (never null) */ - public DatabaseConnector( + DatabaseConnector( @NotNull PluginLogger logger, @NotNull DatabaseConfig config, @NotNull DriverConfigurer driverConfigurer @@ -83,7 +65,10 @@ public DatabaseConnector( * @param logger the plugin logger (never null) * @param config the database configuration (never null) */ - public DatabaseConnector(@NotNull PluginLogger logger, @NotNull DatabaseConfig config) { + DatabaseConnector( + @NotNull PluginLogger logger, + @NotNull DatabaseConfig config + ) { this(logger, config, DriverConfigurerFactory.getFor(config.databaseMode)); } @@ -98,7 +83,7 @@ public DatabaseConnector(@NotNull PluginLogger logger, @NotNull DatabaseConfig c * @throws SQLException if JDBC or ORMLite initialization fails * @throws IllegalStateException if a connection is already active */ - public synchronized void connect(@NotNull File dataFolder) throws SQLException { + synchronized void connect(@NotNull File dataFolder) throws SQLException { Validator.notNull(dataFolder, "dataFolder cannot be null"); if (dataSource != null || connectionSource != null) { @@ -111,7 +96,12 @@ public synchronized void connect(@NotNull File dataFolder) throws SQLException { // Delegated engine-specific configuration (JDBC URL, engine flags, filesystem prep) driverConfigurer.configure(ds, config, dataFolder); - final ConnectionSource source = new DataSourceConnectionSource(ds, ds.getJdbcUrl()); + final String jdbcUrl = ds.getJdbcUrl(); + if (jdbcUrl == null || jdbcUrl.isBlank()) { + throw new IllegalStateException("DriverConfigurer did not set JDBC URL for mode " + config.databaseMode); + } + + final ConnectionSource source = new DataSourceConnectionSource(ds, jdbcUrl); dataSource = ds; connectionSource = source; @@ -137,7 +127,7 @@ public synchronized void connect(@NotNull File dataFolder) throws SQLException { *

* Safe to call multiple times. Exceptions during close are logged but ignored. */ - public synchronized void close() { + synchronized void close() { if (connectionSource == null && dataSource == null) { logger.warn("DatabaseConnector#close() called, but not connected."); return; @@ -164,7 +154,7 @@ public synchronized void close() { * * @return {@code true} if both {@link ConnectionSource} and {@link HikariDataSource} are active */ - public boolean isConnected() { + boolean isConnected() { final HikariDataSource ds = dataSource; return connectionSource != null && ds != null && !ds.isClosed(); } @@ -174,7 +164,7 @@ public boolean isConnected() { * * @return active ORMLite connection source, or {@code null} if disconnected */ - public @Nullable ConnectionSource getConnectionSource() { + @Nullable ConnectionSource getConnectionSource() { return connectionSource; } @@ -194,7 +184,7 @@ public boolean isConnected() { final HikariDataSource data = new HikariDataSource(); data.setPoolName(POOL_NAME); - data.setMaximumPoolSize(DEFAULT_MAX_POOL_SIZE); + data.setMaximumPoolSize(Math.max(DEFAULT_MAX_POOL_SIZE, Runtime.getRuntime().availableProcessors())); data.setMinimumIdle(DEFAULT_MIN_IDLE); data.setUsername(config.databaseUserName); @@ -229,7 +219,6 @@ private static void closeQuietly(@Nullable HikariDataSource ds) { if (ds != null) { ds.close(); } - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseManager.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseManager.java new file mode 100644 index 0000000..46d50e8 --- /dev/null +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/DatabaseManager.java @@ -0,0 +1,51 @@ +package com.github.imdmk.playtime.infrastructure.database; + +import com.github.imdmk.playtime.infrastructure.database.driver.dependency.DriverDependencyLoader; +import com.github.imdmk.playtime.platform.logger.PluginLogger; +import com.github.imdmk.playtime.shared.validate.Validator; +import com.j256.ormlite.support.ConnectionSource; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.sql.SQLException; + +public final class DatabaseManager { + + private final Plugin plugin; + private final DatabaseConfig config; + + private final DriverDependencyLoader driverLoader; + private final DatabaseConnector connector; + + public DatabaseManager( + @NotNull Plugin plugin, + @NotNull PluginLogger logger, + @NotNull DatabaseConfig config + ) { + this.plugin = Validator.notNull(plugin, "plugin"); + this.config = Validator.notNull(config, "config"); + + this.driverLoader = new DriverDependencyLoader(plugin); + this.connector = new DatabaseConnector(logger, config); + } + + public void loadDriver() { + driverLoader.loadDriverFor(config.databaseMode); + } + + public void connect() throws SQLException { + connector.connect(plugin.getDataFolder()); + } + + @Nullable + public ConnectionSource getConnection() { + return connector.getConnectionSource(); + } + + public void shutdown() { + if (connector.isConnected()) { + connector.close(); + } + } +} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/configurer/DriverConfigurerFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/configurer/DriverConfigurerFactory.java index c0f00ce..4085841 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/configurer/DriverConfigurerFactory.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/configurer/DriverConfigurerFactory.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.infrastructure.database.driver.configurer; import com.github.imdmk.playtime.infrastructure.database.DatabaseMode; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import java.util.Map; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/dependency/DriverDependencyLoader.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/dependency/DriverDependencyLoader.java index dee1922..f10cf1a 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/dependency/DriverDependencyLoader.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/driver/dependency/DriverDependencyLoader.java @@ -3,7 +3,7 @@ import com.alessiodp.libby.BukkitLibraryManager; import com.alessiodp.libby.Library; import com.github.imdmk.playtime.infrastructure.database.DatabaseMode; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/RepositoryManager.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/RepositoryManager.java index 2754660..9258eb7 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/RepositoryManager.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/RepositoryManager.java @@ -2,7 +2,7 @@ import com.github.imdmk.playtime.infrastructure.database.repository.ormlite.BaseDaoRepository; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.j256.ormlite.support.ConnectionSource; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/ormlite/BaseDaoRepository.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/ormlite/BaseDaoRepository.java index 14f0367..065bb32 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/ormlite/BaseDaoRepository.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/database/repository/ormlite/BaseDaoRepository.java @@ -3,7 +3,7 @@ import com.github.imdmk.playtime.infrastructure.database.repository.Repository; import com.github.imdmk.playtime.infrastructure.database.repository.RepositoryContext; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.logger.Level; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/di/BindCore.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/injector/Bind.java similarity index 89% rename from playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/di/BindCore.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/injector/Bind.java index 0b813d0..917412d 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/di/BindCore.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/injector/Bind.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.infrastructure.di; +package com.github.imdmk.playtime.infrastructure.injector; import org.panda_lang.utilities.inject.annotations.Injectable; @@ -21,5 +21,5 @@ @Injectable @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -public @interface BindCore { +public @interface Bind { } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleContext.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleContext.java index 61dc4b6..a3202c4 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleContext.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleContext.java @@ -3,11 +3,12 @@ import com.github.imdmk.playtime.infrastructure.database.repository.RepositoryManager; import com.github.imdmk.playtime.platform.events.BukkitListenerRegistrar; import com.github.imdmk.playtime.platform.gui.GuiRegistry; -import com.github.imdmk.playtime.platform.litecommands.configurer.LiteCommandsRegistrar; import com.github.imdmk.playtime.platform.logger.PluginLogger; import com.github.imdmk.playtime.platform.placeholder.adapter.PlaceholderAdapter; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; +import dev.rollczi.litecommands.LiteCommandsBuilder; import org.bukkit.Server; +import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.annotations.Inject; @@ -34,7 +35,7 @@ public record ModuleContext( @NotNull TaskScheduler taskScheduler, @NotNull RepositoryManager repositoryManager, @NotNull BukkitListenerRegistrar listenerRegistrar, - @NotNull LiteCommandsRegistrar liteCommandsRegistrar, + @NotNull LiteCommandsBuilder liteCommandsBuilder, @NotNull GuiRegistry guiRegistry, @NotNull PlaceholderAdapter placeholderAdapter) { } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleInitializer.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleInitializer.java index 4e89a57..b0f7382 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleInitializer.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleInitializer.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.infrastructure.module; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.Injector; @@ -112,7 +112,7 @@ public void activateFeatures() { forEachModule("activateFeatures", m -> { m.tasks(injector).schedule(context.taskScheduler()); m.listeners(injector).register(context.listenerRegistrar()); - m.commands(injector).configure(context.liteCommandsRegistrar()); + m.commands(injector).configure(context.liteCommandsBuilder()); m.guis(injector).register(context.guiRegistry()); m.placeholders(injector).register(context.placeholderAdapter()); m.afterRegister(context.plugin(), context.server(), injector); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleRegistry.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleRegistry.java index 131e3f9..dff4f9b 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleRegistry.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/ModuleRegistry.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.infrastructure.module; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import org.panda_lang.utilities.inject.Injector; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/phase/CommandPhase.java b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/phase/CommandPhase.java index d05ab0a..7bb0447 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/phase/CommandPhase.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/infrastructure/module/phase/CommandPhase.java @@ -1,13 +1,14 @@ package com.github.imdmk.playtime.infrastructure.module.phase; -import com.github.imdmk.playtime.platform.litecommands.configurer.LiteCommandsRegistrar; +import dev.rollczi.litecommands.LiteCommandsBuilder; +import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; /** * Functional phase interface responsible for command registration. *

* Implementations should declare and configure commands using the - * provided {@link LiteCommandsRegistrar}. + * provided {@link LiteCommandsBuilder}. */ @FunctionalInterface public interface CommandPhase { @@ -17,5 +18,5 @@ public interface CommandPhase { * * @param configurer the command configurer used to register LiteCommands commands (never {@code null}) */ - void configure(@NotNull LiteCommandsRegistrar configurer); + void configure(@NotNull LiteCommandsBuilder configurer); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/message/MessageConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/message/MessageConfig.java similarity index 97% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/message/MessageConfig.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/message/MessageConfig.java index 9ccd5d1..0167806 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/message/MessageConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/message/MessageConfig.java @@ -1,11 +1,11 @@ -package com.github.imdmk.playtime.shared.message; +package com.github.imdmk.playtime.message; import com.eternalcode.multification.notice.Notice; import com.eternalcode.multification.notice.resolver.NoticeResolverDefaults; import com.eternalcode.multification.okaeri.MultificationSerdesPack; +import com.github.imdmk.playtime.config.ConfigSection; import com.github.imdmk.playtime.feature.playtime.messages.ENPlayTimeMessages; import com.github.imdmk.playtime.feature.reload.messages.ENReloadMessages; -import com.github.imdmk.playtime.shared.config.ConfigSection; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/message/MessageService.java b/playtime-core/src/main/java/com/github/imdmk/playtime/message/MessageService.java similarity index 93% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/message/MessageService.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/message/MessageService.java index 2378033..6cf5568 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/message/MessageService.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/message/MessageService.java @@ -1,10 +1,10 @@ -package com.github.imdmk.playtime.shared.message; +package com.github.imdmk.playtime.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.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import net.kyori.adventure.platform.AudienceProvider; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.Component; @@ -51,10 +51,11 @@ public final class MessageService extends BukkitMultification { public MessageService( @NotNull MessageConfig messageConfig, @NotNull AudienceProvider audienceProvider, - @NotNull MiniMessage miniMessage) { - this.messageConfig = Validator.notNull(messageConfig, "messageConfig cannot be null"); - this.audienceProvider = Validator.notNull(audienceProvider, "audienceProvider cannot be null"); - this.miniMessage = Validator.notNull(miniMessage, "miniMessage cannot be null"); + @NotNull MiniMessage miniMessage + ) { + this.messageConfig = Validator.notNull(messageConfig, "messageConfig"); + this.audienceProvider = Validator.notNull(audienceProvider, "audienceProvider"); + this.miniMessage = Validator.notNull(miniMessage, "miniMessage"); } public MessageService(@NotNull MessageConfig messageConfig, @NotNull BukkitAudiences bukkitAudiences) { @@ -116,8 +117,8 @@ public MessageService(@NotNull MessageConfig messageConfig, @NotNull Plugin plug * @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"); + Validator.notNull(sender, "sender"); + Validator.notNull(notice, "notice"); create().viewer(sender).notice(notice).send(); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventureComponents.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventureComponents.java similarity index 93% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventureComponents.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventureComponents.java index de70941..9de1aea 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventureComponents.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventureComponents.java @@ -1,6 +1,6 @@ -package com.github.imdmk.playtime.shared.adventure; +package com.github.imdmk.playtime.platform.adventure; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.format.TextDecoration; @@ -41,7 +41,7 @@ private AdventureComponents() { * @return the deserialized component */ public static @NotNull Component text(@NotNull CharSequence text) { - Validator.notNull(text, "text cannot be null"); + Validator.notNull(text, "text"); return MINI_MESSAGE.deserialize(text.toString()); } @@ -52,7 +52,7 @@ private AdventureComponents() { * @return an unmodifiable list of deserialized components */ public static @NotNull List text(@NotNull CharSequence... texts) { - Validator.notNull(texts, "texts cannot be null"); + Validator.notNull(texts, "texts"); final List out = new ArrayList<>(texts.length); for (CharSequence text : texts) { @@ -69,7 +69,7 @@ private AdventureComponents() { * @return an unmodifiable list of deserialized components */ public static @NotNull List text(@NotNull Iterable texts) { - Validator.notNull(texts, "texts cannot be null"); + Validator.notNull(texts, "texts"); final List out = new ArrayList<>(); for (CharSequence text : texts) { @@ -87,7 +87,7 @@ private AdventureComponents() { * @return a new component without italics */ public static @NotNull Component withoutItalics(@NotNull Component component) { - Validator.notNull(component, "component cannot be null"); + Validator.notNull(component, "component"); return component.decoration(TextDecoration.ITALIC, false); } @@ -108,7 +108,7 @@ private AdventureComponents() { * @return a new component without italics */ public static @NotNull Component withoutItalics(@NotNull ComponentLike like) { - Validator.notNull(like, "component cannot be null"); + Validator.notNull(like, "component"); return like.asComponent().decoration(TextDecoration.ITALIC, false); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatter.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventureFormatter.java similarity index 88% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatter.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventureFormatter.java index def6c1f..744887d 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatter.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventureFormatter.java @@ -1,6 +1,6 @@ -package com.github.imdmk.playtime.shared.adventure; +package com.github.imdmk.playtime.platform.adventure; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import org.jetbrains.annotations.NotNull; @@ -28,7 +28,7 @@ private AdventureFormatter() { * @return formatted component */ public static @NotNull Component format(@NotNull String input, @NotNull AdventurePlaceholders placeholders) { - Validator.notNull(input, "input cannot be null"); + Validator.notNull(input, "input"); return format(AdventureComponents.text(input), placeholders); } @@ -40,7 +40,7 @@ private AdventureFormatter() { * @return formatted components */ public static @NotNull List format(@NotNull List components, @NotNull AdventurePlaceholders placeholders) { - Validator.notNull(components, "components cannot be null"); + Validator.notNull(components, "components"); return components.stream() .map(component -> format(component, placeholders)) .collect(Collectors.toList()); @@ -54,8 +54,8 @@ private AdventureFormatter() { * @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"); + Validator.notNull(input, "input"); + Validator.notNull(placeholders, "placeholders"); if (placeholders.isEmpty()) { return input; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholders.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventurePlaceholders.java similarity index 94% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholders.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventurePlaceholders.java index cda62c8..5a7926c 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholders.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/AdventurePlaceholders.java @@ -1,6 +1,6 @@ -package com.github.imdmk.playtime.shared.adventure; +package com.github.imdmk.playtime.platform.adventure; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -24,7 +24,7 @@ public final class AdventurePlaceholders { private final Map map; private AdventurePlaceholders(@NotNull Map map) { - Validator.notNull(map, "map cannot be null"); + Validator.notNull(map, "map"); this.map = Collections.unmodifiableMap(map); } @@ -91,8 +91,8 @@ public static final class Builder { */ @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"); + Validator.notNull(key, "key"); + Validator.notNull(value, "value"); this.entries.put(key, value); return this; } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/serdes/ComponentSerializer.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/ComponentSerializer.java similarity index 88% rename from playtime-core/src/main/java/com/github/imdmk/playtime/platform/serdes/ComponentSerializer.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/ComponentSerializer.java index 198ac9c..f4ce438 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/serdes/ComponentSerializer.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/adventure/ComponentSerializer.java @@ -1,6 +1,5 @@ -package com.github.imdmk.playtime.platform.serdes; +package com.github.imdmk.playtime.platform.adventure; -import com.github.imdmk.playtime.shared.adventure.AdventureComponents; import eu.okaeri.configs.schema.GenericsDeclaration; import eu.okaeri.configs.serdes.DeserializationData; import eu.okaeri.configs.serdes.ObjectSerializer; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitEventCaller.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitEventCaller.java index ff35bdc..5a7a3a5 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitEventCaller.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitEventCaller.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.events; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.Server; import org.bukkit.event.Event; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitListenerRegistrar.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitListenerRegistrar.java index 2e1ddec..10f1f0b 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitListenerRegistrar.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/events/BukkitListenerRegistrar.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.events; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.event.Listener; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiRegistry.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiRegistry.java index 9bc05bd..c996139 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiRegistry.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiRegistry.java @@ -1,7 +1,6 @@ package com.github.imdmk.playtime.platform.gui; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.gui.IdentifiableGui; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/gui/GuiType.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiType.java similarity index 93% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/gui/GuiType.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiType.java index ef3ae28..a17c8e5 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/gui/GuiType.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/GuiType.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.shared.gui; +package com.github.imdmk.playtime.platform.gui; /** * Defines the supported GUI layout types within the plugin. diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/gui/IdentifiableGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/IdentifiableGui.java similarity index 90% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/gui/IdentifiableGui.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/IdentifiableGui.java index 5d3729e..f9f0a9d 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/gui/IdentifiableGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/IdentifiableGui.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.shared.gui; +package com.github.imdmk.playtime.platform.gui; import org.jetbrains.annotations.NotNull; /** diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/ConfigurableGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/ConfigurableGui.java index e5bb1eb..a15678f 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/ConfigurableGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/ConfigurableGui.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.gui.config; -import com.github.imdmk.playtime.shared.gui.GuiType; +import com.github.imdmk.playtime.platform.gui.GuiType; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/GuiConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/GuiConfig.java index db5c821..4b08026 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/GuiConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/GuiConfig.java @@ -1,11 +1,11 @@ package com.github.imdmk.playtime.platform.gui.config; +import com.github.imdmk.playtime.config.ConfigSection; import com.github.imdmk.playtime.feature.playtime.gui.PlayTimeTopGuiConfig; -import com.github.imdmk.playtime.platform.serdes.ComponentSerializer; +import com.github.imdmk.playtime.platform.adventure.ComponentSerializer; +import com.github.imdmk.playtime.platform.gui.item.ItemGuiSerializer; import com.github.imdmk.playtime.platform.serdes.EnchantmentSerializer; -import com.github.imdmk.playtime.platform.serdes.ItemGuiSerializer; import com.github.imdmk.playtime.platform.serdes.SoundSerializer; -import com.github.imdmk.playtime.shared.config.ConfigSection; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/NavigationBarConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/NavigationBarConfig.java index ee54bec..8e828c1 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/NavigationBarConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/config/NavigationBarConfig.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.gui.config; +import com.github.imdmk.playtime.platform.adventure.AdventureComponents; import com.github.imdmk.playtime.platform.gui.item.ItemGui; -import com.github.imdmk.playtime.shared.adventure.AdventureComponents; import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; import org.bukkit.Material; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiBuilderFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiBuilderFactory.java index d759900..e5cfff8 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiBuilderFactory.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiBuilderFactory.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.gui.factory; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.gui.GuiType; +import com.github.imdmk.playtime.platform.gui.GuiType; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.builder.gui.BaseGuiBuilder; import dev.triumphteam.gui.components.ScrollType; import dev.triumphteam.gui.guis.Gui; @@ -19,7 +19,7 @@ public final class GuiBuilderFactory { private GuiBuilderFactory() { - throw new UnsupportedOperationException("Utility class"); + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated."); } /** diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiFactory.java index d68c960..cee734d 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiFactory.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/factory/GuiFactory.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.gui.factory; import com.github.imdmk.playtime.platform.gui.config.ConfigurableGui; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.guis.BaseGui; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGui.java index 134d86a..f9f967b 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGui.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.gui.item; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import net.kyori.adventure.text.Component; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -30,7 +30,8 @@ public record ItemGui( @Nullable Integer slot, @Nullable Map enchantments, @Nullable List flags, - @Nullable String requiredPermission) { + @Nullable String requiredPermission +) { public ItemGui { Validator.notNull(material, "material cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/serdes/ItemGuiSerializer.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiSerializer.java similarity index 95% rename from playtime-core/src/main/java/com/github/imdmk/playtime/platform/serdes/ItemGuiSerializer.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiSerializer.java index bec0b8b..5eacf92 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/serdes/ItemGuiSerializer.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiSerializer.java @@ -1,6 +1,5 @@ -package com.github.imdmk.playtime.platform.serdes; +package com.github.imdmk.playtime.platform.gui.item; -import com.github.imdmk.playtime.platform.gui.item.ItemGui; import eu.okaeri.configs.schema.GenericsDeclaration; import eu.okaeri.configs.serdes.DeserializationData; import eu.okaeri.configs.serdes.ObjectSerializer; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiTransformer.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiTransformer.java index a021496..50b9954 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiTransformer.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemGuiTransformer.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.gui.item; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.builder.item.BaseItemBuilder; import dev.triumphteam.gui.builder.item.ItemBuilder; import dev.triumphteam.gui.components.GuiAction; @@ -71,7 +71,8 @@ private ItemGuiTransformer() { public static @NotNull GuiItem toGuiItem( @NotNull ItemGui item, @NotNull GuiAction onClick, - @NotNull Consumer> builderEditor) { + @NotNull Consumer> builderEditor + ) { Validator.notNull(item, "item cannot be null"); Validator.notNull(onClick, "onClick cannot be null"); Validator.notNull(builderEditor, "builderEditor cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemVariantPermissionResolver.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemVariantPermissionResolver.java index 42dcef5..ce50b59 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemVariantPermissionResolver.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/item/ItemVariantPermissionResolver.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.gui.item; import com.github.imdmk.playtime.platform.gui.render.RenderContext; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.entity.HumanEntity; import org.jetbrains.annotations.NotNull; @@ -44,7 +44,8 @@ public ItemGui resolve( @NotNull HumanEntity viewer, @NotNull RenderContext context, @NotNull Iterable candidates, - @NotNull ItemGui fallback) { + @NotNull ItemGui fallback + ) { Validator.notNull(viewer, "viewer cannot be null"); Validator.notNull(context, "context cannot be null"); Validator.notNull(candidates, "candidates cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/GuiRenderer.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/GuiRenderer.java index 6b58306..2f6fcb8 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/GuiRenderer.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/GuiRenderer.java @@ -21,7 +21,8 @@ default void setItem(@NotNull BaseGui gui, @NotNull ItemGui item, @NotNull RenderContext context, @NotNull RenderOptions options, - @NotNull Consumer onClick) { + @NotNull Consumer onClick + ) { setItem(gui, slot, item, context, options, onClick, b -> {}); } @@ -36,14 +37,16 @@ void setItem(@NotNull BaseGui gui, @NotNull RenderContext context, @NotNull RenderOptions options, @NotNull Consumer onClick, - @NotNull Consumer> builderEditor); + @NotNull Consumer> builderEditor + ); @Contract(mutates = "param1") default void setItem(@NotNull BaseGui gui, @NotNull ItemGui item, @NotNull RenderContext context, @NotNull RenderOptions options, - @NotNull Consumer onClick) { + @NotNull Consumer onClick + ) { var slot = item.slot(); if (slot == null) { throw new IllegalArgumentException("Item slot is null (use add(...) for non-slotted items)"); @@ -58,7 +61,8 @@ default void setItem(@NotNull BaseGui gui, @NotNull RenderContext context, @NotNull RenderOptions options, @NotNull Consumer onClick, - @NotNull Consumer> builderEditor) { + @NotNull Consumer> builderEditor + ) { var slot = item.slot(); if (slot == null) { throw new IllegalArgumentException("Item slot is null (use add(...) for non-slotted items)"); @@ -72,7 +76,8 @@ default void addItem(@NotNull BaseGui gui, @NotNull ItemGui item, @NotNull RenderContext context, @NotNull RenderOptions options, - @NotNull Consumer onClick) { + @NotNull Consumer onClick + ) { addItem(gui, item, context, options, onClick, b -> {}); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/TriumphGuiRenderer.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/TriumphGuiRenderer.java index 1fd1a22..5fbbc70 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/TriumphGuiRenderer.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/render/TriumphGuiRenderer.java @@ -2,7 +2,7 @@ import com.github.imdmk.playtime.platform.gui.item.ItemGui; import com.github.imdmk.playtime.platform.gui.item.ItemGuiTransformer; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.builder.item.BaseItemBuilder; import dev.triumphteam.gui.components.GuiAction; import dev.triumphteam.gui.guis.BaseGui; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/AbstractGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/AbstractGui.java index 704beea..17d6264 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/AbstractGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/AbstractGui.java @@ -6,7 +6,7 @@ import com.github.imdmk.playtime.platform.gui.render.RenderContext; import com.github.imdmk.playtime.platform.gui.render.RenderOptions; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.guis.BaseGui; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; @@ -41,10 +41,12 @@ public abstract class AbstractGui { * @param renderer renderer that places items and enforces permission policy * @param renderOptions render options (no-permission policy, onDenied) */ - protected AbstractGui(@NotNull NavigationBarConfig config, - @NotNull TaskScheduler taskScheduler, - @NotNull GuiRenderer renderer, - @NotNull RenderOptions renderOptions) { + protected AbstractGui( + @NotNull NavigationBarConfig config, + @NotNull TaskScheduler taskScheduler, + @NotNull GuiRenderer renderer, + @NotNull RenderOptions renderOptions + ) { this.config = Validator.notNull(config, "config cannot be null"); this.scheduler = Validator.notNull(taskScheduler, "taskScheduler cannot be null"); this.renderer = Validator.notNull(renderer, "renderer cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/GuiOpener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/GuiOpener.java index 54b5184..4670266 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/GuiOpener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/GuiOpener.java @@ -1,9 +1,9 @@ package com.github.imdmk.playtime.platform.gui.view; import com.github.imdmk.playtime.platform.gui.GuiRegistry; +import com.github.imdmk.playtime.platform.gui.IdentifiableGui; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.gui.IdentifiableGui; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.guis.BaseGui; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/NavigationBar.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/NavigationBar.java index 41e8280..843cd10 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/NavigationBar.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/NavigationBar.java @@ -5,7 +5,7 @@ import com.github.imdmk.playtime.platform.gui.render.RenderContext; import com.github.imdmk.playtime.platform.gui.render.RenderOptions; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.triumphteam.gui.guis.BaseGui; import dev.triumphteam.gui.guis.PaginatedGui; import org.bukkit.entity.Player; @@ -43,10 +43,12 @@ final class NavigationBar { * @param renderer GUI renderer enforcing permission policy * @param renderOptions render options (no-permission policy, onDenied) */ - NavigationBar(@NotNull NavigationBarConfig config, - @NotNull TaskScheduler scheduler, - @NotNull GuiRenderer renderer, - @NotNull RenderOptions renderOptions) { + NavigationBar( + @NotNull NavigationBarConfig config, + @NotNull TaskScheduler scheduler, + @NotNull GuiRenderer renderer, + @NotNull RenderOptions renderOptions + ) { this.config = Validator.notNull(config, "config cannot be null"); this.renderer = Validator.notNull(renderer, "renderer cannot be null"); this.scheduler = Validator.notNull(scheduler, "scheduler cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/ParameterizedGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/ParameterizedGui.java index ae66eb7..8a8c924 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/ParameterizedGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/ParameterizedGui.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.gui.view; -import com.github.imdmk.playtime.shared.gui.IdentifiableGui; +import com.github.imdmk.playtime.platform.gui.IdentifiableGui; import dev.triumphteam.gui.guis.BaseGui; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/SimpleGui.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/SimpleGui.java index 6b7e1ce..fa235d1 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/SimpleGui.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/gui/view/SimpleGui.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.gui.view; -import com.github.imdmk.playtime.shared.gui.IdentifiableGui; +import com.github.imdmk.playtime.platform.gui.IdentifiableGui; import dev.triumphteam.gui.guis.BaseGui; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/InvalidUsageHandlerImpl.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/InvalidUsageHandlerImpl.java index 17a830e..f454964 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/InvalidUsageHandlerImpl.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/InvalidUsageHandlerImpl.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.litecommands; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.rollczi.litecommands.handler.result.ResultHandlerChain; import dev.rollczi.litecommands.invalidusage.InvalidUsage; import dev.rollczi.litecommands.invalidusage.InvalidUsageHandler; @@ -20,11 +20,11 @@ public InvalidUsageHandlerImpl(@NotNull MessageService messageService) { @Override public void handle(Invocation invocation, InvalidUsage result, ResultHandlerChain chain) { - CommandSender sender = invocation.sender(); - Schematic schematic = result.getSchematic(); + final CommandSender sender = invocation.sender(); + final Schematic schematic = result.getSchematic(); if (schematic.isOnlyFirst()) { - this.messageService.create() + messageService.create() .viewer(sender) .notice(notice -> notice.commandUsageInvalid) .placeholder("{USAGE}", schematic.first()) @@ -32,13 +32,13 @@ public void handle(Invocation invocation, InvalidUsage notice.commandUsageHeader) .send(); - for (String scheme : schematic.all()) { - this.messageService.create() + for (final String scheme : schematic.all()) { + messageService.create() .viewer(sender) .notice(notice -> notice.commandUsageEntry) .placeholder("{USAGE}", scheme) diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/MissingPermissionsHandlerImpl.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/MissingPermissionsHandlerImpl.java index 84ca9fd..2ac0cd8 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/MissingPermissionsHandlerImpl.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/MissingPermissionsHandlerImpl.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.litecommands; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.rollczi.litecommands.handler.result.ResultHandlerChain; import dev.rollczi.litecommands.invocation.Invocation; import dev.rollczi.litecommands.permission.MissingPermissions; @@ -19,7 +19,7 @@ public MissingPermissionsHandlerImpl(@NotNull MessageService messageService) { @Override public void handle(Invocation invocation, MissingPermissions permissions, ResultHandlerChain chain) { - this.messageService.create() + messageService.create() .viewer(invocation.sender()) .notice(n -> n.commandPermissionMissing) .placeholder("{PERMISSIONS}", String.join(", ", permissions.getPermissions())) diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/NoticeResultHandlerImpl.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/NoticeResultHandlerImpl.java index fa96ef8..0890e1f 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/NoticeResultHandlerImpl.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/NoticeResultHandlerImpl.java @@ -1,8 +1,8 @@ package com.github.imdmk.playtime.platform.litecommands; import com.eternalcode.multification.notice.Notice; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageService; +import com.github.imdmk.playtime.message.MessageService; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.rollczi.litecommands.handler.result.ResultHandler; import dev.rollczi.litecommands.handler.result.ResultHandlerChain; import dev.rollczi.litecommands.invocation.Invocation; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/configurer/BukkitLiteCommandsRegistrar.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/configurer/BukkitLiteCommandsRegistrar.java deleted file mode 100644 index 1a78ebd..0000000 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/configurer/BukkitLiteCommandsRegistrar.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.github.imdmk.playtime.platform.litecommands.configurer; - -import com.github.imdmk.playtime.shared.Validator; -import dev.rollczi.litecommands.LiteCommands; -import dev.rollczi.litecommands.LiteCommandsBuilder; -import dev.rollczi.litecommands.bukkit.LiteBukkitFactory; -import dev.rollczi.litecommands.bukkit.LiteBukkitSettings; -import org.bukkit.Server; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; - -/** - * Bukkit-specific implementation of {@link LiteCommandsRegistrar} responsible for - * configuring and constructing {@link LiteCommands} instances via the LiteCommands framework. - * - *

This class provides a simple builder-style API for registering commands - * and applying additional {@link LiteCommandsBuilder} customizations before - * the command system is initialized.

- * - *

Usage:

- *
{@code
- * LiteCommandsConfigurer configurer = new BukkitLiteCommandsConfigurer()
- *     .register(new MyCommand(), new OtherCommand())
- *     .configure(builder -> builder.settings().prefix("myplugin"));
- *
- * LiteCommands liteCommands = configurer.create("myplugin", plugin, server);
- * }
- * - *

Thread-safety: This class is not thread-safe and should be configured - * only during plugin initialization (main thread).

- * - * @see LiteCommands - * @see LiteCommandsBuilder - * @see LiteBukkitFactory - */ -public final class BukkitLiteCommandsRegistrar implements LiteCommandsRegistrar { - - private final List>> customizers = new ArrayList<>(); - private final List commands = new ArrayList<>(); - - /** - * Registers a new customization for the {@link LiteCommandsBuilder}. - * - *

Customizers can modify settings, add components, or register custom parameter resolvers.

- * - * @param customizer a consumer that customizes the LiteCommands builder (non-null) - * @return this configurer instance for chaining - * @throws NullPointerException if {@code customizer} is null - */ - @Contract("_ -> this") - @Override - public LiteCommandsRegistrar configure(@NotNull Consumer> customizer) { - this.customizers.add(customizer); - return this; - } - - /** - * Registers one or more command handler instances to be used by LiteCommands. - * - * @param commands non-null command handler instances - * @return this configurer instance for chaining - * @throws NullPointerException if {@code commands} is null - */ - @Contract("_ -> this") - @Override - public LiteCommandsRegistrar registerCommands(@NotNull Object... commands) { - this.commands.addAll(Arrays.asList(commands)); - return this; - } - - /** - * Creates and builds a fully configured {@link LiteCommands} instance. - * - *

All registered customizers are applied sequentially before building. - * The specified commands are then registered into the resulting command manager.

- * - * @param fallbackPrefix fallback command prefix (e.g., plugin name) - * @param plugin Bukkit plugin instance - * @param server Bukkit server reference - * @return a fully initialized {@link LiteCommands} instance - * @throws NullPointerException if any argument is null - */ - @Override - public @NotNull LiteCommands create(@NotNull String fallbackPrefix, - @NotNull Plugin plugin, - @NotNull Server server) { - Validator.notNull(fallbackPrefix, "fallbackPrefix cannot be null"); - Validator.notNull(plugin, "plugin cannot be null"); - Validator.notNull(server, "server cannot be null"); - - var builder = LiteBukkitFactory.builder(fallbackPrefix, plugin, server); - for (var customizer : customizers) { - customizer.accept(builder); - } - - builder.commands(commands.toArray()); - - return builder.build(); - } -} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/configurer/LiteCommandsRegistrar.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/configurer/LiteCommandsRegistrar.java deleted file mode 100644 index 676652c..0000000 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/litecommands/configurer/LiteCommandsRegistrar.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.github.imdmk.playtime.platform.litecommands.configurer; - -import dev.rollczi.litecommands.LiteCommands; -import dev.rollczi.litecommands.LiteCommandsBuilder; -import dev.rollczi.litecommands.bukkit.LiteBukkitSettings; -import org.bukkit.Server; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Consumer; - -/** - * Thin facade over {@link LiteCommandsBuilder} to keep LiteCommands usage - * behind a simple, fluent configuration interface. - * - *

Intent: - *

    - *
  • accept external customizers,
  • - *
  • register command handlers,
  • - *
  • create a ready {@link LiteCommands} instance.
  • - *
- * - *

Threading: should be used on the server main thread. - * Implementations are expected to be non-blocking and side-effect free - * until {@link #create(String, Plugin, Server)} is invoked.

- */ -public interface LiteCommandsRegistrar { - - /** - * Applies a low-level customizer to the underlying {@link LiteCommandsBuilder}. - * - * @param customizer a callback that configures the builder - * @return this configurer for fluent chaining - */ - LiteCommandsRegistrar configure( - @NotNull Consumer> customizer - ); - - /** - * Registers command handler instances to be picked up by LiteCommands. - * - * @param commands command handler objects - * @return this configurer for fluent chaining - */ - LiteCommandsRegistrar registerCommands(@NotNull Object... commands); - - /** - * Builds a {@link LiteCommands} instance for Bukkit. - * - * @param fallbackPrefix fallback command prefix (non-null) - * @param plugin owning plugin (non-null) - * @param server Bukkit server (non-null) - * @return initialized {@link LiteCommands} ready to use - */ - @NotNull - LiteCommands create(@NotNull String fallbackPrefix, - @NotNull Plugin plugin, - @NotNull Server server); -} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/logger/BukkitPluginLogger.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/logger/BukkitPluginLogger.java index 3e17b63..5623ca7 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/logger/BukkitPluginLogger.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/logger/BukkitPluginLogger.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.logger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAPIAdapter.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAPIAdapter.java index bb887e2..5be739c 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAPIAdapter.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAPIAdapter.java @@ -2,7 +2,7 @@ import com.github.imdmk.playtime.platform.logger.PluginLogger; import com.github.imdmk.playtime.platform.placeholder.PluginPlaceholder; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAdapterFactory.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAdapterFactory.java index b2b7f37..baa0e53 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAdapterFactory.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/placeholder/adapter/PlaceholderAdapterFactory.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.platform.placeholder.adapter; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.Server; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; @@ -44,7 +44,8 @@ public final class PlaceholderAdapterFactory { public static PlaceholderAdapter createFor( @NotNull Plugin plugin, @NotNull Server server, - @NotNull PluginLogger logger) { + @NotNull PluginLogger logger + ) { Validator.notNull(plugin, "plugin cannot be null"); Validator.notNull(server, "server cannot be null"); Validator.notNull(logger, "logger cannot be null"); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/scheduler/BukkitTaskScheduler.java b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/scheduler/BukkitTaskScheduler.java index 87aa3ec..2c07b97 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/platform/scheduler/BukkitTaskScheduler.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/platform/scheduler/BukkitTaskScheduler.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.platform.scheduler; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigBinder.java b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigBinder.java deleted file mode 100644 index 5650790..0000000 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigBinder.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.github.imdmk.playtime.shared.config; - -import eu.okaeri.configs.OkaeriConfig; -import org.jetbrains.annotations.NotNull; -import org.panda_lang.utilities.inject.Resources; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Set; - -/** - * Utility for binding Okaeri configuration objects to Panda {@link Resources} injection context. - * - *

This binder walks over provided configuration sections, registers each instance in the - * {@link Resources} registry via {@code assignInstance}, and recursively processes nested - * {@link OkaeriConfig} fields. Static and transient fields are ignored. The traversal is - * cycle-safe through identity-based visited tracking.

- * - *

Thread-safety: This class holds no state, but {@link Resources} and - * config instances are typically not thread-safe for concurrent mutation. Bind on the init thread.

- */ -public final class ConfigBinder { - - private ConfigBinder() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - /** - * Binds the given configuration sections into the {@link Resources} context. - * - *

Each section (and its nested {@link OkaeriConfig} fields) is registered - * with {@link Resources#on(Class)} → {@code assignInstance(object)}. Cycles are - * prevented using an identity-based visited set.

- * - * @param resources non-null Panda resources/injector context - * @param sections non-null set of top-level configuration sections to bind - * @throws IllegalStateException if reflective access to a config field fails - * @throws NullPointerException if any argument is null - */ - public static void bind(@NotNull Resources resources, @NotNull Set sections) { - final Set visited = Collections.newSetFromMap(new IdentityHashMap<>()); - for (final var section : sections) { - bindRecursive(resources, section, visited); - } - } - - /** - * Recursively registers the given object and its nested {@link OkaeriConfig} fields - * into the {@link Resources} context. - * - *

Walks the class hierarchy up to {@link Object}, skipping {@code static} and {@code transient} - * fields. Uses identity tracking to avoid infinite recursion on cyclic graphs.

- * - * @param resources non-null injection context - * @param object non-null configuration object to bind - * @param visited identity set used to detect already-processed instances - * @throws IllegalStateException if reflective access fails - */ - private static void bindRecursive(@NotNull Resources resources, @NotNull Object object, @NotNull Set visited) { - if (!visited.add(object)) { - return; - } - - resources.on(object.getClass()).assignInstance(object); - - for (Class clazz = object.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { - for (Field field : clazz.getDeclaredFields()) { - int modifiers = field.getModifiers(); - if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) { - continue; - } - - try { - field.setAccessible(true); - Object value = field.get(object); - if (value instanceof OkaeriConfig nested) { - bindRecursive(resources, nested, visited); - } - } catch (IllegalAccessException e) { - throw new IllegalStateException("Failed to bind config field: " - + clazz.getSimpleName() + "#" + field.getName(), e); - } - } - } - } -} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigLoadException.java b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigLoadException.java deleted file mode 100644 index 5a6a9ba..0000000 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigLoadException.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.github.imdmk.playtime.shared.config; - -import org.jetbrains.annotations.NotNull; - -/** - * Thrown to indicate that a configuration file failed to load or save. - *

- * Wraps exceptions raised by the OkaeriConfig framework or underlying I/O operations. - * Used to propagate configuration-related errors as unchecked exceptions. - *

- */ -public final class ConfigLoadException extends RuntimeException { - - /** - * Creates a new {@link ConfigLoadException} with a default message and cause. - * - * @param cause the underlying exception that caused this failure - */ - public ConfigLoadException(@NotNull Throwable cause) { - super("Failed to load configuration", cause); - } - - /** - * Creates a new {@link ConfigLoadException} with a custom message. - * - * @param message the detail message describing the failure - */ - public ConfigLoadException(@NotNull String message) { - super(message); - } - - /** - * Creates a new {@link ConfigLoadException} with a custom message and cause. - * - * @param message the detail message describing the failure - * @param cause the underlying exception that caused this failure - */ - public ConfigLoadException(@NotNull String message, @NotNull Throwable cause) { - super(message, cause); - } -} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigManager.java b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigManager.java deleted file mode 100644 index 922c175..0000000 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/config/ConfigManager.java +++ /dev/null @@ -1,286 +0,0 @@ -package com.github.imdmk.playtime.shared.config; - -import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; -import eu.okaeri.configs.OkaeriConfig; -import eu.okaeri.configs.exception.OkaeriException; -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 org.jetbrains.annotations.Unmodifiable; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.LoaderOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.representer.Representer; -import org.yaml.snakeyaml.resolver.Resolver; - -import java.io.File; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Central coordinator for creating, loading, and saving Okaeri-based configuration sections. - * - *

Provides:

- *
    - *
  • Consistent YAML formatting via a preconfigured {@link YamlSnakeYamlConfigurer} (block style, 2-space indent, no line wrapping).
  • - *
  • Async I/O offloaded to a dedicated single-threaded executor (daemon) to avoid blocking the main thread.
  • - *
  • Bulk operations (create all, load all, save all) and type-based lookup of created configs.
  • - *
- * - *

Thread-safety: Internally uses concurrent collections ({@link ConcurrentHashMap} & {@link java.util.concurrent.ConcurrentHashMap#newKeySet()}) - * and a single-thread executor for async tasks. Public methods that mutate state are not synchronized except where necessary; callers should prefer using - * async methods for I/O. The executor is shut down by {@link #shutdown()}.

- * - *

Lifecycle:

- *
{@code
- * ConfigManager cm = new ConfigManager(dataFolder);
- * MyConfig cfg = cm.create(MyConfig.class);
- * cm.loadAll().join();
- * cm.saveAllSync();
- * cm.shutdown();
- * }
- * - * @see ConfigSection - * @see OkaeriConfig - * @see YamlSnakeYamlConfigurer - * @see ConfigLoadException - */ -public final class ConfigManager { - - private static final String THREAD_NAME = "playtime-config"; - - /** - * Creates a dedicated single-threaded daemon executor used for async config I/O. - * - * @return new single-threaded executor named {@code playtime-config} - */ - private static ExecutorService newSingleThreadExecutor() { - return Executors.newSingleThreadExecutor(r -> { - Thread t = new Thread(r, THREAD_NAME); - t.setDaemon(true); - return t; - }); - } - - private final Set configs = ConcurrentHashMap.newKeySet(); - private final Map, ConfigSection> byType = new ConcurrentHashMap<>(); - - private final PluginLogger logger; - private final ExecutorService executor; - private final File dataFolder; - - public ConfigManager(@NotNull PluginLogger logger, @NotNull ExecutorService executor, @NotNull File dataFolder) { - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.executor = Validator.notNull(executor, "executor cannot be null"); - this.dataFolder = Validator.notNull(dataFolder, "dataFolder cannot be null"); - } - - public ConfigManager(@NotNull PluginLogger logger, @NotNull File dataFolder) { - this(logger, newSingleThreadExecutor(), dataFolder); - } - - /** - * Creates a configuration instance of the given type, binds its file, applies YAML/serdes settings, - * saves defaults if necessary, loads content, and registers it for bulk operations. - * - *

Requirements on the config class:

- *
    - *
  • {@link ConfigSection#getFileName()} must return a non-blank relative path (e.g., {@code "config.yml"}).
  • - *
  • {@link ConfigSection#getSerdesPack()} must not return {@code null}.
  • - *
- * - * @param configClass config type to create - * @param specific {@link ConfigSection} subtype - * @return created and loaded config instance - * @throws IllegalStateException if the file name is blank - * @throws NullPointerException if the serdes pack is {@code null} - * @throws OkaeriException if saving defaults or loading fails internally (propagated from {@link OkaeriConfig}) - */ - public @NotNull T create(@NotNull Class configClass) { - final T config = eu.okaeri.configs.ConfigManager.create(configClass); - - final String fileName = config.getFileName(); - if (fileName.isBlank()) { - throw new IllegalStateException( - "Missing config file name for " + configClass.getName() - + " – override getFileName() to return a non-empty path, e.g. 'config.yml'." - ); - } - - final OkaeriSerdesPack serdes = Validator.notNull(config.getSerdesPack(), "config serdes pack cannot be null"); - - final File file = new File(dataFolder, fileName); - final YamlSnakeYamlConfigurer configurer = createYamlSnakeYamlConfigurer(); - - config.withConfigurer(configurer, serdes); - config.withSerdesPack(new SerdesCommons()); - config.withBindFile(file); - config.withRemoveOrphans(true); - config.saveDefaults(); - config.load(true); - - configs.add(config); - byType.put(configClass, config); - return config; - } - - /** - * Creates and registers all provided root config types in the specified order. - * - * @param configClasses ordered list of root {@link ConfigSection} classes - * @throws OkaeriException if any config fails during creation or loading - */ - public void createAll(@NotNull List> configClasses) { - configClasses.forEach(this::create); - } - - /** - * Returns the config instance of the given type, or {@code null} if not created. - * - * @param type config class used as the lookup key - * @param config subtype - * @return config instance or {@code null} - */ - @SuppressWarnings("unchecked") - public T get(@NotNull Class type) { - return (T) byType.get(type); - } - - /** - * Returns the config instance of the given type, throwing if it was not created. - * - * @param type config class used as the lookup key - * @param config subtype - * @return non-null config instance - * @throws IllegalStateException if a config of this type has not been created yet - */ - public @NotNull T require(@NotNull Class type) { - final T config = get(type); - if (config == null) { - throw new IllegalStateException("Config not created: " + type.getName()); - } - return config; - } - - /** - * Creates a {@link YamlSnakeYamlConfigurer} with conservative and readable defaults: - * block style, 2-space indentation, no line splitting, limited aliases, no recursive keys. - * - * @return configured YAML configurer - */ - private @NotNull YamlSnakeYamlConfigurer createYamlSnakeYamlConfigurer() { - final LoaderOptions loader = new LoaderOptions(); - loader.setAllowRecursiveKeys(false); - loader.setMaxAliasesForCollections(50); - - final Constructor constructor = new Constructor(loader); - - final DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - options.setIndent(2); - options.setSplitLines(false); - - final Representer representer = new ConfigRepresenter(options); - final Resolver resolver = new Resolver(); - - final Yaml yaml = new Yaml(constructor, representer, options, loader, resolver); - return new YamlSnakeYamlConfigurer(yaml); - } - - /** - * Asynchronously reloads all registered configs on the manager's executor. - * - * @return future completed when all configs have been loaded, or completed exceptionally with {@link ConfigLoadException} - */ - public @NotNull CompletableFuture loadAll() { - return CompletableFuture.runAsync(() -> configs.forEach(this::load), executor); - } - - /** - * Synchronously reloads all registered configs on the caller thread. - * - *

Use this when you control the calling context and want deterministic reloading.

- * - * @throws ConfigLoadException if any config fails to load - */ - public void loadAllSync() { - configs.forEach(this::load); - } - - /** - * Loads the provided config and wraps {@link OkaeriException} into {@link ConfigLoadException} with logging. - * - * @param config target config to load - * @throws ConfigLoadException on load failure - */ - private void load(@NotNull ConfigSection config) { - try { - config.load(true); - } catch (OkaeriException e) { - logger.error(e, "Failed to load config: %s", config.getClass().getSimpleName()); - throw new ConfigLoadException(e); - } - } - - /** - * Asynchronously saves all registered configs on the manager's executor. - * - * @return future completed when all configs have been saved, or completed exceptionally with {@link ConfigLoadException} - */ - public @NotNull CompletableFuture saveAll() { - return CompletableFuture.runAsync(() -> configs.forEach(this::save), executor); - } - - /** - * Synchronously saves all registered configs on the caller thread. - * - * @throws ConfigLoadException if any config fails to save - */ - public void saveAllSync() { - configs.forEach(this::save); - } - - /** - * Saves the provided config and wraps {@link OkaeriException} into {@link ConfigLoadException} with logging. - * - * @param config target config to save - * @throws ConfigLoadException on save failure - */ - private void save(@NotNull ConfigSection config) { - try { - config.save(); - } catch (OkaeriException e) { - logger.error(e, "Failed to save config: %s", config.getClass().getSimpleName()); - throw new ConfigLoadException(e); - } - } - - /** - * Returns an immutable snapshot view of all registered config instances. - * - * @return unmodifiable set of registered configs - */ - public @NotNull @Unmodifiable Set getConfigs() { - return Collections.unmodifiableSet(configs); - } - - /** - * Shuts down the manager by stopping the executor and clearing internal registries. - * - *

After calling this method, the manager cannot be reused safely.

- */ - public void shutdown() { - executor.shutdownNow(); - configs.clear(); - byType.clear(); - } -} diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/DurationSplitter.java b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/DurationSplitter.java index 7b7b9cb..58f9476 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/DurationSplitter.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/DurationSplitter.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.shared.time; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import java.time.Duration; @@ -27,7 +27,7 @@ private DurationSplitter() { * @return map of {@link DurationUnit} to its value in the given duration */ public static @NotNull Map split(@NotNull Duration duration) { - Validator.notNull(duration, "duration cannot be null"); + Validator.notNull(duration, "duration"); EnumMap parts = new EnumMap<>(DurationUnit.class); for (DurationUnit unit : DurationUnit.ORDERED) { diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/Durations.java b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/Durations.java index 0c49eb8..f8ef205 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/Durations.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/time/Durations.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.shared.time; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.jetbrains.annotations.NotNull; import java.time.Duration; @@ -51,8 +51,8 @@ private Durations() { * @throws IllegalArgumentException if duration or style are {@code null} */ public static @NotNull String format(@NotNull Duration duration, @NotNull DurationFormatStyle style) { - Validator.notNull(duration, "duration cannot be null"); - Validator.notNull(style, "style cannot be null"); + Validator.notNull(duration, "duration"); + Validator.notNull(style, "style"); if (duration.isZero() || duration.isNegative()) { return LESS_THAN_SECOND; @@ -72,7 +72,7 @@ private Durations() { * @throws IllegalArgumentException if the provided style is {@code null} */ public static void setDefaultFormatStyle(@NotNull DurationFormatStyle style) { - Validator.notNull(style, "durationFormatStyle cannot be null"); + Validator.notNull(style, "durationFormatStyle"); DEFAULT_FORMAT_STYLE = style; } @@ -84,7 +84,7 @@ public static void setDefaultFormatStyle(@NotNull DurationFormatStyle style) { * @return clamped, non-negative duration */ public static @NotNull Duration clamp(@NotNull Duration input) { - Validator.notNull(input, "duration cannot be null"); + Validator.notNull(input, "duration"); if (input.isNegative()) { return Duration.ZERO; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/Validator.java b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/validate/Validator.java similarity index 91% rename from playtime-core/src/main/java/com/github/imdmk/playtime/shared/Validator.java rename to playtime-core/src/main/java/com/github/imdmk/playtime/shared/validate/Validator.java index 16fd3ed..f356272 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/shared/Validator.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/shared/validate/Validator.java @@ -1,4 +1,4 @@ -package com.github.imdmk.playtime.shared; +package com.github.imdmk.playtime.shared.validate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,14 +25,14 @@ private Validator() { * provided message. * * @param obj the value to validate; may be null - * @param message exception message used when {@code obj} is null + * @param context context of exception 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 message) { + public static T notNull(@Nullable T obj, @NotNull String context) { if (obj == null) { - throw new NullPointerException(message); + throw new NullPointerException(context + " cannot be null"); } return obj; } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserArgument.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserArgument.java index a6c693c..549603d 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserArgument.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserArgument.java @@ -1,8 +1,8 @@ package com.github.imdmk.playtime.user; +import com.github.imdmk.playtime.message.MessageConfig; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; -import com.github.imdmk.playtime.shared.message.MessageConfig; +import com.github.imdmk.playtime.shared.validate.Validator; import dev.rollczi.litecommands.argument.Argument; import dev.rollczi.litecommands.argument.parser.ParseResult; import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; @@ -37,11 +37,12 @@ final class UserArgument extends ArgumentResolver { @NotNull PluginLogger logger, @NotNull Server server, @NotNull MessageConfig messageConfig, - @NotNull UserService userService) { - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.server = Validator.notNull(server, "server cannot be null"); - this.messageConfig = Validator.notNull(messageConfig, "config cannot be null"); - this.userService = Validator.notNull(userService, "userService cannot be null"); + @NotNull UserService userService + ) { + this.logger = Validator.notNull(logger, "logger"); + this.server = Validator.notNull(server, "server"); + this.messageConfig = Validator.notNull(messageConfig, "config"); + this.userService = Validator.notNull(userService, "userService"); } @Override diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserModule.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserModule.java index 07cfa95..5919f4d 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserModule.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserModule.java @@ -59,9 +59,7 @@ public RepositoryPhase repositories(@NotNull Injector injector) { @Override public CommandPhase commands(@NotNull Injector injector) { - return configurer -> configurer.configure(builder -> { - builder.argument(User.class, injector.newInstance(UserArgument.class)); - }); + return builder -> builder.argument(User.class, injector.newInstance(UserArgument.class)); } @Override diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserSaveTask.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserSaveTask.java index 3f8c15f..b6a2ce2 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserSaveTask.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserSaveTask.java @@ -3,7 +3,7 @@ import com.github.imdmk.playtime.PlaytimeService; import com.github.imdmk.playtime.platform.logger.PluginLogger; import com.github.imdmk.playtime.platform.scheduler.PluginTask; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.Server; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -28,10 +28,10 @@ final class UserSaveTask implements PluginTask { @NotNull PlaytimeService playtimeService, @NotNull UserService userService ) { - this.server = Validator.notNull(server, "server cannot be null"); - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.playtimeService = Validator.notNull(playtimeService, "playtime cannot be null"); - this.userService = Validator.notNull(userService, "userService cannot be null"); + this.server = Validator.notNull(server, "server"); + this.logger = Validator.notNull(logger, "logger"); + this.playtimeService = Validator.notNull(playtimeService, "playtime"); + this.userService = Validator.notNull(userService, "userService"); } @Override diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserServiceImpl.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserServiceImpl.java index cabff20..93286a4 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserServiceImpl.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/UserServiceImpl.java @@ -5,7 +5,7 @@ import com.github.imdmk.playtime.UserSaveEvent; import com.github.imdmk.playtime.platform.events.BukkitEventCaller; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.cache.UserCache; import com.github.imdmk.playtime.user.repository.UserRepository; import com.github.imdmk.playtime.user.top.TopUsersCache; @@ -37,23 +37,24 @@ final class UserServiceImpl implements UserService { @NotNull UserCache cache, @NotNull TopUsersCache topUsersCache, @NotNull UserRepository repository, - @NotNull BukkitEventCaller eventCaller) { - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.cache = Validator.notNull(cache, "cache cannot be null"); - this.topUsersCache = Validator.notNull(topUsersCache, "topUsersCache cannot be null"); - this.repository = Validator.notNull(repository, "repository cannot be null"); - this.eventCaller = Validator.notNull(eventCaller, "eventCaller cannot be null"); + @NotNull BukkitEventCaller eventCaller + ) { + this.logger = Validator.notNull(logger, "logger"); + this.cache = Validator.notNull(cache, "cache"); + this.topUsersCache = Validator.notNull(topUsersCache, "topUsersCache"); + this.repository = Validator.notNull(repository, "repository"); + this.eventCaller = Validator.notNull(eventCaller, "eventCaller"); } @Override public @NotNull Optional findCachedByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); return cache.getUserByUuid(uuid); } @Override public @NotNull Optional findCachedByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); return cache.getUserByName(name); } @@ -65,7 +66,7 @@ final class UserServiceImpl implements UserService { @Override public @NotNull CompletableFuture> findByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); Optional cached = cache.getUserByUuid(uuid); if (cached.isPresent()) { @@ -86,7 +87,7 @@ final class UserServiceImpl implements UserService { @Override public @NotNull CompletableFuture> findByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); Optional cached = cache.getUserByName(name); if (cached.isPresent()) { @@ -112,8 +113,8 @@ final class UserServiceImpl implements UserService { @Override public @NotNull CompletableFuture save(@NotNull User user, @NotNull UserSaveReason reason) { - Validator.notNull(user, "user cannot be null"); - Validator.notNull(reason, "reason cannot be null"); + Validator.notNull(user, "user"); + Validator.notNull(reason, "reason"); eventCaller.callEvent(new UserPreSaveEvent(user, reason)); @@ -132,7 +133,7 @@ final class UserServiceImpl implements UserService { @Override public @NotNull CompletableFuture deleteByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); return repository.deleteByUuid(uuid) .orTimeout(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS) .thenApply(result -> { @@ -150,7 +151,7 @@ final class UserServiceImpl implements UserService { @Override public @NotNull CompletableFuture deleteByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); return repository.deleteByName(name) .orTimeout(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS) .thenApply(deleteResult -> { diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/cache/CaffeineUserCache.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/cache/CaffeineUserCache.java index de01c8a..cc45992 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/cache/CaffeineUserCache.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/cache/CaffeineUserCache.java @@ -3,7 +3,7 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.RemovalCause; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -29,8 +29,8 @@ public final class CaffeineUserCache implements UserCache { private final Cache cacheByName; public CaffeineUserCache(@NotNull Duration expireAfterAccess, @NotNull Duration expireAfterWrite) { - Validator.notNull(expireAfterAccess, "expireAfterAccess cannot be null"); - Validator.notNull(expireAfterWrite, "expireAfterWrite cannot be null"); + Validator.notNull(expireAfterAccess, "expireAfterAccess"); + Validator.notNull(expireAfterWrite, "expireAfterWrite"); this.cacheByName = Caffeine.newBuilder() .expireAfterWrite(expireAfterWrite) @@ -54,7 +54,7 @@ public CaffeineUserCache() { @Override public void cacheUser(@NotNull User user) { - Validator.notNull(user, "user cannot be null"); + Validator.notNull(user, "user"); final UUID uuid = user.getUuid(); final String name = user.getName(); @@ -73,7 +73,7 @@ public void cacheUser(@NotNull User user) { @Override public void invalidateUser(@NotNull User user) { - Validator.notNull(user, "user cannot be null"); + Validator.notNull(user, "user"); cacheByUuid.invalidate(user.getUuid()); cacheByName.invalidate(user.getName()); @@ -81,7 +81,7 @@ public void invalidateUser(@NotNull User user) { @Override public void invalidateByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); final User cached = cacheByUuid.getIfPresent(uuid); cacheByUuid.invalidate(uuid); @@ -92,7 +92,7 @@ public void invalidateByUuid(@NotNull UUID uuid) { @Override public void invalidateByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); final UUID uuid = cacheByName.getIfPresent(name); if (uuid != null) { @@ -104,13 +104,13 @@ public void invalidateByName(@NotNull String name) { @Override public @NotNull Optional getUserByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); return Optional.ofNullable(cacheByUuid.getIfPresent(uuid)); } @Override public @NotNull Optional getUserByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); final UUID uuid = cacheByName.getIfPresent(name); return uuid == null ? Optional.empty() : Optional.ofNullable(cacheByUuid.getIfPresent(uuid)); diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserJoinListener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserJoinListener.java index 4a5b974..1671fa0 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserJoinListener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserJoinListener.java @@ -2,7 +2,7 @@ import com.github.imdmk.playtime.platform.logger.PluginLogger; import com.github.imdmk.playtime.platform.scheduler.TaskScheduler; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserFactory; import com.github.imdmk.playtime.user.UserSaveReason; @@ -40,10 +40,11 @@ public UserJoinListener( @NotNull PluginLogger logger, @NotNull UserService userService, @NotNull UserFactory userFactory, - @NotNull TaskScheduler taskScheduler) { - this.server = Validator.notNull(server, "server cannot be null"); - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.userService = Validator.notNull(userService, "userService cannot be null"); + @NotNull TaskScheduler taskScheduler + ) { + this.server = Validator.notNull(server, "server"); + this.logger = Validator.notNull(logger, "logger"); + this.userService = Validator.notNull(userService, "userService"); this.userFactory = Validator.notNull(userFactory, "userFactory cannot be null"); this.taskScheduler = Validator.notNull(taskScheduler, "taskScheduler cannot be null"); } diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserQuitListener.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserQuitListener.java index efc7dbf..b2ba6b4 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserQuitListener.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/listener/UserQuitListener.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.user.listener; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.UserSaveReason; import com.github.imdmk.playtime.user.UserService; import org.bukkit.entity.Player; @@ -26,8 +26,8 @@ public final class UserQuitListener implements Listener { @Inject public UserQuitListener(@NotNull PluginLogger logger, @NotNull UserService userService) { - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.userService = Validator.notNull(userService, "userService cannot be null"); + this.logger = Validator.notNull(logger, "logger"); + this.userService = Validator.notNull(userService, "userService"); } @EventHandler(priority = EventPriority.HIGHEST) diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserEntityMapper.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserEntityMapper.java index 142d950..2cb2865 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserEntityMapper.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserEntityMapper.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.user.repository; import com.github.imdmk.playtime.infrastructure.database.repository.ormlite.EntityMapper; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserTime; import org.jetbrains.annotations.NotNull; @@ -13,7 +13,7 @@ public final class UserEntityMapper implements EntityMapper { @Override public @NotNull UserEntity toEntity(@NotNull User user) { - Validator.notNull(user, "user cannot be null"); + Validator.notNull(user, "user"); return new UserEntity( user.getUuid(), user.getName(), @@ -23,7 +23,7 @@ public final class UserEntityMapper implements EntityMapper { @Override public @NotNull User toDomain(@NotNull UserEntity entity) { - Validator.notNull(entity, "entity cannot be null"); + Validator.notNull(entity, "entity"); return new User( entity.getUuid(), entity.getName(), diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserRepositoryOrmLite.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserRepositoryOrmLite.java index 9881abe..0b891e5 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserRepositoryOrmLite.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/repository/UserRepositoryOrmLite.java @@ -3,7 +3,7 @@ import com.github.imdmk.playtime.infrastructure.database.repository.RepositoryContext; import com.github.imdmk.playtime.infrastructure.database.repository.ormlite.BaseDaoRepository; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.UserDeleteResult; import com.github.imdmk.playtime.user.UserDeleteStatus; @@ -27,10 +27,11 @@ public final class UserRepositoryOrmLite public UserRepositoryOrmLite( @NotNull PluginLogger logger, @NotNull RepositoryContext context, - @NotNull UserEntityMapper mapper) { + @NotNull UserEntityMapper mapper + ) { super(logger, context); - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.mapper = Validator.notNull(mapper, "mapper cannot be null"); + this.logger = Validator.notNull(logger, "logger"); + this.mapper = Validator.notNull(mapper, "mapper"); } @Override @@ -45,7 +46,7 @@ protected List> entitySubClasses() { @Override public @NotNull CompletableFuture> findByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); return executeAsync(() -> { try { return Optional.ofNullable(dao.queryForId(uuid)) @@ -59,7 +60,7 @@ protected List> entitySubClasses() { @Override public @NotNull CompletableFuture> findByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); return executeAsync(() -> { try { UserEntity entity = dao.queryBuilder() @@ -109,7 +110,7 @@ protected List> entitySubClasses() { @Override public @NotNull CompletableFuture save(@NotNull User user) { - Validator.notNull(user, "user cannot be null"); + Validator.notNull(user, "user"); return executeAsync(() -> { try { dao.createOrUpdate(mapper.toEntity(user)); @@ -123,7 +124,7 @@ protected List> entitySubClasses() { @Override public @NotNull CompletableFuture deleteByUuid(@NotNull UUID uuid) { - Validator.notNull(uuid, "uuid cannot be null"); + Validator.notNull(uuid, "uuid"); return executeAsync(() -> { try { UserEntity userEntity = dao.queryForId(uuid); @@ -146,7 +147,7 @@ protected List> entitySubClasses() { @Override public @NotNull CompletableFuture deleteByName(@NotNull String name) { - Validator.notNull(name, "name cannot be null"); + Validator.notNull(name, "name"); return executeAsync(() -> { try { UserEntity userEntity = dao.queryBuilder() diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/CachedLeaderboard.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/CachedLeaderboard.java index 4e426b1..5f1ce6e 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/CachedLeaderboard.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/CachedLeaderboard.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.user.top; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -27,8 +27,8 @@ record CachedLeaderboard( * A defensive copy of the user list is created to ensure immutability. */ CachedLeaderboard { - Validator.notNull(users, "users cannot be null"); - Validator.notNull(loadedAt, "loadedAt cannot be null"); + Validator.notNull(users, "users"); + Validator.notNull(loadedAt, "loadedAt"); users = List.copyOf(users); } @@ -41,7 +41,7 @@ record CachedLeaderboard( * @return {@code true} if the leaderboard is fresh and large enough, otherwise {@code false} */ boolean isUsable(int requestedLimit, @NotNull Duration expireAfter, @NotNull Instant now) { - Validator.notNull(now, "now cannot be null"); + Validator.notNull(now, "now"); if (this.limit < requestedLimit) { return false; diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/MemoryTopUsersCache.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/MemoryTopUsersCache.java index ba1b6d0..1f1d5df 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/MemoryTopUsersCache.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/MemoryTopUsersCache.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime.user.top; import com.github.imdmk.playtime.platform.logger.PluginLogger; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import com.github.imdmk.playtime.user.User; import com.github.imdmk.playtime.user.repository.UserRepository; import org.jetbrains.annotations.NotNull; @@ -26,9 +26,9 @@ public MemoryTopUsersCache( @NotNull TopUsersCacheConfig config, @NotNull UserRepository userRepository ) { - this.logger = Validator.notNull(logger, "logger cannot be null"); - this.config = Validator.notNull(config, "config cannot be null"); - this.userRepository = Validator.notNull(userRepository, "userRepository cannot be null"); + this.logger = Validator.notNull(logger, "logger"); + this.config = Validator.notNull(config, "config"); + this.userRepository = Validator.notNull(userRepository, "userRepository"); } @Override diff --git a/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/TopUsersCacheConfig.java b/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/TopUsersCacheConfig.java index 8986fbd..2762395 100644 --- a/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/TopUsersCacheConfig.java +++ b/playtime-core/src/main/java/com/github/imdmk/playtime/user/top/TopUsersCacheConfig.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime.user.top; -import com.github.imdmk.playtime.shared.config.ConfigSection; +import com.github.imdmk.playtime.config.ConfigSection; import eu.okaeri.configs.annotation.Comment; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import org.jetbrains.annotations.NotNull; diff --git a/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureComponentsTest.java b/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureComponentsTest.java index ff8ad54..5f5aafc 100644 --- a/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureComponentsTest.java +++ b/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureComponentsTest.java @@ -1,5 +1,6 @@ package com.github.imdmk.playtime.shared.adventure; +import com.github.imdmk.playtime.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/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatterTest.java b/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatterTest.java index 8bb5963..a332f16 100644 --- a/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatterTest.java +++ b/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventureFormatterTest.java @@ -1,5 +1,7 @@ package com.github.imdmk.playtime.shared.adventure; +import com.github.imdmk.playtime.platform.adventure.AdventureFormatter; +import com.github.imdmk.playtime.platform.adventure.AdventurePlaceholders; import net.kyori.adventure.text.Component; import org.junit.jupiter.api.Test; diff --git a/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholdersTest.java b/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholdersTest.java index 36181dd..1788086 100644 --- a/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholdersTest.java +++ b/playtime-core/src/test/java/com/github/imdmk/playtime/shared/adventure/AdventurePlaceholdersTest.java @@ -1,5 +1,6 @@ package com.github.imdmk.playtime.shared.adventure; +import com.github.imdmk.playtime.platform.adventure.AdventurePlaceholders; import net.kyori.adventure.text.Component; import org.junit.jupiter.api.Test; diff --git a/playtime-plugin/build.gradle.kts b/playtime-plugin/build.gradle.kts index 82abc27..5b3d067 100644 --- a/playtime-plugin/build.gradle.kts +++ b/playtime-plugin/build.gradle.kts @@ -6,9 +6,6 @@ plugins { } dependencies { - compileOnly("org.jetbrains:annotations:26.0.2-1") - compileOnly("org.spigotmc:spigot-api:1.21.10-R0.1-SNAPSHOT") - implementation(project(":playtime-core")) } @@ -18,7 +15,7 @@ tasks.build { } tasks.withType { - archiveFileName.set("AdvancedPlaytime v${project.version} (MC 1.17.x-1.21.x).jar") + archiveFileName.set("AdvancedPlaytime v${project.version} (MC 1.21).jar") mergeServiceFiles() diff --git a/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderDefaultSettings.java b/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderDefaultSettings.java index 39e7dd4..a1d98de 100644 --- a/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderDefaultSettings.java +++ b/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderDefaultSettings.java @@ -1,16 +1,16 @@ package com.github.imdmk.playtime; +import com.github.imdmk.playtime.config.ConfigSection; +import com.github.imdmk.playtime.config.PluginConfig; import com.github.imdmk.playtime.feature.migration.MigrationConfig; import com.github.imdmk.playtime.feature.migration.MigrationModule; import com.github.imdmk.playtime.feature.playtime.PlayTimeModule; import com.github.imdmk.playtime.feature.reload.ReloadModule; import com.github.imdmk.playtime.infrastructure.database.DatabaseConfig; import com.github.imdmk.playtime.infrastructure.module.Module; +import com.github.imdmk.playtime.message.MessageConfig; import com.github.imdmk.playtime.platform.gui.GuiModule; import com.github.imdmk.playtime.platform.gui.config.GuiConfig; -import com.github.imdmk.playtime.shared.config.ConfigSection; -import com.github.imdmk.playtime.shared.config.PluginConfig; -import com.github.imdmk.playtime.shared.message.MessageConfig; import com.github.imdmk.playtime.user.UserModule; import com.github.imdmk.playtime.user.top.TopUsersCacheConfig; import org.jetbrains.annotations.NotNull; diff --git a/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderSettings.java b/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderSettings.java index 8b9b9de..f649c45 100644 --- a/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderSettings.java +++ b/playtime-plugin/src/main/java/com/github/imdmk/playtime/LoaderSettings.java @@ -1,7 +1,7 @@ package com.github.imdmk.playtime; +import com.github.imdmk.playtime.config.ConfigSection; import com.github.imdmk.playtime.infrastructure.module.Module; -import com.github.imdmk.playtime.shared.config.ConfigSection; import org.jetbrains.annotations.NotNull; import java.util.List; diff --git a/playtime-plugin/src/main/java/com/github/imdmk/playtime/PlayTimePluginLoader.java b/playtime-plugin/src/main/java/com/github/imdmk/playtime/PlayTimePluginLoader.java index 90146f2..a935cb8 100644 --- a/playtime-plugin/src/main/java/com/github/imdmk/playtime/PlayTimePluginLoader.java +++ b/playtime-plugin/src/main/java/com/github/imdmk/playtime/PlayTimePluginLoader.java @@ -1,6 +1,6 @@ package com.github.imdmk.playtime; -import com.github.imdmk.playtime.shared.Validator; +import com.github.imdmk.playtime.shared.validate.Validator; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -16,8 +16,8 @@ public final class PlayTimePluginLoader extends JavaPlugin { private volatile PlayTimePlugin pluginCore; public PlayTimePluginLoader(@NotNull ExecutorService executor, @NotNull LoaderSettings settings) { - this.executor = Validator.notNull(executor, "executor cannot be null"); - this.settings = Validator.notNull(settings, "settings cannot be null"); + this.executor = Validator.notNull(executor, "executor"); + this.settings = Validator.notNull(settings, "settings"); } public PlayTimePluginLoader() {