9 | * The method annotated with {@code @CommandRoot} serves as the entry point for a command hierarchy. 10 | * When a command is executed, the method annotated with {@code @CommandRoot} is invoked first to handle the command. 11 | *
12 | * 13 | * @see CommanderCommand 14 | * @since 0.7.0.0-RC1 15 | */ 16 | @Documented 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Target(ElementType.METHOD) 19 | public @interface CommandRoot { 20 | 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/CommanderCommand.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation; 2 | 3 | import dev.temez.springlify.commander.command.CommandType; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * Marks a method or class as a command in the Commander framework. 11 | *12 | * Commands annotated with {@code CommanderCommand} can be registered and executed by the Commander module. 13 | * This annotation provides metadata about the command such as its name, description, and aliases. 14 | *
15 | * 16 | * @see CommandType 17 | * @since 0.7.0.0-RC1 18 | */ 19 | @Component 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target({ElementType.TYPE, ElementType.METHOD}) 23 | public @interface CommanderCommand { 24 | 25 | /** 26 | * Specifies the type of the command. 27 | * 28 | * @return the type of the command 29 | */ 30 | @NotNull CommandType type() default CommandType.SHARED; 31 | 32 | /** 33 | * Specifies the name of the command. 34 | * 35 | * @return the name of the command 36 | */ 37 | @NotNull String name(); 38 | 39 | /** 40 | * Provides a description of the command. 41 | * 42 | * @return the description of the command 43 | */ 44 | @NotNull String description() default ""; 45 | 46 | /** 47 | * Specifies alias names for the command. 48 | *49 | * Aliases can be used as alternative names to invoke the command. 50 | *
51 | * 52 | * @return an array of alias names for the command 53 | */ 54 | @NotNull String[] alias() default {}; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/SenderDetailsSource.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation; 2 | 3 | import dev.temez.springlify.commander.command.sender.SenderDetailsFactory; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * Indicates that detailed sender information support should be enabled for a command method. 10 | *11 | * Methods annotated with {@code @EnableDetailsSupport} will receive additional sender details 12 | * when invoked as part of a command execution. 13 | *
14 | *15 | * The {@link SenderDetailsFactory} specified in the annotation value determines how sender details are constructed. 16 | *
17 | * 18 | * @see SenderDetailsFactory 19 | * @since 0.7.0.0-RC1 20 | */ 21 | @Documented 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Target(ElementType.METHOD) 24 | public @interface SenderDetailsSource { 25 | 26 | /** 27 | * Specifies the class of the sender details factory to be used for constructing sender details. 28 | * 29 | * @return The class of the sender details factory. 30 | */ 31 | @NotNull 32 | Class extends SenderDetailsFactory>> value(); 33 | } 34 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/context/External.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.context; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * An annotation used to mark commander components as external. 7 | *8 | * This annotation can be applied to filters, parameter adapters, and parameter completers to indicate that they are 9 | * external to the current module or system. 10 | *
11 | * 12 | * @since 0.7.0.0-RC1 13 | */ 14 | @Documented 15 | @Target(ElementType.TYPE) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | public @interface External { 18 | } 19 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/context/Global.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.context; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * An annotation used to mark commander components as global. 7 | *8 | * This annotation can be applied to simple command filters to indicate that they are 9 | * global components, meaning they are available and applicable across all commands and contexts. 10 | *
11 | * 12 | * @since 0.7.0.0-RC1 13 | */ 14 | @Documented 15 | @Target(ElementType.TYPE) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | public @interface Global { 18 | } 19 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/filter/ApplyFilters.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.filter; 2 | 3 | import dev.temez.springlify.commander.command.filter.simple.SimpleCommandFilter; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * An annotation to apply filters to commands. 10 | *11 | * This annotation is used to specify one or more filters to be applied to individual commands. 12 | *
13 | *14 | * The {@code SimpleCommandFilter} type parameter specifies the type of filters that can be applied. 15 | *
16 | * 17 | * @see SimpleCommandFilter 18 | * @since 0.7.0.0-RC1 19 | */ 20 | @Documented 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(value = ElementType.METHOD) 23 | public @interface ApplyFilters { 24 | 25 | /** 26 | * Specifies one or more filters to be applied to the command. 27 | * 28 | * @return An array of filter classes to be applied. 29 | */ 30 | @NotNull 31 | Class extends SimpleCommandFilter>[] value(); 32 | } 33 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/filter/RequirePermission.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.filter; 2 | 3 | import dev.temez.springlify.commander.command.filter.impl.RequirePermissionFilter; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.springframework.core.annotation.Order; 6 | 7 | import java.lang.annotation.*; 8 | 9 | 10 | /** 11 | * An annotation to specify a required permission for executing a command method. 12 | *13 | * This annotation is used to specify a required permission for executing a command method. 14 | *
15 | *16 | * The {@code value} attribute specifies the required permission. 17 | *
18 | * 19 | * @see RequirePermissionFilter 20 | * @since 0.7.0.0-RC1 21 | */ 22 | @Order() 23 | @Documented 24 | @ValidateWith(RequirePermissionFilter.class) 25 | @Retention(RetentionPolicy.RUNTIME) 26 | @Target(ElementType.METHOD) 27 | public @interface RequirePermission { 28 | 29 | /** 30 | * Specifies the required permission for executing the command method. 31 | * 32 | * @return The required permission. 33 | */ 34 | @NotNull 35 | String value(); 36 | } 37 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/filter/ValidateWith.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.filter; 2 | 3 | import dev.temez.springlify.commander.command.filter.CommandFilter; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.lang.annotation.*; 7 | 8 | 9 | /** 10 | * An annotation to specify validation filters for command annotations. 11 | *12 | * This annotation is used to specify a validation filter for command annotations. It can be applied to other annotations 13 | * to enforce validation rules on commands. 14 | *
15 | *16 | * The {@code CommandFilter} type parameter specifies the type of validation filter to be applied. 17 | *
18 | * 19 | * @see CommandFilter 20 | * @since 0.7.0.0-RC1 21 | */ 22 | @Documented 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target(value = ElementType.ANNOTATION_TYPE) 25 | public @interface ValidateWith { 26 | 27 | /** 28 | * Specifies the validation filter class to be applied. 29 | * 30 | * @return The class of the validation filter. 31 | */ 32 | @NotNull 33 | Class extends CommandFilter>> value(); 34 | } 35 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/parameter/Adapter.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.parameter; 2 | 3 | import dev.temez.springlify.commander.argument.adapter.ParameterAdapter; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * An annotation used to specify an external parameter adapter for a method parameter. 10 | *11 | * This annotation should be applied to method parameters in command methods to specify the adapter that will 12 | * convert the raw input string into the appropriate parameter type. 13 | *
14 | * 15 | * @since 0.7.0.0-RC1 16 | */ 17 | @Documented 18 | @Retention(RetentionPolicy.RUNTIME) 19 | @Target(ElementType.PARAMETER) 20 | public @interface Adapter { 21 | 22 | /** 23 | * The class of the argument adapter to be used for this parameter. 24 | * 25 | * @return The class of the argument adapter. 26 | */ 27 | @NotNull Class extends ParameterAdapter>> value(); 28 | } 29 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/annotation/parameter/Completer.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.annotation.parameter; 2 | 3 | import dev.temez.springlify.commander.argument.completer.ParameterCompleter; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * An annotation used to specify an external parameter completer for a method parameter. 10 | *11 | * This annotation should be applied to method parameters in command methods to specify the completer that will 12 | * provide completion suggestions for the parameter. 13 | *
14 | * 15 | * @since 0.7.0.0-RC1 16 | */ 17 | @Documented 18 | @Retention(RetentionPolicy.RUNTIME) 19 | @Target(ElementType.PARAMETER) 20 | public @interface Completer { 21 | 22 | /** 23 | * The class of the argument completer to be used for this parameter. 24 | * 25 | * @return The class of the argument completer. 26 | */ 27 | @NotNull Class extends ParameterCompleter> value(); 28 | } 29 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/argument/adapter/ParameterAdapter.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.argument.adapter; 2 | 3 | import dev.temez.springlify.commander.argument.completer.ParameterCompleter; 4 | import dev.temez.springlify.commander.command.sender.Sender; 5 | import dev.temez.springlify.commander.exception.argument.ArgumentException; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Unmodifiable; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | 13 | /** 14 | * An interface for adapting raw command parameters into typed objects. 15 | *16 | * Implementations of this interface are responsible for parsing raw command parameters into typed objects of type {@code T}. 17 | * They may also provide completion suggestions for command parameters. 18 | *
19 | * 20 | * @param39 | * This default implementation returns an empty list, indicating that no completion suggestions are provided. 40 | *
41 | * 42 | * @param commandSender The command sender for whom completion suggestions are generated. 43 | * @return A list of completion suggestions. 44 | */ 45 | @Override 46 | default @Unmodifiable @NotNull List15 | * This adapter parses the raw command parameter into a {@code Float} using {@link Float#parseFloat(String)}. 16 | *
17 | * 18 | * @see ParameterAdapter 19 | * @since 0.7.0.0-RC1 20 | */ 21 | @Component 22 | @RequiredArgsConstructor 23 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) 24 | public class FloatParameterAdapter implements ParameterAdapter16 | * This adapter parses the raw command parameter into an {@code Integer} using {@link Integer#parseInt(String)}. 17 | *
18 | * 19 | * @see ParameterAdapter 20 | * @since 0.7.0.0-RC1 21 | */ 22 | @Component 23 | @RequiredArgsConstructor 24 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) 25 | public class IntegerParameterAdapter implements ParameterAdapter15 | * This adapter simply returns the raw command parameter as is, without any parsing. 16 | *
17 | * 18 | * @see ParameterAdapter 19 | * @since 0.7.0.0-RC1 20 | */ 21 | @Component 22 | @RequiredArgsConstructor 23 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) 24 | public class StringParameterAdapter implements ParameterAdapter11 | * Implementations of this interface provide a mechanism for obtaining the appropriate parameter adapter 12 | * for a given parameter type. 13 | *
14 | * 15 | * @see ParameterAdapter 16 | * @since 0.7.0.0-RC1 17 | */ 18 | public interface ParameterAdapterResolver { 19 | 20 | /** 21 | * Retrieves the parameter adapter for the specified parameter type. 22 | * 23 | * @param parameterType The class representing the type of parameter for which an adapter is needed. 24 | * @param12 | * Implementations of this interface are responsible for generating a list of completion suggestions 13 | * based on the input provided by the command sender. 14 | *
15 | * 16 | * @since 0.7.0.0-RC1 17 | */ 18 | public interface ParameterCompleter { 19 | 20 | /** 21 | * Generates a list of completion suggestions for the provided command sender. 22 | * 23 | * @param commandSender The command sender for whom completion suggestions are generated. 24 | * @return A list of completion suggestions. 25 | */ 26 | @Unmodifiable 27 | @NotNull List6 | * Each command can be categorized into one of the supported types: in-game commands, 7 | * shared commands (usable by both in-game and console), or console commands. 8 | *
9 | * 10 | * @since 0.7.0.0-RC1 11 | */ 12 | public enum CommandType { 13 | 14 | /** 15 | * Represents an in-game command, usable only by players in the game. 16 | */ 17 | INGAME, 18 | 19 | /** 20 | * Represents a shared command, usable by both players in-game and from the console. 21 | */ 22 | SHARED, 23 | 24 | /** 25 | * Represents a console command, usable only from the server console. 26 | */ 27 | CONSOLE 28 | } 29 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/completer/CommandCompleter.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.completer; 2 | 3 | import dev.temez.springlify.commander.command.invocation.CommandInvocation; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.jetbrains.annotations.Unmodifiable; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Interface for command completers that provide completion suggestions for commands. 11 | *12 | * Implementations of this interface are responsible for generating completion suggestions 13 | * based on the current state of the command invocation. 14 | *
15 | * 16 | * @since 0.7.0.0-RC1 17 | */ 18 | public interface CommandCompleter { 19 | 20 | /** 21 | * Provides a list of completion suggestions for the given command invocation. 22 | * 23 | * @param commandInvocation The current state of the command invocation. 24 | * @return An unmodifiable list of completion suggestions. 25 | */ 26 | @NotNull @Unmodifiable List12 | * Implementations of this interface should provide logic to determine if they support a given 13 | * command invocation and to generate completion suggestions for it. 14 | *
15 | * 16 | * @see CommandInvocation 17 | * @since 0.7.0.0-RC1 18 | */ 19 | public interface CompletionProvider { 20 | 21 | /** 22 | * Determines whether this provider supports the given command invocation. 23 | * 24 | * @param commandInvocation The current state of the command invocation. 25 | * @return {@code true} if this provider supports the given command invocation, {@code false} otherwise. 26 | */ 27 | boolean supports(@NotNull CommandInvocation commandInvocation); 28 | 29 | /** 30 | * Generates a list of completion suggestions for the given command invocation. 31 | * 32 | * @param commandInvocation The current state of the command invocation. 33 | * @return An unmodifiable list of completion suggestions. 34 | */ 35 | @NotNull @Unmodifiable List12 | * Implementations of this interface handle the execution logic for commands based on the provided {@link CommandInvocation}. 13 | *
14 | * 15 | * @since 0.7.0.0-RC1 16 | */ 17 | public interface CommandExecutor { 18 | 19 | /** 20 | * Executes a command based on the provided {@link CommandInvocation}. 21 | *22 | * This method processes the command invocation and performs the necessary actions defined by the command. 23 | * Implementations should handle any exceptions that occur during execution. 24 | *
25 | * 26 | * @param commandInvocation The command invocation containing the details of the command to be executed. 27 | * @throws CommandExecutionException If an error occurs during command execution. 28 | */ 29 | void execute(@NotNull CommandInvocation commandInvocation) throws CommandExecutionException, InvocationTargetException; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/executor/details/ProviderSenderDetailsResolver.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.executor.details; 2 | 3 | import dev.temez.springlify.commander.command.Command; 4 | import dev.temez.springlify.commander.command.executor.details.provider.SenderDetailsProvider; 5 | import dev.temez.springlify.commander.command.sender.Sender; 6 | import dev.temez.springlify.commander.exception.details.SenderDetailsException; 7 | import lombok.AccessLevel; 8 | import lombok.RequiredArgsConstructor; 9 | import lombok.experimental.FieldDefaults; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Implementation of {@link SenderDetailsResolver} that delegates the resolution to a list of {@link SenderDetailsProvider}s. 17 | * 18 | * @see SenderDetailsProvider 19 | * @since 0.7.0.0-RC1 20 | */ 21 | @Component 22 | @RequiredArgsConstructor 23 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) 24 | public class ProviderSenderDetailsResolver implements SenderDetailsResolver { 25 | 26 | @NotNull 27 | List10 | * Implementations of this interface determine whether they support a specific command and provide a way to resolve sender details for that command. 11 | *
12 | * 13 | * @since 0.7.0.0-RC1 14 | */ 15 | public interface SenderDetailsProvider { 16 | 17 | /** 18 | * Determines whether this provider supports the given command. 19 | * 20 | * @param command The command to check support for. 21 | * @return {@code true} if this provider supports the command, {@code false} otherwise. 22 | */ 23 | boolean supports(@NotNull Command command); 24 | 25 | /** 26 | * Resolves details about the sender of the given command. 27 | * 28 | * @param command The command whose sender details are to be resolved. 29 | * @param sender The sender of the command. 30 | * @return An object containing details about the sender. 31 | */ 32 | @NotNull Object getSenderDetails(@NotNull Command command, @NotNull Sender> sender); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/executor/details/provider/impl/GenericSenderDetailsProvider.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.executor.details.provider.impl; 2 | 3 | import dev.temez.springlify.commander.annotation.SenderDetailsSource; 4 | import dev.temez.springlify.commander.command.Command; 5 | import dev.temez.springlify.commander.command.executor.details.provider.SenderDetailsProvider; 6 | import dev.temez.springlify.commander.command.sender.Sender; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * A generic implementation of the {@link SenderDetailsProvider} interface. 12 | *13 | * This provider supports all commands and resolves sender details by returning the platform-specific sender object. 14 | *
15 | * 16 | * @see SenderDetailsProvider 17 | * @see Sender 18 | * @since 0.7.0.0-RC1 19 | */ 20 | @Component 21 | public class GenericSenderDetailsProvider implements SenderDetailsProvider { 22 | 23 | /** 24 | * Determines whether this provider supports the given command. 25 | * 26 | * @param command The command to check support for. 27 | * @return {@code true} indicating that this provider supports all commands. 28 | */ 29 | @Override 30 | public boolean supports(@NotNull Command command) { 31 | return !command.getCommandInvocationMetadata().getCommandMethod().isAnnotationPresent(SenderDetailsSource.class); 32 | } 33 | 34 | /** 35 | * Resolves details about the sender of the given command. 36 | * 37 | * @param command The command whose sender details are to be resolved. 38 | * @param sender The sender of the command. 39 | * @return The platform-specific sender object. 40 | */ 41 | @Override 42 | @NotNull 43 | public Object getSenderDetails(@NotNull Command command, @NotNull Sender> sender) { 44 | return sender.getPlatformSender(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/executor/provider/ParameterProvider.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.executor.provider; 2 | 3 | import dev.temez.springlify.commander.command.sender.Sender; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.lang.reflect.Parameter; 7 | 8 | /** 9 | * A provider interface for parsing command parameters. 10 | *11 | * Implementations of this interface are responsible for parsing raw arguments into 12 | * appropriate parameter types based on the method parameter definition. 13 | *
14 | * 15 | * @since 0.7.0.0-RC1 16 | */ 17 | public interface ParameterProvider { 18 | 19 | /** 20 | * Parses the raw argument into the appropriate parameter type. 21 | * 22 | * @param sender The sender of the command. 23 | * @param rawArgument The raw argument to be parsed. 24 | * @param parameter The method parameter definition. 25 | * @return The parsed parameter object. 26 | */ 27 | @NotNull 28 | Object parse(@NotNull Sender> sender, @NotNull String rawArgument, @NotNull Parameter parameter); 29 | 30 | /** 31 | * Checks if the provider supports parsing for the given parameter. 32 | * 33 | * @param parameter The method parameter definition. 34 | * @return {@code true} if the provider supports parsing for the parameter, {@code false} otherwise. 35 | */ 36 | boolean supports(@NotNull Parameter parameter); 37 | } 38 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/filter/CommandFilter.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.filter; 2 | 3 | import dev.temez.springlify.commander.command.sender.Sender; 4 | import dev.temez.springlify.commander.exception.filter.CommandFilterException; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.lang.annotation.Annotation; 8 | 9 | /** 10 | * Represents a command filter that operates based on an annotation type. 11 | * 12 | * @param The type of annotation associated with the filter. 13 | * @since 0.7.0.0-RC1 14 | */ 15 | public interface CommandFilter { 16 | 17 | /** 18 | * Performs filtering based on the provided annotation. 19 | * 20 | * @param sender The sender executing the command. 21 | * @param annotation The annotation associated with the filter. 22 | * @throws CommandFilterException If an error occurs during the filtering process. 23 | */ 24 | void doFilter(@NotNull Sender> sender, @NotNull A annotation) throws CommandFilterException; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/filter/CommandFilterService.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.filter; 2 | 3 | import dev.temez.springlify.commander.command.Command; 4 | import dev.temez.springlify.commander.command.sender.Sender; 5 | import dev.temez.springlify.commander.exception.filter.CommandFilterException; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | /** 9 | * Service interface for command filtering operations. 10 | * 11 | * @since 0.7.0.0-RC1 12 | */ 13 | public interface CommandFilterService { 14 | 15 | /** 16 | * Filters the command execution based on the sender and the command. 17 | * 18 | * @param sender The sender executing the command. 19 | * @param command The command being executed. 20 | * @throws CommandFilterException If an error occurs during the filtering process. 21 | */ 22 | void filter(@NotNull Sender> sender, @NotNull Command command) throws CommandFilterException; 23 | 24 | /** 25 | * Checks if the sender has access to execute the given command. 26 | * 27 | * @param sender The sender executing the command. 28 | * @param command The command to check accessibility for. 29 | * @return {@code true} if the sender has access to execute the command, {@code false} otherwise. 30 | */ 31 | boolean isAccessible(@NotNull Sender> sender, @NotNull Command command); 32 | } 33 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/filter/ProviderCommandFilterService.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.filter; 2 | 3 | import dev.temez.springlify.commander.command.Command; 4 | import dev.temez.springlify.commander.command.filter.provider.CommandFilterProvider; 5 | import dev.temez.springlify.commander.command.sender.Sender; 6 | import dev.temez.springlify.commander.exception.filter.CommandFilterException; 7 | import lombok.AccessLevel; 8 | import lombok.RequiredArgsConstructor; 9 | import lombok.experimental.FieldDefaults; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Service implementation for filtering command execution. 17 | * 18 | * @since 0.7.0.0-RC1 19 | */ 20 | @Service 21 | @RequiredArgsConstructor 22 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) 23 | public class ProviderCommandFilterService implements CommandFilterService { 24 | 25 | @NotNull 26 | List14 | * This filter checks if the sender has the required permission specified in the {@link RequirePermission} annotation. 15 | *
16 | * 17 | * @since 0.7.0.0-RC1 18 | */ 19 | @Component 20 | public class RequirePermissionFilter implements CommandFilter11 | * Implementations of this interface can determine whether a command is supported and apply filtering logic 12 | * based on various criteria such as the sender, the command itself, or any other contextual information. 13 | *
14 | * 15 | * @since 0.7.0.0-RC1 16 | */ 17 | public interface CommandFilterProvider { 18 | 19 | /** 20 | * Checks if the provider supports the given command. 21 | * 22 | * @param command The command to check. 23 | * @return {@code true} if the provider supports the command, {@code false} otherwise. 24 | */ 25 | boolean supports(@NotNull Command command); 26 | 27 | /** 28 | * Filters a command before its execution. 29 | *30 | * This method applies filtering logic to the given command based on the sender and any other relevant 31 | * contextual information. If the command is not allowed to execute, a {@link CommandFilterException} may be thrown. 32 | *
33 | * 34 | * @param sender The sender of the command. 35 | * @param command The command to filter. 36 | * @throws CommandFilterException If the command is not allowed to execute based on the applied filtering criteria. 37 | */ 38 | void filter(@NotNull Sender> sender, @NotNull Command command) throws CommandFilterException; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/filter/resolver/CommandFilterResolver.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.filter.resolver; 2 | 3 | import dev.temez.springlify.commander.command.filter.CommandFilter; 4 | import dev.temez.springlify.commander.exception.filter.CommandFilterNotFoundException; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.lang.annotation.Annotation; 8 | 9 | /** 10 | * Resolves command filters based on annotations. 11 | * 12 | * @see CommandFilter 13 | * @since 0.7.0.0-RC1 14 | */ 15 | public interface CommandFilterResolver { 16 | 17 | /** 18 | * Retrieves a command filter based on its annotation class. 19 | * 20 | * @param The type of the annotation. 21 | * @param annotation The annotation class. 22 | * @return The command filter corresponding to the annotation class. 23 | * @throws CommandFilterNotFoundException If no command filter is found for the given annotation class. 24 | */ 25 | @NotNull CommandFilter getFilter(@NotNull Class annotation) throws CommandFilterNotFoundException; 26 | 27 | /** 28 | * Retrieves a command filter based on its annotation instance. 29 | * 30 | * @param The type of the annotation. 31 | * @param annotation The annotation instance. 32 | * @return The command filter corresponding to the annotation instance. 33 | * @throws CommandFilterNotFoundException If no command filter is found for the given annotation. 34 | */ 35 | @NotNull CommandFilter getFilter(@NotNull A annotation) throws CommandFilterNotFoundException; 36 | } 37 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/filter/simple/SimpleCommandFilter.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.filter.simple; 2 | 3 | import dev.temez.springlify.commander.command.Command; 4 | import dev.temez.springlify.commander.command.sender.Sender; 5 | import dev.temez.springlify.commander.exception.filter.CommandFilterException; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | /** 9 | * Interface for implementing simple command filters. 10 | * 11 | * @since 0.7.0.0-RC1 12 | */ 13 | public interface SimpleCommandFilter { 14 | 15 | /** 16 | * Performs filtering on the command execution. 17 | * 18 | * @param sender The sender executing the command. 19 | * @param command The command being executed. 20 | * @throws CommandFilterException If an error occurs during the filtering process. 21 | */ 22 | void doFilter(@NotNull Sender> sender, @NotNull Command command) throws CommandFilterException; 23 | } 24 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/filter/simple/impl/CommandSourceFilter.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.filter.simple.impl; 2 | 3 | import dev.temez.springlify.commander.annotation.context.Global; 4 | import dev.temez.springlify.commander.command.Command; 5 | import dev.temez.springlify.commander.command.CommandType; 6 | import dev.temez.springlify.commander.command.filter.simple.SimpleCommandFilter; 7 | import dev.temez.springlify.commander.command.sender.Sender; 8 | import dev.temez.springlify.commander.exception.filter.CommandFilterException; 9 | import lombok.RequiredArgsConstructor; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | * A global command filter that restricts command execution based on the command source. 15 | * 16 | * @since 0.7.0.0-RC1 17 | */ 18 | @Global 19 | @Component 20 | @RequiredArgsConstructor 21 | public class CommandSourceFilter implements SimpleCommandFilter { 22 | 23 | /** 24 | * Performs filtering based on the command source. 25 | * 26 | * @param sender The sender executing the command. 27 | * @param command The command being executed. 28 | * @throws CommandFilterException If the command source is not allowed for the given command. 29 | */ 30 | @Override 31 | public void doFilter(@NotNull Sender> sender, @NotNull Command command) throws CommandFilterException { 32 | if (sender.isConsoleSender() && command.getType() == CommandType.INGAME) { 33 | throw new CommandFilterException("commander.filter.command-source.available-only-from-game"); 34 | } 35 | if (!sender.isConsoleSender() && command.getType() == CommandType.CONSOLE) { 36 | throw new CommandFilterException("commander.filter.command-source.available-only-from-console"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/invocation/CommandInvocation.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.invocation; 2 | 3 | import dev.temez.springlify.commander.command.Command; 4 | import dev.temez.springlify.commander.command.sender.Sender; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Unmodifiable; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Interface representing a command invocation. 12 | * 13 | * @since 0.7.0.0-RC1 14 | */ 15 | public interface CommandInvocation { 16 | 17 | /** 18 | * Retrieves the sender of the command invocation. 19 | * 20 | * @return The sender of the command invocation. 21 | */ 22 | @NotNull Sender> getSender(); 23 | 24 | /** 25 | * Retrieves the command associated with the invocation. 26 | * 27 | * @return The command associated with the invocation. 28 | */ 29 | @NotNull Command getCommand(); 30 | 31 | /** 32 | * Sets the command associated with the invocation. 33 | * 34 | * @param command The command to set. 35 | */ 36 | void setCommand(@NotNull Command command); 37 | 38 | /** 39 | * Retrieves the arguments passed with the command invocation. 40 | * 41 | * @return An unmodifiable list of arguments. 42 | */ 43 | @NotNull @Unmodifiable List9 | * Implementations of this interface can perform pre-processing tasks on command invocations 10 | * before their execution, such as validation, normalization, or modification of command parameters. 11 | *
12 | * 13 | * @since 0.7.0.0-RC1 14 | */ 15 | public interface ExecutionPreprocessorService { 16 | 17 | /** 18 | * Processes the given command invocation before execution. 19 | * 20 | * @param commandInvocation The command invocation to preprocess. 21 | */ 22 | void process(@NotNull CommandInvocation commandInvocation); 23 | } 24 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/preprocessor/ExecutionPreprocessorServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.preprocessor; 2 | 3 | import dev.temez.springlify.commander.command.invocation.CommandInvocation; 4 | import dev.temez.springlify.commander.exception.CommandException; 5 | import lombok.AccessLevel; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.experimental.FieldDefaults; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.springframework.core.annotation.Order; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.Comparator; 14 | import java.util.List; 15 | import java.util.Optional; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * Implementation of {@link ExecutionPreprocessorService} for pre-processing command executions. 20 | *21 | * This service orchestrates the pre-processing of command invocations by delegating to registered {@link InvocationPreprocessor} instances. 22 | *
23 | * 24 | * @since 0.7.0.0-RC1 25 | */ 26 | @Slf4j 27 | @Service 28 | @RequiredArgsConstructor 29 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) 30 | public class ExecutionPreprocessorServiceImpl implements ExecutionPreprocessorService { 31 | 32 | @NotNull 33 | List9 | * Implementations of this interface can perform pre-processing tasks on command invocations 10 | * such as validation, normalization, or modification of command parameters. 11 | *
12 | * 13 | * @since 0.7.0.0-RC1 14 | */ 15 | public interface InvocationPreprocessor { 16 | 17 | /** 18 | * Processes the given command invocation before execution. 19 | * 20 | * @param invocation The command invocation to preprocess. 21 | */ 22 | void process(@NotNull CommandInvocation invocation); 23 | } 24 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/preprocessor/impl/SubcommandPreprocessor.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.preprocessor.impl; 2 | 3 | import dev.temez.springlify.commander.command.Command; 4 | import dev.temez.springlify.commander.command.invocation.CommandInvocation; 5 | import dev.temez.springlify.commander.command.preprocessor.InvocationPreprocessor; 6 | import dev.temez.springlify.commander.exception.CommandException; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | import org.springframework.core.annotation.Order; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.Comparator; 13 | 14 | /** 15 | * Preprocessor for handling subcommands within command invocations. 16 | *17 | * This preprocessor extracts and processes subcommands from command invocations. 18 | *
19 | * 20 | * @since 0.7.0.0-RC1 21 | */ 22 | @Order 23 | @Component 24 | public class SubcommandPreprocessor implements InvocationPreprocessor { 25 | 26 | /** 27 | * Processes the command invocation by handling subcommands. 28 | * 29 | * @param invocation The command invocation to preprocess. 30 | * @throws CommandException If an error occurs during the preprocessing. 31 | */ 32 | @Override 33 | public void process(@NotNull CommandInvocation invocation) throws CommandException { 34 | Command subCommand = getSubCommand(invocation); 35 | if (subCommand != null) { 36 | invocation.setArguments(invocation.getArguments().stream().skip(1).toList()); 37 | invocation.setCommand(subCommand); 38 | process(invocation); 39 | } 40 | } 41 | 42 | /** 43 | * Retrieves the subcommand from the command invocation. 44 | * 45 | * @param invocation The command invocation. 46 | * @return The subcommand, or {@code null} if not found. 47 | */ 48 | private @Nullable Command getSubCommand(@NotNull CommandInvocation invocation) { 49 | if (invocation.getArguments().isEmpty()) { 50 | return null; 51 | } 52 | String possibleSubcommand = invocation.getArguments().get(0); 53 | return invocation.getCommand().getSubcommands() 54 | .stream() 55 | .sorted(Comparator.comparingInt(a -> a.getName().length())) 56 | .filter(subcommand -> possibleSubcommand.equalsIgnoreCase(subcommand.getName())) 57 | .findFirst() 58 | .orElse(null); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /springlify-commander/springlify-commander-commons/src/main/java/dev/temez/springlify/commander/command/sender/Sender.java: -------------------------------------------------------------------------------- 1 | package dev.temez.springlify.commander.command.sender; 2 | 3 | 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.UUID; 7 | 8 | /** 9 | * Interface representing a sender of commands. 10 | * 11 | * @param8 | * Implementations of this interface are responsible for creating sender details objects 9 | * based on the provided {@link Sender}. 10 | *
11 | *12 | * The {@code SenderDetails} type parameter specifies the type of sender details object 13 | * that will be constructed by implementations of this interface. 14 | *
15 | * 16 | * @paramUsage example: 14 | *
{@code 15 | * @VelocityComand(command="mycommand", alias = {"alias1", "alias2"}) 16 | * public class MyCommand implements CommandExecutor { 17 | * 18 | * // Command execution logic 19 | * 20 | * } 21 | * }22 | * 23 | *
In this example, `MyCommand` is marked as a Velocity command with the primary command
24 | * "mycommand" and two aliases "alias1" and "alias2."
25 | *
26 | * @since 0.7.0.0-RC1
27 | */
28 | @Target(ElementType.TYPE)
29 | @Retention(RetentionPolicy.RUNTIME)
30 | @Component
31 | @Documented
32 | public @interface BukkitCommand {
33 |
34 | /**
35 | * Alias for the {@link Component} annotation's value attribute.
36 | * Specifies the name of the bean.
37 | *
38 | * @return The primary bean name.
39 | */
40 | @AliasFor(annotation = Component.class)
41 | String value() default "";
42 |
43 | /**
44 | * Specifies the primary command name.
45 | *
46 | * @return The primary command name.
47 | */
48 | @NotNull
49 | String command();
50 | }
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-bukkit/src/main/java/dev/temez/springlify/platform/annotation/ConditionalOnPluginEnabled.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.annotation;
2 |
3 | import dev.temez.springlify.platform.condition.OnPluginEnabledCondition;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.springframework.context.annotation.Conditional;
6 |
7 | import java.lang.annotation.*;
8 |
9 |
10 | @Documented
11 | @Target({ElementType.TYPE, ElementType.METHOD})
12 | @Retention(RetentionPolicy.RUNTIME)
13 | @Conditional(OnPluginEnabledCondition.class)
14 | public @interface ConditionalOnPluginEnabled {
15 |
16 | @NotNull String value();
17 |
18 | }
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-bukkit/src/main/java/dev/temez/springlify/platform/condition/OnPluginEnabledCondition.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.condition;
2 |
3 | import dev.temez.springlify.platform.annotation.ConditionalOnPluginEnabled;
4 | import org.bukkit.Bukkit;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.springframework.context.annotation.Condition;
7 | import org.springframework.context.annotation.ConditionContext;
8 | import org.springframework.core.type.AnnotatedTypeMetadata;
9 |
10 | import java.util.Map;
11 |
12 | public class OnPluginEnabledCondition implements Condition {
13 |
14 | @Override
15 | @SuppressWarnings("DataFlowIssue")
16 | public boolean matches(@NotNull ConditionContext context,@NotNull AnnotatedTypeMetadata metadata) {
17 | Map This class is used for configuring color properties using RGB values. This class is used for configuring enchantment properties, such as the enchantment itself, level, and level restriction. This class is used for configuring location properties, such as world, coordinates, yaw, and pitch. This class is used for configuring potion effect properties, such as the effect type, duration, amplifier, and visibility. This class is used for configuring skin texture properties, such as the texture and signature. This converter is used by Spring Boot's type conversion mechanism to convert string values to Enchantment objects
15 | * when binding configuration properties. This method converts the string representation to an Enchantment object using the enchantment's key. This converter is used by Spring Boot's type conversion mechanism to convert string values to PotionEffectType
14 | * objects when binding configuration properties. This method converts the string representation to a PotionEffectType object using the effect type's name. This class is used for configuring ItemStacks, including the material, amount, and item meta. This property represents additional metadata for the ItemStack, such as display name, lore, etc. This class is used for configuring the general item meta properties, such as display name, lore, enchantments, etc. This class is used for configuring the item meta properties specific to leather armor, such as color. This class is used for configuring the item meta properties specific to potions, such as effects and color. This class is used for configuring the item meta properties specific to skulls, such as owner and skin. This component is responsible for mapping properties from {@link ColorConfiguration} to {@link Color} instances. This component is responsible for mapping properties from {@link LocationConfiguration} to {@link Location} instances. This component is responsible for mapping properties from {@link PotionEffectConfiguration} to {@link PotionEffect} instances. This class implements the {@link DestructionAwareBeanPostProcessor} interface
17 | * to handle the registration of {@link Listener} beans after they are initialized
18 | * and their unregistration before they are destroyed. This component implements the {@link ItemBuilderFactory} interface and initializes
18 | * item builders with a specified text converter during initialization. This interface defines methods for mapping configurations from source objects to result objects,
13 | * as well as retrieving mapping schemas for a given source and result class. This interface defines a method for retrieving the mapping schema for a given pair of source and result classes. This interface defines a method for mapping a single source object to a result object,
11 | * as well as a default method for mapping a collection of source objects to a collection of result objects. This exception is typically thrown when there is an issue with mapping between different data formats or structures. This exception is typically thrown when there is an issue with accessing or manipulating registry entries. This interface provides methods for accessing and manipulating a collection of registry entries. This interface defines a method for retrieving the identifier of the registry entry. This interface defines methods for registering and unregistering event listeners.
9 | * Implementations of this interface will handle the specific logic for their respective
10 | * server platforms. This interface defines methods for parsing text lines into adventure components,
13 | * as well as providing a reset component for formatting. Usage example:
18 | * In this example, `MyCommand` is marked as a Velocity command with the primary command
28 | * "mycommand" and two aliases "alias1" and "alias2."
29 | *
30 | * @since 0.7.1.0-SNAPSHOT
31 | */
32 | @Target(ElementType.TYPE)
33 | @Retention(RetentionPolicy.RUNTIME)
34 | @Component
35 | public @interface VelocityCommand {
36 |
37 | /**
38 | * Alias for the {@link Component} annotation's value attribute.
39 | * Specifies the name of the bean.
40 | *
41 | * @return The primary bean name.
42 | */
43 | @AliasFor(annotation = Component.class)
44 | String value() default "";
45 |
46 | /**
47 | * Specifies the primary command name.
48 | *
49 | * @return The primary command name.
50 | */
51 | @NotNull
52 | String command();
53 |
54 | /**
55 | * Specifies an array of alias names for the command.
56 | *
57 | * @return An array of alias names for the command.
58 | */
59 | @NotNull
60 | String[] alias() default {};
61 | }
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-velocity/src/main/java/dev/temez/springlify/platform/annotation/VelocityEventListener.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.annotation;
2 |
3 | import org.springframework.core.annotation.AliasFor;
4 | import org.springframework.stereotype.Component;
5 |
6 | import java.lang.annotation.ElementType;
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 | import java.lang.annotation.Target;
10 |
11 | /**
12 | * The {@code VelocityEventHandler} annotation is a custom annotation used to mark classes as event
13 | * handlers when developing plugins for Velocity.
14 | *
15 | * This annotation is used to declare that a class is an event listener,
16 | * and should be registered.
17 | *
18 | * Usage example:
19 | * In this example, `MyListenableService` is marked as an event handler class, and the
33 | * `onPlayerJoin` method is an event handler for the "PlayerJoinEvent."
34 | *
35 | * @since 0.7.1.0-SNAPSHOT
36 | */
37 | @Retention(RetentionPolicy.RUNTIME)
38 | @Target({ElementType.TYPE})
39 | @Component
40 | public @interface VelocityEventListener {
41 |
42 |
43 | /**
44 | * Alias for the {@link Component} annotation's value attribute.
45 | * Specifies the name of the bean.
46 | *
47 | * @return The primary bean name.
48 | */
49 | @AliasFor(annotation = Component.class)
50 | String value() default "";
51 | }
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-velocity/src/main/java/dev/temez/springlify/platform/configuration/VelocityPluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.configuration;
2 |
3 | import com.velocitypowered.api.command.CommandManager;
4 | import com.velocitypowered.api.event.EventManager;
5 | import com.velocitypowered.api.plugin.PluginManager;
6 | import com.velocitypowered.api.proxy.ConsoleCommandSource;
7 | import com.velocitypowered.api.proxy.ProxyServer;
8 | import com.velocitypowered.api.scheduler.Scheduler;
9 | import dev.temez.springlify.starter.plugin.SpringlifyVelocityPlugin;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.springframework.context.annotation.Bean;
12 | import org.springframework.context.annotation.Configuration;
13 |
14 | @Configuration
15 | public class VelocityPluginConfiguration {
16 |
17 | @Bean
18 | @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
19 | ProxyServer proxyServer(@NotNull SpringlifyVelocityPlugin plugin) {
20 | return plugin.getServer();
21 | }
22 |
23 | @Bean
24 | ConsoleCommandSource consoleCommandSource(@NotNull ProxyServer proxyServer) {
25 | return proxyServer.getConsoleCommandSource();
26 | }
27 |
28 | @Bean
29 | PluginManager pluginManager(@NotNull ProxyServer proxyServer) {
30 | return proxyServer.getPluginManager();
31 | }
32 |
33 | @Bean
34 | EventManager eventManager(@NotNull ProxyServer proxyServer) {
35 | return proxyServer.getEventManager();
36 | }
37 |
38 | @Bean
39 | CommandManager commandManager(@NotNull ProxyServer proxyServer) {
40 | return proxyServer.getCommandManager();
41 | }
42 |
43 | @Bean
44 | Scheduler scheduler(@NotNull ProxyServer proxyServer) {
45 | return proxyServer.getScheduler();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-velocity/src/main/java/dev/temez/springlify/platform/initializer/EventListenerInitializer.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.initializer;
2 |
3 | import dev.temez.springlify.platform.annotation.VelocityEventListener;
4 | import dev.temez.springlify.platform.server.ServerPlatformAdapter;
5 | import lombok.AccessLevel;
6 | import lombok.experimental.FieldDefaults;
7 | import lombok.extern.log4j.Log4j2;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
10 | import org.springframework.context.annotation.Lazy;
11 | import org.springframework.stereotype.Component;
12 |
13 | /**
14 | * The {@code ListenableServiceInitializer} class is a Spring DestructionAwareBeanPostProcessor.
15 | * It automatically registers and unregisters event listeners annotated with
16 | * {@link VelocityEventListener} when Spring beans are initialized and destroyed.
17 | *
18 | * This class performs the following tasks:
19 | * - Detects beans annotated with {@link VelocityEventListener}.
20 | * - Registers event listeners with Velocity's event manager upon bean initialization.
21 | * - Unregisters event listeners from Velocity's event manager when beans are destroyed.
22 | * - Logs debug messages when registering and unregistering event listeners.
23 | *
24 | * @since 0.7.1.0-SNAPSHOT
25 | */
26 | @Log4j2
27 | @Component
28 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
29 | public class EventListenerInitializer implements DestructionAwareBeanPostProcessor {
30 |
31 | @NotNull
32 | ServerPlatformAdapter serverPlatformAdapter;
33 |
34 | @Lazy
35 | public EventListenerInitializer(@NotNull ServerPlatformAdapter serverPlatformAdapter) {
36 | this.serverPlatformAdapter = serverPlatformAdapter;
37 | }
38 |
39 | @Override
40 | public Object postProcessAfterInitialization(@NotNull Object bean, @NotNull String beanName) {
41 | if (bean.getClass().isAnnotationPresent(VelocityEventListener.class)) {
42 | serverPlatformAdapter.registerEventListener(bean);
43 | }
44 | return bean;
45 | }
46 |
47 | @Override
48 | public void postProcessBeforeDestruction(@NotNull Object bean, @NotNull String beanName) {
49 | if (bean.getClass().isAnnotationPresent(VelocityEventListener.class)) {
50 | serverPlatformAdapter.unregisterEventListener(bean);
51 | log.debug("Unregistered {} from event manager.", bean.getClass().getSimpleName());
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-velocity/src/main/java/dev/temez/springlify/platform/server/VelocityServerPlatformAdapter.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.server;
2 |
3 | import com.velocitypowered.api.command.Command;
4 | import com.velocitypowered.api.command.CommandManager;
5 | import com.velocitypowered.api.event.EventManager;
6 | import dev.temez.springlify.starter.plugin.SpringlifyVelocityPlugin;
7 | import lombok.AccessLevel;
8 | import lombok.RequiredArgsConstructor;
9 | import lombok.experimental.FieldDefaults;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.jetbrains.annotations.NotNull;
12 | import org.springframework.stereotype.Component;
13 |
14 | @Slf4j
15 | @Component
16 | @RequiredArgsConstructor
17 | @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
18 | public class VelocityServerPlatformAdapter implements ServerPlatformAdapter {
19 |
20 | @NotNull
21 | EventManager eventManager;
22 |
23 | @NotNull
24 | CommandManager commandManager;
25 |
26 | @NotNull
27 | SpringlifyVelocityPlugin plugin;
28 |
29 | @Override
30 | public void registerEventListener(@NotNull Object listener) {
31 | eventManager.register(plugin, listener);
32 | log.debug("Registered {} as an event listener", listener.getClass().getSimpleName());
33 |
34 | }
35 |
36 | @Override
37 | public void unregisterEventListener(@NotNull Object listener) {
38 | eventManager.unregisterListener(plugin, listener);
39 | log.debug("Unregistered event listener: {}", listener.getClass().getSimpleName());
40 |
41 | }
42 |
43 | @Override
44 | public void registerCommandExecutor(@NotNull String command, @NotNull Object commandExecutor, @NotNull String... alias) {
45 | commandManager.register(command, (Command) commandExecutor, alias);
46 | log.debug("Registered {} as a command executor", commandExecutor.getClass().getSimpleName());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/springlify-starter/README.md:
--------------------------------------------------------------------------------
1 | # springlify-starter
2 |
3 | A core module of the library that enables the usage of the `Spring Framework` with minor platform-specific improvements.
4 | It contains necessary abstractions and mechanisms to ensure compatibility with platforms such as `Bukkit`, `Velocity`
5 | and others.
6 |
7 | The module includes a `Spring Boot` configuration loader and a platform adapter for registering event listeners.
8 |
9 | Features
10 |
11 | - Spring Framework Integration: Seamlessly integrate Spring into your Minecraft plugin development.
12 | - Configuration Loader: Easily load and manage Spring configurations while developing plugins.
13 | - Platform Adapter: Easily register event listeners and command handlers specific to the platform.
14 |
15 | Select a link to the platform documentation.
16 |
17 | - [springlify-starter-bukkit](/springlify-starter-bukkit/README.md)
18 | - [springlify-starter-commons](/springlify-starter-commons/README.md)
--------------------------------------------------------------------------------
/springlify-starter/springlify-starter-bukkit/README.md:
--------------------------------------------------------------------------------
1 | # springlify-starter
2 |
3 | First, you need to create a Spring application class. Notice, spring application class and plugin main are not the same
4 | things.
5 | Specify base `scanBasePackages` for scanning through the library classes and our application ones.
6 |
7 | ```java
8 | @SpringBootApplication(
9 | scanBasePackages = {
10 | "dev.temez.springlify",
11 | "dev.temez.demo"
12 | }
13 | )
14 | public class SpringlifyDemoApplication {
15 |
16 | }
17 | ```
18 |
19 | Then, the main class of your plugin. You should extend your class from `SpringlifyBukkitPlugin`.
20 |
21 | ```java
22 | @SpringlifyApplication(
23 | springApplicationClass = SpringlifyExampleApplication.class
24 | )
25 | public final class SpringlifyDemoPlugin extends SpringlifyBukkitPlugin {
26 |
27 |
28 | }
29 | ```
30 |
31 | To build your project, use `./gradlew shadowJar` task.
32 |
33 | You are now ready to implement the main functionality of your plugin.
34 | Refer to the examples provided in `springlify-examples:example-bukkit-plugin` for guidance and good luck.
35 |
36 | ### Other starter features
37 |
38 | #### 1. Event handler auto registration
39 |
40 | Starter has a build in `EventHandlerInitializer`.
41 | It automatically will register and unregister a classes, which implement `Listener` as Bukkit event listeners.
42 |
43 | ```java
44 |
45 | @Component
46 | public class PlayerJoinListener implements Listener {
47 |
48 | @EventHandler
49 | public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
50 | event.getPlayer().sendMessage("Welcome to the server!");
51 | }
52 | }
53 | ```
54 |
55 | #### 2. Command executor and completer auto registration
56 |
57 | Starter has a build in `CommandHandlerInitializer`. It will register classes which implement
58 | `CommandExecutor` and `TabCompleter` as Bukkit command executors and completers.
59 |
60 | ```java
61 |
62 | @BukkitCommand(command = "test")
63 | public class HelloCommand implements CommandExecutor {
64 |
65 | @Override
66 | public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String @NotNull [] args) {
67 | sender.sendMessage("Hello world!");
68 | return true;
69 | }
70 | }
71 | ```
--------------------------------------------------------------------------------
/springlify-starter/springlify-starter-bukkit/springlify-starter-bukkit.gradle:
--------------------------------------------------------------------------------
1 | //file:noinspection GroovyAssignabilityCheck
2 | //file:noinspection DependencyNotationArgument
3 | dependencies {
4 | compileOnly libs.paper.paperapi
5 |
6 | api project(":springlify-starter:springlify-starter-commons")
7 |
8 | testImplementation libs.paper.paperapi
9 | }
--------------------------------------------------------------------------------
/springlify-starter/springlify-starter-bukkit/src/main/java/dev/temez/springlify/starter/plugin/SpringlifyBukkitPlugin.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.starter.plugin;
2 |
3 | import dev.temez.springlify.starter.configuration.loader.ConfigurationLoader;
4 | import dev.temez.springlify.starter.configuration.loader.ConfigurationLoaderImpl;
5 | import dev.temez.springlify.starter.initializer.SpringlifyInitializer;
6 | import dev.temez.springlify.starter.initializer.SpringlifyInitializerImpl;
7 | import dev.temez.springlify.starter.initializer.loader.ClassLoaderFactory;
8 | import dev.temez.springlify.starter.initializer.loader.CompoundClassLoaderFactory;
9 | import lombok.AccessLevel;
10 | import lombok.Getter;
11 | import lombok.Setter;
12 | import lombok.experimental.FieldDefaults;
13 | import lombok.experimental.NonFinal;
14 | import org.bukkit.plugin.java.JavaPlugin;
15 | import org.jetbrains.annotations.NotNull;
16 | import org.springframework.context.ConfigurableApplicationContext;
17 |
18 | /**
19 | * Base class for Bukkit plugins using the Springlify.
20 | *
21 | * This abstract class extends {@link JavaPlugin} and implements {@link SpringlifyPlugin}.
22 | * It initializes necessary components for integrating Spring with Bukkit {@link ClassLoaderFactory}, and {@link ConfigurationLoader}.
23 | * It also provides lifecycle management methods for enabling and disabling the plugin. This annotation is used to specify the main Spring application class that will be
15 | * used to initialize the Spring context within a Bukkit plugin. Usage: This class provides Spring beans for the {@link SpringlifyInitializer}
13 | * by retrieving them from the provided {@link SpringlifyPlugin} instance. This interface defines a method for loading configurations into a {@link ConfigurableApplicationContext}
11 | * for a given {@link SpringlifyPlugin}. Implementations of this interface will provide the logic
12 | * for loading configurations from various sources into the Spring context. This interface defines a method for initializing a {@link ConfigurableApplicationContext} for a given
11 | * {@link SpringlifyPlugin}. Implementations of this interface will provide the logic for setting up
12 | * the Spring context. This interface defines a method for creating a {@link ClassLoader} specific to a {@link SpringlifyPlugin}.
10 | * Implementations of this interface will provide the logic for creating and configuring the class loader. This class implements {@link ClassLoaderFactory} and provides a method for creating a {@link CompoundClassLoader}
13 | * that combines multiple class loaders. The created class loader includes the class loader of the plugin
14 | * and the context class loader of the current thread. the type of the source object
25 | * @param R map(@NotNull S source, @NotNull Class the type of the source objects
37 | * @param Collection source, @NotNull Class the type of the source objects
22 | * @param MappingSchema getSchema(@NotNull Class sourceClass, @NotNull Class the type of the source objects
14 | * @param {
18 |
19 | /**
20 | * Maps a source object to a result object.
21 | *
22 | * @param source the source object to map
23 | * @return the mapped result object
24 | */
25 | @NotNull
26 | R map(@NotNull S source);
27 |
28 | /**
29 | * Maps a collection of source objects to a collection of result objects.
30 | *
31 | * @param sourceList the collection of source objects to map
32 | * @return the collection of mapped result objects
33 | */
34 | default @NotNull Collection sourceList) {
35 | return sourceList.stream()
36 | .map(this::map)
37 | .toList();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-commons/src/main/java/dev/temez/springlify/platform/exception/FormattingException.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.exception;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | public class FormattingException extends RuntimeException {
6 |
7 | public FormattingException(@NotNull String message) {
8 | super(message);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/springlify-platform/springlify-platform-commons/src/main/java/dev/temez/springlify/platform/exception/MappingException.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.platform.exception;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | /**
6 | * Exception thrown to indicate an error related to mapping operations.
7 | *
8 | * {@code
19 | * @VelocityComand(command="mycommand, alias = {"alias1", "alias2"})
20 | * public class MyCommand {
21 | *
22 | * // Command execution logic
23 | *
24 | * }
25 | * }
26 | *
27 | * {@code
20 | * @Service
21 | * @VelocityEventHandler
22 | * public class MyListenableService {
23 | *
24 | * @Subscribe
25 | * private void onEvent(@NotNull PlayerJoinEvent event) {
26 | * //event handling logic
27 | * }
28 | *
29 | * }
30 | * }
31 | *
32 | *
19 | * @SpringlifyApplication(springApplicationClass = MySpringApplication.class)
20 | * public class MyPlugin extends SpringlifyBukkitPlugin {
21 | * // Plugin code here
22 | * }
23 | *
24 | *
25 | * @since 0.7.0.0-RC1
26 | */
27 | @Target(ElementType.TYPE)
28 | @Retention(RetentionPolicy.RUNTIME)
29 | public @interface SpringlifyApplication {
30 |
31 | /**
32 | * Specifies the main Spring application class.
33 | *
34 | * @return the Spring application class
35 | */
36 | @NotNull Class> springApplicationClass();
37 | }
38 |
--------------------------------------------------------------------------------
/springlify-starter/springlify-starter-commons/src/main/java/dev/temez/springlify/starter/configuration/SpringlifyPluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package dev.temez.springlify.starter.configuration;
2 |
3 | import dev.temez.springlify.starter.initializer.SpringlifyInitializer;
4 | import dev.temez.springlify.starter.plugin.SpringlifyPlugin;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | /**
10 | * Spring configuration class for integrating Springlify plugins.
11 | *
12 | *