diff --git a/core/src/main/java/dev/triassic/template/TemplateImpl.java b/core/src/main/java/dev/triassic/template/TemplateImpl.java index e787d92..e240bc3 100644 --- a/core/src/main/java/dev/triassic/template/TemplateImpl.java +++ b/core/src/main/java/dev/triassic/template/TemplateImpl.java @@ -53,14 +53,15 @@ public void initialize() { final long startTime = System.currentTimeMillis(); try { - this.config = ConfigurationManager.load(dataDirectory, TemplateConfiguration.class); + this.config = ConfigurationManager.load( + dataDirectory, TemplateConfiguration.class, platformType); } catch (IOException e) { logger.error("Failed to load configuration", e); return; } this.commandRegistry = new CommandRegistry(this, commandManager); - commandRegistry.registerAll(); + commandRegistry.registerAll(platformType); logger.info("Enabled in {}ms", System.currentTimeMillis() - startTime); } diff --git a/core/src/main/java/dev/triassic/template/annotation/ExcludePlatform.java b/core/src/main/java/dev/triassic/template/annotation/ExcludePlatform.java new file mode 100644 index 0000000..b9db086 --- /dev/null +++ b/core/src/main/java/dev/triassic/template/annotation/ExcludePlatform.java @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: CC0-1.0 + * + * Dedicated to the public domain under CC0 1.0 Universal. + * + * You can obtain a full copy of the license at: + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +package dev.triassic.template.annotation; + +import dev.triassic.template.util.PlatformType; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Excludes a command class or configuration field from certain platforms. + * + *

Use this to prevent commands or config nodes from being registered or loaded + * on platforms where they are not supported. Elements without this annotation + * are included on all platforms by default.

+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.FIELD}) +public @interface ExcludePlatform { + + /** + * The platforms on which the annotated element should be excluded. + * + * @return an array of {@link PlatformType} to exclude + */ + PlatformType[] value(); +} diff --git a/core/src/main/java/dev/triassic/template/command/CommandRegistry.java b/core/src/main/java/dev/triassic/template/command/CommandRegistry.java index 135f2c0..f90d8e5 100644 --- a/core/src/main/java/dev/triassic/template/command/CommandRegistry.java +++ b/core/src/main/java/dev/triassic/template/command/CommandRegistry.java @@ -10,7 +10,10 @@ package dev.triassic.template.command; import dev.triassic.template.TemplateImpl; +import dev.triassic.template.annotation.ExcludePlatform; import dev.triassic.template.command.defaults.ReloadCommand; +import dev.triassic.template.util.PlatformType; +import java.util.Arrays; import java.util.List; import lombok.RequiredArgsConstructor; import org.incendo.cloud.CommandManager; @@ -27,11 +30,21 @@ public final class CommandRegistry { /** * Registers all commands with the command manager. */ - public void registerAll() { + public void registerAll(final PlatformType platformType) { final List commands = List.of( new ReloadCommand(instance) ); - commands.forEach(command -> command.register(commandManager)); + commands.forEach(command -> { + final ExcludePlatform exclude = command.getClass().getAnnotation(ExcludePlatform.class); + if (exclude != null) { + if (Arrays.asList(exclude.value()).contains(platformType)) { + return; + } + } + + command.register(commandManager); + }); } + } diff --git a/core/src/main/java/dev/triassic/template/command/defaults/ReloadCommand.java b/core/src/main/java/dev/triassic/template/command/defaults/ReloadCommand.java index e0c3d28..2a2cd44 100644 --- a/core/src/main/java/dev/triassic/template/command/defaults/ReloadCommand.java +++ b/core/src/main/java/dev/triassic/template/command/defaults/ReloadCommand.java @@ -10,10 +10,12 @@ package dev.triassic.template.command.defaults; import dev.triassic.template.TemplateImpl; +import dev.triassic.template.annotation.ExcludePlatform; import dev.triassic.template.command.Commander; import dev.triassic.template.command.TemplateCommand; import dev.triassic.template.configuration.ConfigurationManager; import dev.triassic.template.configuration.TemplateConfiguration; +import dev.triassic.template.util.PlatformType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/core/src/main/java/dev/triassic/template/configuration/ConfigurationManager.java b/core/src/main/java/dev/triassic/template/configuration/ConfigurationManager.java index c9ce1dd..0ebc2f1 100644 --- a/core/src/main/java/dev/triassic/template/configuration/ConfigurationManager.java +++ b/core/src/main/java/dev/triassic/template/configuration/ConfigurationManager.java @@ -10,6 +10,8 @@ package dev.triassic.template.configuration; import dev.triassic.template.BuildParameters; +import dev.triassic.template.annotation.ExcludePlatform; +import dev.triassic.template.util.PlatformType; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -20,6 +22,9 @@ import lombok.RequiredArgsConstructor; import org.spongepowered.configurate.CommentedConfigurationNode; import org.spongepowered.configurate.ConfigurateException; +import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.objectmapping.meta.Processor; +import org.spongepowered.configurate.serialize.TypeSerializerCollection; import org.spongepowered.configurate.yaml.NodeStyle; import org.spongepowered.configurate.yaml.YamlConfigurationLoader; @@ -57,14 +62,22 @@ public final class ConfigurationManager { */ public static ConfigurationManager load( Path path, - final Class clazz + final Class clazz, + final PlatformType platformType ) throws IOException { path = path.resolve("config.yml"); final YamlConfigurationLoader loader = YamlConfigurationLoader.builder() .indent(2) .nodeStyle(NodeStyle.BLOCK) - .defaultOptions(opts -> opts.header(HEADER)) + .defaultOptions(opts -> opts + .header(HEADER) + .serializers(TypeSerializerCollection.defaults().childBuilder() + .registerAnnotatedObjects(ObjectMapper.factoryBuilder() + .addProcessor(ExcludePlatform.class, excludePlatform(platformType)) + .build() + ) + .build())) .path(path) .build(); @@ -103,4 +116,17 @@ public CompletableFuture reload() { public T get() { return config.get(); } + + private static Processor.Factory excludePlatform( + final PlatformType platformType + ) { + return (annotation, fieldType) -> (value, destination) -> { + for (PlatformType platform : annotation.value()) { + if (platformType.equals(platform)) { + destination.parent().removeChild(destination.key()); + break; + } + } + }; + } } diff --git a/core/src/main/java/dev/triassic/template/configuration/TemplateConfiguration.java b/core/src/main/java/dev/triassic/template/configuration/TemplateConfiguration.java index 59f1d92..303a923 100644 --- a/core/src/main/java/dev/triassic/template/configuration/TemplateConfiguration.java +++ b/core/src/main/java/dev/triassic/template/configuration/TemplateConfiguration.java @@ -9,6 +9,8 @@ package dev.triassic.template.configuration; +import dev.triassic.template.annotation.ExcludePlatform; +import dev.triassic.template.util.PlatformType; import lombok.Getter; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; @@ -21,6 +23,17 @@ @SuppressWarnings("FieldMayBeFinal") public class TemplateConfiguration { + /** + * An example string that showcases the usage of {@link ExcludePlatform}. + * + *

Take note of how the {@link ExcludePlatform} annotation goes after + * the {@link Comment} annotation, it is important to do it in this order, + * otherwise the node will be recreated empty to add the comment.

+ */ + @Comment("This string should not appear on Velocity and Bungeecord platforms.") + @ExcludePlatform({PlatformType.BUNGEECORD, PlatformType.VELOCITY}) + private String exampleString = "This is an example string!"; + /** * The version of the configuration file. */