diff --git a/README.md b/README.md index 66a7e61..a818bfe 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ YetAnotherMessagesLibrary (YAML) =========== [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -![Version](https://repo.titanvale.net/api/badge/latest/releases/dev/peri/yetanothermessageslibrary/core?color=42c611&name=Releases&prefix=v) -![Version](https://repo.titanvale.net/api/badge/latest/snapshots/dev/peri/yetanothermessageslibrary/core?color=d45f48&name=Snapshots&prefix=v) +![Version](https://repo.mythicprojects.org/api/badge/latest/releases/org/mythicprojects/yetanothermessageslibrary/core?color=42c611&name=Releases&prefix=v) +![Version](https://repo.mythicprojects.org/api/badge/latest/snapshots/org/mythicprojects/yetanothermessageslibrary/core?color=d45f48&name=Snapshots&prefix=v) ![GitHub repo size](https://img.shields.io/github/repo-size/P3ridot/YetAnotherMessagesLibrary) Lightweight and modular *Minecraft Messages Library* based on [adventure](https://github.com/KyoriPowered/adventure). @@ -21,8 +21,8 @@ Implementations of values/messages suppliers or utilities class to easily add su ### Replaceable Implementations of `Replaceable` interface to easily replace placeholders in messages -- [okaeri-placeholders](https://github.com/OkaeriPoland/okaeri-placeholders) - [PlaceholderAPI](https://github.com/PlaceholderAPI/PlaceholderAPI) +- [okaeri-placeholders **\[EXPERIMENTAL\]**](https://github.com/OkaeriPoland/okaeri-placeholders) ## Maven/Gradle @@ -31,13 +31,13 @@ Implementations of `Replaceable` interface to easily replace placeholders in mes ```xml - titanvale-releases - https://repo.titanvale.net/releases + mythic-releases + https://repo.mythicprojects.org/releases - titanvale-snapshots - https://repo.titanvale.net/snapshots + mythic-snapshots + https://repo.mythicprojects.org/snapshots ``` @@ -55,13 +55,13 @@ Implementations of `Replaceable` interface to easily replace placeholders in mes repositories { // Releases maven { - name = "titanvale-releases" - url = "https://repo.titanvale.net/releases" + name = "mythic-releases" + url = "https://repo.mythicprojects.org/releases" } // Snapshots maven { - name = "titanvale-snapshots" - url = "https://repo.titanvale.net/snapshots" + name = "mythic-snapshots" + url = "https://repo.mythicprojects.org/snapshots" } } ``` diff --git a/build.gradle b/build.gradle index a1bffba..797e413 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { allprojects { group 'dev.peri.yetanothermessageslibrary' - version '6.8.0-SNAPSHOT' + version '7.0.0-SNAPSHOT' apply plugin: 'java-library' apply plugin: 'maven-publish' @@ -43,13 +43,12 @@ subprojects { publications { libraries(MavenPublication) { artifactId = project.name.toLowerCase() - from components.java pom { - url = "https://github.com/P3ridot/YetAnotherMessagesLibrary" + url = "https://github.com/Mythic-Projects/YetAnotherMessagesLibrary" name = project.name - description = "YetAnotherMessagesLibrary is simple Miecraft Messages Library based on `adventure`. It allows to easily send messages to players with built-in support for localization and placeholders." + description = "YetAnotherMessagesLibrary is simple Minecraft Messages Library based on `adventure`. It allows to easily send messages to players with built-in support for localization and placeholders." developers { developer { @@ -60,9 +59,9 @@ subprojects { } scm { - url = "https://github.com/P3ridot/YetAnotherMessagesLibrary.git" - connection = "git@github.com:P3ridot/YetAnotherMessagesLibrary.git" - developerConnection = "git@github.com:P3ridot/YetAnotherMessagesLibrary.git" + url = "https://github.com/Mythic-Projects/YetAnotherMessagesLibrary.git" + connection = "git@github.com:Mythic-Projects/YetAnotherMessagesLibrary.git" + developerConnection = "git@github.com:Mythic-Projects/YetAnotherMessagesLibrary.git" } licenses { @@ -93,8 +92,8 @@ subprojects { repositories { maven { - name "titanvale-repo" - url "https://repo.titanvale.net/${version.toString().endsWith('SNAPSHOT') ? 'snapshots' : 'releases'}" + name "mythic" + url "https://repo.mythicprojects.org/${version.toString().endsWith('SNAPSHOT') ? 'snapshots' : 'releases'}" credentials { username = System.getenv("MAVEN_NAME") diff --git a/core/build.gradle b/core/build.gradle index 32a12d8..ce8b74e 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,5 +1,3 @@ dependencies { - compileOnlyApi adventure.api - compileOnlyApi adventure.minimessage - compileOnlyApi adventure.serializer.legacy + api project(':tools') } \ No newline at end of file diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/MessageService.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/MessageService.java index 56d4e00..b7045ca 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/MessageService.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/MessageService.java @@ -1,17 +1,20 @@ package dev.peri.yetanothermessageslibrary; import dev.peri.yetanothermessageslibrary.locale.LocaleProvider; +import dev.peri.yetanothermessageslibrary.replace.ComponentReplacer; import dev.peri.yetanothermessageslibrary.replace.Replaceable; +import dev.peri.yetanothermessageslibrary.replace.StringReplaceable; import dev.peri.yetanothermessageslibrary.replace.StringReplacer; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; +import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; -public interface MessageService { +public interface MessageService { /** * Get message from repository @@ -23,7 +26,7 @@ public interface MessageService { * @param type of message * @return message */ - default T get(@Nullable Object entity, @NotNull Function<@NotNull C, @Nullable T> valueSupplier) { + default T get(@Nullable Object entity, @NotNull Function<@NotNull REPOSITORY, @Nullable T> valueSupplier) { Locale locale = this.getLocale(entity); return valueSupplier.apply(this.getRepository(locale)); } @@ -36,7 +39,7 @@ default T get(@Nullable Object entity, @NotNull Function<@NotNull C, @Nullab * @param type of message * @return message */ - default T get(@NotNull Function<@NotNull C, @Nullable T> valueSupplier) { + default T get(@NotNull Function<@NotNull REPOSITORY, @Nullable T> valueSupplier) { return this.get(null, valueSupplier); } @@ -50,7 +53,7 @@ default T get(@NotNull Function<@NotNull C, @Nullable T> valueSupplier) { * @param replacements replacements to replace in message * @return message with replaced placeholders */ - default String get(@Nullable Object entity, @NotNull Function<@NotNull C, @Nullable String> stringSupplier, @NotNull Replaceable... replacements) { + default String getString(@Nullable Object entity, @NotNull Function<@NotNull REPOSITORY, @Nullable String> stringSupplier, @NotNull StringReplaceable... replacements) { String string = this.get(entity, stringSupplier); if (string == null) { return null; @@ -59,6 +62,25 @@ default String get(@Nullable Object entity, @NotNull Function<@NotNull C, @Nulla return StringReplacer.replace(locale, string, replacements); } + /** + * Get message from repository and replace placeholders + * + * @param entity entity to find locale for using registered {@link LocaleProvider} + * use default locale if entity is null or no {@link LocaleProvider} is registered + * can be {@link Locale} if you want to use specific locale + * @param componentSupplier function to get message from repository + * @param replacements replacements to replace in message + * @return message with replaced placeholders + */ + default Component getComponent(@Nullable Object entity, @NotNull Function<@NotNull REPOSITORY, @Nullable Component> componentSupplier, @NotNull Replaceable... replacements) { + Component component = this.get(entity, componentSupplier); + if (component == null) { + return null; + } + Locale locale = this.getLocale(entity); + return ComponentReplacer.replace(locale, component, replacements); + } + /** * Get message from repository with default locale and replace placeholders * @@ -69,7 +91,7 @@ default String get(@Nullable Object entity, @NotNull Function<@NotNull C, @Nulla * @param replacements replacements to replace in message * @return message with replaced placeholders */ - default List getList(@Nullable Object entity, @NotNull Function<@NotNull C, @Nullable List> listSupplier, @NotNull Replaceable... replacements) { + default List getStringList(@Nullable Object entity, @NotNull Function<@NotNull REPOSITORY, @Nullable List> listSupplier, @NotNull StringReplaceable... replacements) { List stringList = this.get(entity, listSupplier); if (stringList == null || stringList.isEmpty()) { return stringList; @@ -78,6 +100,25 @@ default List getList(@Nullable Object entity, @NotNull Function<@NotNull return StringReplacer.replace(locale, stringList, replacements); } + /** + * Get message from repository with default locale and replace placeholders + * + * @param entity entity to find locale for using registered {@link LocaleProvider} + * use default locale if entity is null or no {@link LocaleProvider} is registered + * can be {@link Locale} if you want to use specific locale + * @param listSupplier function to get message from repository + * @param replacements replacements to replace in message + * @return message with replaced placeholders + */ + default List getComponentList(@Nullable Object entity, @NotNull Function<@NotNull REPOSITORY, @Nullable List> listSupplier, @NotNull Replaceable... replacements) { + List componentList = this.get(entity, listSupplier); + if (componentList == null || componentList.isEmpty()) { + return componentList; + } + Locale locale = this.getLocale(entity); + return ComponentReplacer.replace(locale, componentList, replacements); + } + /** * Set default locale that will be used if: *
    @@ -148,7 +189,7 @@ default List getList(@Nullable Object entity, @NotNull Function<@NotNull * * @return message repositories */ - @NotNull @Unmodifiable Map getMessageRepositories(); + @NotNull @Unmodifiable Map getMessageRepositories(); /** * Get message repository for locale @@ -156,7 +197,7 @@ default List getList(@Nullable Object entity, @NotNull Function<@NotNull * @param locale locale * @return message repository */ - @NotNull C getRepository(@NotNull Locale locale); + @NotNull REPOSITORY getRepository(@NotNull Locale locale); /** * Register message repository for locale @@ -164,7 +205,7 @@ default List getList(@Nullable Object entity, @NotNull Function<@NotNull * @param locale locale * @param messageRepository message repository */ - void registerRepository(@NotNull Locale locale, @NotNull C messageRepository); + void registerRepository(@NotNull Locale locale, @NotNull REPOSITORY messageRepository); /** * Register message repository for locale and set it as default @@ -172,7 +213,7 @@ default List getList(@Nullable Object entity, @NotNull Function<@NotNull * @param defaultLocale default locale * @param messageRepository message repository */ - default void registerDefaultRepository(@NotNull Locale defaultLocale, @NotNull C messageRepository) { + default void registerDefaultRepository(@NotNull Locale defaultLocale, @NotNull REPOSITORY messageRepository) { this.setDefaultLocale(defaultLocale); this.registerRepository(defaultLocale, messageRepository); } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/SendableMessageService.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/SendableMessageService.java index 9d136b0..1d0bc6a 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/SendableMessageService.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/SendableMessageService.java @@ -8,7 +8,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface SendableMessageService> extends MessageService { +public interface SendableMessageService> + extends MessageService { /** * Wrap message in {@link MessageDispatcher} to easily send it @@ -17,12 +18,12 @@ public interface SendableMessageService messageSupplier) { + default DISPATCHER getMessage(@NotNull Function<@NotNull REPOSITORY, @Nullable Sendable> messageSupplier) { return this.getDispatcherFactory().prepareDispatcher(this.getViewerService(), this::getLocale, (entity) -> this.get(entity, messageSupplier)); } - @NotNull ViewerService getViewerService(); + @NotNull ViewerService getViewerService(); - @NotNull MessageDispatcherFactory getDispatcherFactory(); + @NotNull MessageDispatcherFactory getDispatcherFactory(); } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleMessageService.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleMessageService.java index 4c300a7..31737ad 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleMessageService.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleMessageService.java @@ -12,11 +12,11 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; -public abstract class SimpleMessageService implements MessageService { +public abstract class SimpleMessageService implements MessageService { private Locale defaultLocale = Locale.getDefault(); private final Collection> localeProviders = new LinkedHashSet<>(); - private final Map messageRepositories = new LinkedHashMap<>(); + private final Map messageRepositories = new LinkedHashMap<>(); @Override public @NotNull Locale getDefaultLocale() { @@ -45,13 +45,13 @@ public void registerLocaleProvider(@NotNull LocaleProvider localeProvider) { } @Override - public @NotNull @Unmodifiable Map getMessageRepositories() { + public @NotNull @Unmodifiable Map getMessageRepositories() { return Collections.unmodifiableMap(this.messageRepositories); } @Override - public @NotNull C getRepository(@NotNull Locale locale) { - C messageRepository = this.messageRepositories.get(locale); + public @NotNull REPOSITORY getRepository(@NotNull Locale locale) { + REPOSITORY messageRepository = this.messageRepositories.get(locale); if (messageRepository == null) { // If we can't find message repository for language wariant (for e.g. en_GB) we will try to find message repository for language (for e.g. en) messageRepository = this.messageRepositories.get(Locale.forLanguageTag(locale.getLanguage())); @@ -69,7 +69,7 @@ public void registerLocaleProvider(@NotNull LocaleProvider localeProvider) { } @Override - public void registerRepository(@NotNull Locale locale, @NotNull C messageRepository) { + public void registerRepository(@NotNull Locale locale, @NotNull REPOSITORY messageRepository) { Validate.notNull(locale, "Locale cannot be null"); Validate.notNull(messageRepository, "Message repository cannot be null"); this.messageRepositories.put(locale, messageRepository); diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleSendableMessageService.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleSendableMessageService.java index e87b4b7..093c846 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleSendableMessageService.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/SimpleSendableMessageService.java @@ -7,23 +7,25 @@ import dev.peri.yetanothermessageslibrary.viewer.ViewerService; import org.jetbrains.annotations.NotNull; -public abstract class SimpleSendableMessageService> extends SimpleMessageService implements SendableMessageService { +public abstract class SimpleSendableMessageService> + extends SimpleMessageService + implements SendableMessageService { - private final ViewerService viewerService; - private final MessageDispatcherFactory dispatcherFactory; + private final ViewerService viewerService; + private final MessageDispatcherFactory dispatcherFactory; public SimpleSendableMessageService( - @NotNull ViewerService viewerService, - @NotNull MessageDispatcherFactory dispatcherFactory + @NotNull ViewerService viewerService, + @NotNull MessageDispatcherFactory dispatcherFactory ) { this.viewerService = viewerService; this.dispatcherFactory = dispatcherFactory; } public SimpleSendableMessageService( - @NotNull ViewerDataSupplier viewerDataSupplier, - @NotNull ViewerFactory viewerFactory, - @NotNull MessageDispatcherFactory dispatcherFactory + @NotNull ViewerDataSupplier viewerDataSupplier, + @NotNull ViewerFactory viewerFactory, + @NotNull MessageDispatcherFactory dispatcherFactory ) { this( new ViewerService<>(viewerDataSupplier, viewerFactory), @@ -32,12 +34,12 @@ public SimpleSendableMessageService( } @Override - public @NotNull ViewerService getViewerService() { + public @NotNull ViewerService getViewerService() { return this.viewerService; } @Override - public @NotNull MessageDispatcherFactory getDispatcherFactory() { + public @NotNull MessageDispatcherFactory getDispatcherFactory() { return this.dispatcherFactory; } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/AdventureHelper.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/AdventureHelper.java deleted file mode 100644 index bd01242..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/AdventureHelper.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.peri.yetanothermessageslibrary.adventure; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.jetbrains.annotations.NotNull; - -public final class AdventureHelper { - - private AdventureHelper() { - } - - private static final LegacyComponentSerializer LEGACY_SECTION = LegacyComponentSerializer.legacySection(); - private static final LegacyComponentSerializer LEGACY_AMPERSAND = LegacyComponentSerializer.legacyAmpersand(); - - public static @NotNull Component legacyToComponent(@NotNull String legacyText) { - return LEGACY_SECTION.deserialize(legacyText); //TODO: Find better way without using legacy serializer - } - - public static @NotNull String componentToAmpersandString(@NotNull Component component) { - return LEGACY_AMPERSAND.serialize(component); //TODO: Find better way without using legacy serializer - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/MiniComponent.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/MiniComponent.java deleted file mode 100644 index cdb8a04..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/MiniComponent.java +++ /dev/null @@ -1,61 +0,0 @@ -package dev.peri.yetanothermessageslibrary.adventure; - -import java.util.regex.Pattern; -import net.kyori.adventure.text.TextReplacementConfig; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.jetbrains.annotations.NotNull; - -/** - * Some utility class to make MiniMessage optional - */ -public final class MiniComponent { - - private static final Pattern SECTION_COLOR_PATTERN = Pattern.compile("(?i)ยง([0-9A-FK-OR])"); - private static final Pattern ALL_TEXT_PATTERN = Pattern.compile(".*"); - - private static final Pattern HEX_TO_LEGACY_PATTERN = Pattern.compile("&#([0-9A-Fa-f]{1})([0-9A-Fa-f]{1})([0-9A-Fa-f]{1})([0-9A-Fa-f]{1})([0-9A-Fa-f]{1})([0-9A-Fa-f]{1})"); - private static final String LEGACY_HEX_REPLACEMENT = "&x&$1&$2&$3&$4&$5&$6"; - - private static final LegacyComponentSerializer AMPERSAND_SERIALIZER = LegacyComponentSerializer.legacyAmpersand(); - private static final TextReplacementConfig COLOR_REPLACEMENTS = TextReplacementConfig.builder() - .match(ALL_TEXT_PATTERN) - .replacement((result, input) -> AMPERSAND_SERIALIZER.deserialize(result.group())) - .build(); - private static final MiniMessage MINI_MESSAGE = MiniMessage.builder() - .preProcessor(text -> { - String processedText = HEX_TO_LEGACY_PATTERN.matcher(text).replaceAll(LEGACY_HEX_REPLACEMENT); // convert simple hex format to legacy - processedText = SECTION_COLOR_PATTERN.matcher(processedText).replaceAll("&$1"); // convert section to ampersand - return processedText; - }) - .postProcessor(component -> component.replaceText(COLOR_REPLACEMENTS)) - .build(); - - private MiniComponent() { - } - - /** - * Parse a string to {@link RawComponent} using {@link MiniMessage}. - * - * @param raw the string to parse. - * @return the parsed component. - */ - public static @NotNull RawComponent of(@NotNull String raw) { - return new RawComponent(raw, MINI_MESSAGE.deserialize(raw)); - } - - /** - * Parse multiple strings to {@link RawComponent} using {@link MiniMessage}. - * - * @param raw array of strings to parse. - * @return array of parsed components. - */ - public static @NotNull RawComponent[] of(@NotNull String... raw) { - RawComponent[] miniComponents = new RawComponent[raw.length]; - for (int i = 0; i < raw.length; i++) { - miniComponents[i] = MiniComponent.of(raw[i]); - } - return miniComponents; - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/RawComponent.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/RawComponent.java deleted file mode 100644 index 64ca3e8..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/adventure/RawComponent.java +++ /dev/null @@ -1,30 +0,0 @@ -package dev.peri.yetanothermessageslibrary.adventure; - -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.NotNull; - -/** - * Utility class to store raw String and Component at the same time. - * Helpful with serialization and deserialization of components. - */ -public class RawComponent { - - public static final RawComponent EMPTY = new RawComponent("", Component.empty()); - - private final String raw; - private final Component component; - - public RawComponent(@NotNull String raw, @NotNull Component component) { - this.raw = raw; - this.component = component; - } - - public @NotNull String getRaw() { - return this.raw; - } - - public @NotNull Component getComponent() { - return this.component; - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcher.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcher.java index 66981e4..f258e07 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcher.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcher.java @@ -3,153 +3,228 @@ import dev.peri.yetanothermessageslibrary.replace.Replaceable; import dev.peri.yetanothermessageslibrary.replace.replacement.Replacement; import dev.peri.yetanothermessageslibrary.util.TriFunction; -import dev.peri.yetanothermessageslibrary.viewer.Viewer; -import dev.peri.yetanothermessageslibrary.viewer.ViewerService; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.WeakHashMap; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; +import java.util.regex.Pattern; +import net.kyori.adventure.text.ComponentLike; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * MessageDispatcher is a class that allows you to send messages to receivers with placeholders and actions. + * It highly simplifies the process of sending messages to multiple receivers in multiple languages etc. + * + * @param the type of the receiver + * @param the type of the dispatcher itself + */ @SuppressWarnings("unchecked") -public class MessageDispatcher> { - - private final ViewerService viewerService; - private final Function localeSupplier; - private final Function messageSupplier; - - private final Set receivers = Collections.newSetFromMap(new WeakHashMap<>()); - private final Set> predicates = new HashSet<>(); - private final Set> actions = new HashSet<>(); - - private final Map fields = new WeakHashMap<>(); - private final List replacements = new ArrayList<>(); - @SuppressWarnings("rawtypes") - private final List replacementSuppliers = new ArrayList<>(); - - public MessageDispatcher( - @NotNull ViewerService viewerService, - @NotNull Function<@Nullable Object, @NotNull Locale> localeSupplier, - @NotNull Function<@Nullable Object, @Nullable Sendable> messageSupplier - ) { - this.viewerService = viewerService; - this.localeSupplier = localeSupplier; - this.messageSupplier = messageSupplier; +public interface MessageDispatcher> { + + /** + * Add a receiver to the dispatcher + * + * @param receiver the receiver + * @return this dispatcher + */ + @Contract("_ -> this") + DISPATCHER receiver(@Nullable RECEIVER receiver); + + /** + * Add multiple receivers to the dispatcher + * + * @param receivers the receivers + * @return this dispatcher + */ + @Contract("_ -> this") + default DISPATCHER receivers(@NotNull Collection receivers) { + receivers.forEach(this::receiver); + return (DISPATCHER) this; } + /** + * Add multiple receivers to the dispatcher + * + * @param receivers the receivers + * @return this dispatcher + */ @Contract("_ -> this") - public D receiver(@Nullable R receiver) { - if (receiver == null) { - return (D) this; + default DISPATCHER receivers(@NotNull RECEIVER... receivers) { + for (RECEIVER receiver : receivers) { + this.receiver(receiver); } + return (DISPATCHER) this; + } - this.receivers.add(receiver); - return (D) this; + /** + * Add all players to the dispatcher + * + * @return this dispatcher + * @throws UnsupportedOperationException if the operation is not implemented in the current MessageDispatcher + */ + @Contract(" -> this") + default DISPATCHER all() throws UnsupportedOperationException { + this.allPlayers(); + this.console(); + return (DISPATCHER) this; } - @Contract("_ -> this") - public D receivers(@NotNull Collection receivers) { - receivers.forEach(this::receiver); - return (D) this; + /** + * Add all players to the dispatcher + * + * @return this dispatcher + * @throws UnsupportedOperationException if the operation is not implemented in the current MessageDispatcher + */ + @Contract(" -> this") + default DISPATCHER allPlayers() throws UnsupportedOperationException { + throw new UnsupportedOperationException("allPlayers is not supported by this MessageDispatcher"); } - @Contract("_ -> this") - public D predicate(@NotNull Predicate<@NotNull R> predicate) { - this.predicates.add(predicate); - return (D) this; + /** + * Add all viewers to the dispatcher + * + * @return this dispatcher + * @throws UnsupportedOperationException if the operation is not implemented in the current MessageDispatcher + */ + @Contract(" -> this") + default DISPATCHER console() throws UnsupportedOperationException { + throw new UnsupportedOperationException("console is not supported by this MessageDispatcher"); } + /** + * Add a predicate to the dispatcher + * + * @param predicate the predicate + * @return this dispatcher + */ + @Contract("_ -> this") + DISPATCHER predicate(@NotNull Predicate predicate); + + /** + * Add a predicate to the dispatcher for a specific receiver class + * + * @param receiverClass the class of the receiver + * @param predicate the predicate + * @param the type of the receiver + * @return this dispatcher + */ @Contract("_, _ -> this") - public D predicate(@NotNull Class requiredType, @NotNull Predicate<@NotNull T> predicate) { + default DISPATCHER predicate(@NotNull Class receiverClass, @NotNull Predicate predicate) { return this.predicate(receiver -> { - if (!requiredType.isInstance(receiver)) { + if (!receiverClass.isInstance(receiver)) { return false; } - return predicate.test(requiredType.cast(receiver)); + return predicate.test(receiverClass.cast(receiver)); }); } + /** + * Add a field to the dispatcher to use by the replacements + * + * @param key the key of the field + * @param value the value of the field + * @return this dispatcher + */ + @Contract("_, _ -> this") + DISPATCHER field(@NotNull String key, @Nullable Object value); + + /** + * Add multiple fields to the dispatcher to use by the replacements + * + * @param fields the fields + * @return this dispatcher + */ + @Contract("_ -> this") + DISPATCHER fields(@NotNull Map fields); + + @Contract("_ -> this") + DISPATCHER with(@NotNull Replaceable replacement); + + @Contract("_ -> this") + DISPATCHER with(@NotNull Replaceable @NotNull ... replacement); + @Contract("_ -> this") - public D action(@NotNull Consumer<@NotNull R> action) { - this.actions.add(action); - return (D) this; + DISPATCHER with(@NotNull Iterable replacements); + + default DISPATCHER with(@NotNull String placeholder, @NotNull ComponentLike replacement) { + return this.with(Replacement.component(placeholder, replacement)); } - @Contract("_, _ -> this") - public D field(@NotNull String key, @Nullable Object value) { - this.fields.put(key, value); - return (D) this; + default DISPATCHER with(@NotNull Pattern placeholder, @NotNull ComponentLike replacement) { + return this.with(Replacement.component(placeholder, replacement)); } - @Contract("_, -> this") - public D fields(@NotNull Map<@NotNull String, @Nullable Object> fields) { - this.fields.putAll(fields); - return (D) this; + default DISPATCHER with(@NotNull String placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull ComponentLike> replacement) { + return this.with(Replacement.component(placeholder, replacement)); } - @Contract("_ -> this") - public D with(@NotNull Replaceable replacement) { - this.replacements.add(replacement); - return (D) this; + default DISPATCHER with(@NotNull Pattern placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull ComponentLike> replacement) { + return this.with(Replacement.component(placeholder, replacement)); } - @Contract("_ -> this") - public D with(@NotNull Replaceable @NotNull ... replacement) { - Collections.addAll(this.replacements, replacement); - return (D) this; + default DISPATCHER with(@NotNull String placeholder, @NotNull Supplier replacement) { + return this.with(Replacement.component(placeholder, replacement)); } - @Contract("_ -> this") - public D with(@NotNull Iterable replacements) { - replacements.forEach(this.replacements::add); - return (D) this; + default DISPATCHER with(@NotNull Pattern placeholder, @NotNull Supplier replacement) { + return this.with(Replacement.component(placeholder, replacement)); + } + + @Contract("_, _ -> this") + default DISPATCHER with(@NotNull String placeholder, @NotNull Object replacement) { + return this.with(Replacement.string(placeholder, replacement)); } @Contract("_, _ -> this") - public D with(@NotNull String from, @NotNull Object to) { - return this.with(Replacement.of(from, to)); + default DISPATCHER with(@NotNull Pattern placeholder, @NotNull Object replacement) { + return this.with(Replacement.string(placeholder, replacement)); } @Contract("_, _ -> this") - public D with(@NotNull String from, @NotNull Supplier<@NotNull Object> to) { - return this.with(Replacement.of(from, to)); + default DISPATCHER withString(@NotNull String placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull Object> replacement) { + return this.with(Replacement.string(placeholder, replacement)); + } + + @Contract("_, _ -> this") + default DISPATCHER withString(@NotNull Pattern placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull Object> replacement) { + return this.with(Replacement.string(placeholder, replacement)); + } + + @Contract("_, _ -> this") + default DISPATCHER withString(@NotNull String placeholder, @NotNull Supplier replacement) { + return this.with(Replacement.string(placeholder, replacement)); + } + + @Contract("_, _ -> this") + default DISPATCHER withString(@NotNull Pattern placeholder, @NotNull Supplier replacement) { + return this.with(Replacement.string(placeholder, replacement)); } @Contract("_, _, _ -> this") - public D with( - @NotNull Class requiredType, + DISPATCHER with( + @Nullable Class requiredType, @NotNull TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> replacementSupplier, - @Nullable TriFunction<@NotNull R, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier - ) { - this.replacementSuppliers.add(new ReplaceableSupplier<>(requiredType, replacementSupplier, fallbackSupplier)); - return (D) this; - } + @Nullable TriFunction<@NotNull RECEIVER, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier + ); @Contract("_, _ -> this") - public D with( - @NotNull Class requiredType, + default DISPATCHER with( + @Nullable Class requiredType, @NotNull TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> replacementSupplier ) { return this.with(requiredType, replacementSupplier, null); } @Contract("_, _, _ -> this") - public D with( - @NotNull Class requiredType, + default DISPATCHER with( + @Nullable Class requiredType, @NotNull Function<@NotNull T, ? extends @NotNull Replaceable> replacementSupplier, - @Nullable Function<@NotNull R, ? extends @NotNull Replaceable> fallbackSupplier + @Nullable Function<@NotNull RECEIVER, ? extends @NotNull Replaceable> fallbackSupplier ) { return this.with( requiredType, @@ -161,93 +236,37 @@ public D with( } @Contract("_, _ -> this") - public D with( - @NotNull Class requiredType, + default DISPATCHER with( + @Nullable Class requiredType, @NotNull Function<@NotNull T, ? extends @NotNull Replaceable> replacementSupplier ) { return this.with(requiredType, replacementSupplier, null); } @Contract("_, _ -> this") - public D with( - @NotNull Class requiredType, + default DISPATCHER with( + @Nullable Class requiredType, @NotNull Collection> replacementSuppliers ) { replacementSuppliers.forEach(replacementSupplier -> this.with(requiredType, replacementSupplier)); - return (D) this; + return (DISPATCHER) this; } - @Contract(" -> this") - public D send() { - this.receivers.forEach(this::sendTo); - return (D) this; - } - - private void sendTo(@NotNull R receiver) { - Locale locale = this.localeSupplier.apply(receiver); - - Sendable message = this.messageSupplier.apply(locale); - if (message == null) { - return; - } - - if (this.predicates.stream().anyMatch(predicate -> !predicate.test(receiver))) { - return; - } - - Viewer viewer = this.viewerService.findOrCreateViewer(receiver); - List replaceables = this.prepareReplacements(receiver, locale); - message.send(locale, viewer, replaceables.toArray(new Replaceable[0])); - this.actions.forEach(action -> action.accept(receiver)); - } - - protected @NotNull List prepareReplacements(@NotNull R receiver, @NotNull Locale locale) { - List replacement = new ArrayList<>(this.replacements); - this.replacementSuppliers - .stream() - .map(supplier -> { - return supplier.supplyReplacement( - supplier.getEntityType().cast(receiver), - locale, - this.fields - ); - }) - .filter(Objects::nonNull) - .forEachOrdered(replacement::add); - return replacement; - } - - private class ReplaceableSupplier { - - private final Class entityType; - private final TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> supplier; - private final TriFunction<@NotNull R, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier; - - private ReplaceableSupplier( - @NotNull Class entityType, - @NotNull TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> supplier, - @Nullable TriFunction<@NotNull R, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier - ) { - this.entityType = entityType; - this.supplier = supplier; - this.fallbackSupplier = fallbackSupplier; - } - - public @NotNull Class getEntityType() { - return this.entityType; - } - - public @Nullable Replaceable supplyReplacement(@NotNull R receiver, @NotNull Locale locale, @NotNull Map<@NotNull String, @Nullable Object> fields) { - if (this.entityType.isInstance(receiver)) { - return this.supplier.apply(this.entityType.cast(receiver), locale, fields); - } - - if (this.fallbackSupplier == null) { - return null; - } - return this.fallbackSupplier.apply(receiver, locale, fields); - } + /** + * Add an action to the dispatcher that will be executed after the message is sent + * + * @param action the action + * @return this dispatcher + */ + @Contract("_ -> this") + DISPATCHER action(@NotNull Consumer action); - } + /** + * Send the message to all receivers + * + * @return this dispatcher + */ + @Contract(" -> this") + DISPATCHER send(); } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcherFactory.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcherFactory.java index 89e0bb2..18679c8 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcherFactory.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/MessageDispatcherFactory.java @@ -6,10 +6,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface MessageDispatcherFactory> { +public interface MessageDispatcherFactory> { - @NotNull D prepareDispatcher( - @NotNull ViewerService viewerService, + @NotNull DISPATCHER prepareDispatcher( + @NotNull ViewerService viewerService, @NotNull Function<@Nullable Object, @NotNull Locale> localeSupplier, @NotNull Function<@Nullable Object, @Nullable Sendable> messageSupplier ); diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SendableMessage.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SendableMessage.java index c6d1d0f..1940226 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SendableMessage.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SendableMessage.java @@ -1,7 +1,6 @@ package dev.peri.yetanothermessageslibrary.message; -import dev.peri.yetanothermessageslibrary.adventure.MiniComponent; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; import dev.peri.yetanothermessageslibrary.message.holder.SendableHolder; import dev.peri.yetanothermessageslibrary.message.holder.impl.ActionBarHolder; import dev.peri.yetanothermessageslibrary.message.holder.impl.BossBarHolder; @@ -19,6 +18,7 @@ import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,7 +85,7 @@ public Builder addHolders(@NotNull SendableHolder... holders) { * @return this builder */ @Contract("_, _ -> this") - public Builder chat(boolean onlyConsole, @NotNull RawComponent... messages) { + public Builder chat(boolean onlyConsole, @NotNull Component... messages) { return this.addHolders(new ChatHolder(onlyConsole, messages)); } @@ -96,7 +96,7 @@ public Builder chat(boolean onlyConsole, @NotNull RawComponent... messages) { * @return this builder */ @Contract("_, -> this") - public Builder chat(@NotNull RawComponent... messages) { + public Builder chat(@NotNull Component... messages) { return this.chat(false, messages); } @@ -110,7 +110,7 @@ public Builder chat(@NotNull RawComponent... messages) { */ @Contract("_, _ -> this") public Builder chat(boolean onlyConsole, @NotNull String... messages) { - return this.chat(onlyConsole, MiniComponent.of(messages)); + return this.chat(onlyConsole, GlobalAdventureSerializer.deserializeArray(messages)); } /** @@ -132,7 +132,7 @@ public Builder chat(@NotNull String... messages) { * @return this builder */ @Contract("_, -> this") - public Builder actionBar(@NotNull RawComponent message) { + public Builder actionBar(@NotNull Component message) { return this.addHolders(new ActionBarHolder(message)); } @@ -145,7 +145,7 @@ public Builder actionBar(@NotNull RawComponent message) { */ @Contract("_, -> this") public Builder actionBar(@NotNull String message) { - return this.actionBar(MiniComponent.of(message)); + return this.actionBar(GlobalAdventureSerializer.deserialize(message)); } /** @@ -159,7 +159,7 @@ public Builder actionBar(@NotNull String message) { * @return this builder */ @Contract("_, _, _, _, _ -> this") - public Builder title(@NotNull RawComponent title, @NotNull RawComponent subtitle, int fadeIn, int stay, int fadeOut) { + public Builder title(@NotNull Component title, @NotNull Component subtitle, int fadeIn, int stay, int fadeOut) { return this.addHolders(new TitleHolder(title, subtitle, TitleHolder.times(fadeIn, stay, fadeOut))); } @@ -176,7 +176,7 @@ public Builder title(@NotNull RawComponent title, @NotNull RawComponent subtitle */ @Contract("_, _, _, _, _ -> this") public Builder title(@NotNull String title, @NotNull String subtitle, int fadeIn, int stay, int fadeOut) { - return this.title(MiniComponent.of(title), MiniComponent.of(subtitle), fadeIn, stay, fadeOut); + return this.title(GlobalAdventureSerializer.deserialize(title), GlobalAdventureSerializer.deserialize(subtitle), fadeIn, stay, fadeOut); } /** @@ -190,7 +190,7 @@ public Builder title(@NotNull String title, @NotNull String subtitle, int fadeIn * @return this builder */ @Contract("_, _, _, _, _, _ -> this") - public Builder bossBar(@NotNull RawComponent name, float progress, @NotNull BossBar.Color color, @NotNull BossBar.Overlay overlay, @NotNull Collection flags, int stay) { + public Builder bossBar(@NotNull Component name, float progress, @NotNull BossBar.Color color, @NotNull BossBar.Overlay overlay, @NotNull Collection flags, int stay) { return this.addHolders(BossBarHolder.builder(name) .progress(progress) .color(color) @@ -213,7 +213,7 @@ public Builder bossBar(@NotNull RawComponent name, float progress, @NotNull Boss */ @Contract("_, _, _, _, _, _, -> this") public Builder bossBar(@NotNull String name, float progress, @NotNull BossBar.Color color, @NotNull BossBar.Overlay overlay, @NotNull Collection flags, int stay) { - return this.bossBar(MiniComponent.of(name), progress, color, overlay, flags, stay); + return this.bossBar(GlobalAdventureSerializer.deserialize(name), progress, color, overlay, flags, stay); } /** diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SimpleMessageDispatcher.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SimpleMessageDispatcher.java new file mode 100644 index 0000000..6b9945e --- /dev/null +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/SimpleMessageDispatcher.java @@ -0,0 +1,182 @@ +package dev.peri.yetanothermessageslibrary.message; + +import dev.peri.yetanothermessageslibrary.replace.Replaceable; +import dev.peri.yetanothermessageslibrary.util.TriFunction; +import dev.peri.yetanothermessageslibrary.viewer.Viewer; +import dev.peri.yetanothermessageslibrary.viewer.ViewerService; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@SuppressWarnings("unchecked") +public class SimpleMessageDispatcher> + implements MessageDispatcher { + + private final ViewerService viewerService; + private final Function localeSupplier; + private final Function messageSupplier; + + private final Set receivers = Collections.newSetFromMap(new WeakHashMap<>()); + private final Set> predicates = new HashSet<>(); + private final Set> actions = new HashSet<>(); + + private final Map fields = new WeakHashMap<>(); + private final List replacements = new ArrayList<>(); + @SuppressWarnings("rawtypes") + private final List replacementSuppliers = new ArrayList<>(); + + public SimpleMessageDispatcher( + @NotNull ViewerService viewerService, + @NotNull Function<@Nullable Object, @NotNull Locale> localeSupplier, + @NotNull Function<@Nullable Object, @Nullable Sendable> messageSupplier + ) { + this.viewerService = viewerService; + this.localeSupplier = localeSupplier; + this.messageSupplier = messageSupplier; + } + + @Contract("_ -> this") + public DISPATCHER receiver(@Nullable RECEIVER receiver) { + if (receiver == null) { + return (DISPATCHER) this; + } + + this.receivers.add(receiver); + return (DISPATCHER) this; + } + + @Contract("_ -> this") + public DISPATCHER predicate(@NotNull Predicate<@NotNull RECEIVER> predicate) { + this.predicates.add(predicate); + return (DISPATCHER) this; + } + + @Contract("_, _ -> this") + public DISPATCHER field(@NotNull String key, @Nullable Object value) { + this.fields.put(key, value); + return (DISPATCHER) this; + } + + @Contract("_, -> this") + public DISPATCHER fields(@NotNull Map<@NotNull String, @Nullable Object> fields) { + this.fields.putAll(fields); + return (DISPATCHER) this; + } + + @Contract("_ -> this") + public DISPATCHER with(@NotNull Replaceable replacement) { + this.replacements.add(replacement); + return (DISPATCHER) this; + } + + @Contract("_ -> this") + public DISPATCHER with(@NotNull Replaceable @NotNull ... replacement) { + Collections.addAll(this.replacements, replacement); + return (DISPATCHER) this; + } + + @Contract("_ -> this") + public DISPATCHER with(@NotNull Iterable replacements) { + replacements.forEach(this.replacements::add); + return (DISPATCHER) this; + } + + @Contract("_, _, _ -> this") + public DISPATCHER with( + @Nullable Class requiredType, + @NotNull TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> replacementSupplier, + @Nullable TriFunction<@NotNull RECEIVER, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier + ) { + this.replacementSuppliers.add(new ReplaceableSupplier<>(requiredType, replacementSupplier, fallbackSupplier)); + return (DISPATCHER) this; + } + + @Contract("_ -> this") + public DISPATCHER action(@NotNull Consumer<@NotNull RECEIVER> action) { + this.actions.add(action); + return (DISPATCHER) this; + } + + @Contract(" -> this") + public DISPATCHER send() { + this.receivers.forEach(this::sendTo); + return (DISPATCHER) this; + } + + private void sendTo(@NotNull RECEIVER receiver) { + Locale locale = this.localeSupplier.apply(receiver); + + Sendable message = this.messageSupplier.apply(locale); + if (message == null) { + return; + } + + if (this.predicates.stream().anyMatch(predicate -> !predicate.test(receiver))) { + return; + } + + Viewer viewer = this.viewerService.findOrCreateViewer(receiver); + List replaceables = this.prepareReplacements(receiver, locale); + message.send(locale, viewer, replaceables.toArray(new Replaceable[0])); + this.actions.forEach(action -> action.accept(receiver)); + } + + protected @NotNull List prepareReplacements(@NotNull RECEIVER receiver, @NotNull Locale locale) { + List replacement = new ArrayList<>(this.replacements); + this.replacementSuppliers + .stream() + .map(supplier -> supplier.supplyReplacement( + receiver, + locale, + this.fields + )) + .filter(Objects::nonNull) + .forEachOrdered(replacement::add); + return replacement; + } + + private class ReplaceableSupplier { + + private final Class entityType; + private final TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> supplier; + private final TriFunction<@NotNull RECEIVER, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier; + + private ReplaceableSupplier( + @Nullable Class entityType, + @NotNull TriFunction<@NotNull T, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> supplier, + @Nullable TriFunction<@NotNull RECEIVER, @NotNull Locale, @NotNull Map<@NotNull String, @Nullable Object>, ? extends @NotNull Replaceable> fallbackSupplier + ) { + this.entityType = entityType; + this.supplier = supplier; + this.fallbackSupplier = fallbackSupplier; + } + + public @Nullable Replaceable supplyReplacement(@NotNull RECEIVER receiver, @NotNull Locale locale, @NotNull Map<@NotNull String, @Nullable Object> fields) { + boolean needCast = this.entityType != null; + if (needCast && !this.entityType.isInstance(receiver)) { + return this.fallbackSupplier != null + ? this.fallbackSupplier.apply(receiver, locale, fields) + : null; + } + + T entity = needCast + ? this.entityType.cast(receiver) + : (T) receiver; + return this.supplier.apply(entity, locale, fields); + } + + } + +} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ActionBarHolder.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ActionBarHolder.java index e8b2cbe..d2dd3b4 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ActionBarHolder.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ActionBarHolder.java @@ -1,25 +1,25 @@ package dev.peri.yetanothermessageslibrary.message.holder.impl; -import dev.peri.yetanothermessageslibrary.adventure.MiniComponent; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; import dev.peri.yetanothermessageslibrary.message.SendableMessage; import dev.peri.yetanothermessageslibrary.message.holder.SendableHolder; import dev.peri.yetanothermessageslibrary.replace.ComponentReplacer; import dev.peri.yetanothermessageslibrary.replace.Replaceable; import dev.peri.yetanothermessageslibrary.viewer.Viewer; import java.util.Locale; +import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class ActionBarHolder extends SendableHolder { - private final RawComponent message; + private final Component message; - public ActionBarHolder(@NotNull RawComponent message) { + public ActionBarHolder(@NotNull Component message) { this.message = message; } - public @NotNull RawComponent getMessage() { + public @NotNull Component getMessage() { return this.message; } @@ -30,15 +30,15 @@ public void send(@Nullable Locale locale, @NotNull Viewer viewer, @NotNull Repla @Override public @NotNull SendableHolder copy(@NotNull Replaceable... replacements) { - return new ActionBarHolder(ComponentReplacer.replaceRaw(this.message, replacements)); + return new ActionBarHolder(ComponentReplacer.replace(this.message, replacements)); } - public static @NotNull SendableMessage message(@NotNull RawComponent message) { + public static @NotNull SendableMessage message(@NotNull Component message) { return SendableMessage.of(new ActionBarHolder(message)); } public static @NotNull SendableMessage message(@NotNull String message) { - return SendableMessage.of(new ActionBarHolder(MiniComponent.of(message))); + return SendableMessage.of(new ActionBarHolder(GlobalAdventureSerializer.deserialize(message))); } } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/BossBarHolder.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/BossBarHolder.java index 554ff88..4e4ec00 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/BossBarHolder.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/BossBarHolder.java @@ -1,7 +1,6 @@ package dev.peri.yetanothermessageslibrary.message.holder.impl; -import dev.peri.yetanothermessageslibrary.adventure.MiniComponent; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; import dev.peri.yetanothermessageslibrary.message.holder.SendableHolder; import dev.peri.yetanothermessageslibrary.replace.ComponentReplacer; import dev.peri.yetanothermessageslibrary.replace.Replaceable; @@ -11,13 +10,14 @@ import java.util.Locale; import java.util.Set; import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class BossBarHolder extends SendableHolder { - private final RawComponent name; + private final Component name; private final float progress; private final BossBar.Color color; @@ -27,7 +27,7 @@ public class BossBarHolder extends SendableHolder { private final boolean clearOtherBars; - public BossBarHolder(@NotNull RawComponent name, float progress, @NotNull BossBar.Color color, @NotNull BossBar.Overlay overlay, @NotNull Collection flags, int stay, boolean clearOtherBars) { + public BossBarHolder(@NotNull Component name, float progress, @NotNull BossBar.Color color, @NotNull BossBar.Overlay overlay, @NotNull Collection flags, int stay, boolean clearOtherBars) { this.name = name; this.progress = progress; this.color = color; @@ -37,7 +37,7 @@ public BossBarHolder(@NotNull RawComponent name, float progress, @NotNull BossBa this.stay = stay; } - public @NotNull RawComponent getName() { + public @NotNull Component getName() { return this.name; } @@ -81,7 +81,7 @@ public void send(@Nullable Locale locale, @NotNull Viewer viewer, @NotNull Repla @Override public @NotNull SendableHolder copy(@NotNull Replaceable... replacements) { return new BossBarHolder( - ComponentReplacer.replaceRaw(this.name, replacements), + ComponentReplacer.replace(this.name, replacements), this.progress, this.color, this.overlay, @@ -91,17 +91,17 @@ public void send(@Nullable Locale locale, @NotNull Viewer viewer, @NotNull Repla ); } - public static @NotNull Builder builder(@NotNull RawComponent name) { + public static @NotNull Builder builder(@NotNull Component name) { return new Builder(name); } public static @NotNull Builder builder(@NotNull String name) { - return new Builder(MiniComponent.of(name)); + return new Builder(GlobalAdventureSerializer.deserialize(name)); } public static class Builder { - private final RawComponent name; + private final Component name; private float progress = BossBar.MAX_PROGRESS; private BossBar.Color color = BossBar.Color.PINK; @@ -112,7 +112,7 @@ public static class Builder { private boolean clearOtherBars = false; - private Builder(@NotNull RawComponent name) { + private Builder(@NotNull Component name) { this.name = name; } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ChatHolder.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ChatHolder.java index cb813ef..5dbb6a7 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ChatHolder.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/ChatHolder.java @@ -1,7 +1,6 @@ package dev.peri.yetanothermessageslibrary.message.holder.impl; -import dev.peri.yetanothermessageslibrary.adventure.MiniComponent; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; import dev.peri.yetanothermessageslibrary.message.SendableMessage; import dev.peri.yetanothermessageslibrary.message.holder.SendableHolder; import dev.peri.yetanothermessageslibrary.replace.ComponentReplacer; @@ -20,14 +19,14 @@ public class ChatHolder extends SendableHolder { protected boolean onlyConsole; - private final List messages = new ArrayList<>(); + private final List messages = new ArrayList<>(); - public ChatHolder(boolean onlyConsole, @NotNull Collection messages) { + public ChatHolder(boolean onlyConsole, @NotNull Collection messages) { this.onlyConsole = onlyConsole; this.messages.addAll(messages); } - public ChatHolder(boolean onlyConsole, @NotNull RawComponent... messages) { + public ChatHolder(boolean onlyConsole, @NotNull Component... messages) { this(onlyConsole, Arrays.asList(messages)); } @@ -35,7 +34,7 @@ public boolean sendOnlyToConsole() { return this.onlyConsole; } - public @NotNull List getMessages() { + public @NotNull List getMessages() { return this.messages; } @@ -45,26 +44,25 @@ public void send(@Nullable Locale locale, @NotNull Viewer viewer, @NotNull Repla return; } - List finalMessage = this.messages.stream() + this.messages.stream() .map(message -> ComponentReplacer.replace(locale, message, replacements)) - .collect(Collectors.toList()); - viewer.sendChatMessage(finalMessage); + .forEachOrdered(viewer::sendChatMessage); } @Override public @NotNull SendableHolder copy(@NotNull Replaceable... replacements) { - List finalMessages = this.messages.stream() - .map(message -> ComponentReplacer.replaceRaw(message, replacements)) + List finalMessages = this.messages.stream() + .map(message -> ComponentReplacer.replace(message, replacements)) .collect(Collectors.toList()); return new ChatHolder(this.onlyConsole, finalMessages); } - public static @NotNull SendableMessage message(@NotNull RawComponent... messages) { + public static @NotNull SendableMessage message(@NotNull Component... messages) { return SendableMessage.of(new ChatHolder(false, messages)); } public static @NotNull SendableMessage message(@NotNull String... messages) { - return SendableMessage.of(new ChatHolder(false, MiniComponent.of(messages))); + return SendableMessage.of(new ChatHolder(false, GlobalAdventureSerializer.deserialize(messages))); } } diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/TitleHolder.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/TitleHolder.java index 5f84717..bf37bd1 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/TitleHolder.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/message/holder/impl/TitleHolder.java @@ -1,13 +1,13 @@ package dev.peri.yetanothermessageslibrary.message.holder.impl; -import dev.peri.yetanothermessageslibrary.adventure.MiniComponent; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; import dev.peri.yetanothermessageslibrary.message.SendableMessage; import dev.peri.yetanothermessageslibrary.message.holder.SendableHolder; import dev.peri.yetanothermessageslibrary.replace.ComponentReplacer; import dev.peri.yetanothermessageslibrary.replace.Replaceable; import dev.peri.yetanothermessageslibrary.viewer.Viewer; import java.util.Locale; +import net.kyori.adventure.text.Component; import net.kyori.adventure.title.Title; import net.kyori.adventure.title.Title.Times; import net.kyori.adventure.util.Ticks; @@ -17,21 +17,21 @@ public class TitleHolder extends SendableHolder { - private final RawComponent title; - private final RawComponent subTitle; + private final Component title; + private final Component subTitle; private final Times times; - public TitleHolder(@NotNull RawComponent title, @NotNull RawComponent subTitle, @NotNull Times times) { + public TitleHolder(@NotNull Component title, @NotNull Component subTitle, @NotNull Times times) { this.title = title; this.subTitle = subTitle; this.times = times; } - public @NotNull RawComponent getTitle() { + public @NotNull Component getTitle() { return this.title; } - public @NotNull RawComponent getSubTitle() { + public @NotNull Component getSubTitle() { return this.subTitle; } @@ -55,18 +55,18 @@ public void send(@Nullable Locale locale, @NotNull Viewer viewer, @NotNull Repla @Override public @NotNull SendableHolder copy(@NotNull Replaceable... replacements) { return new TitleHolder( - ComponentReplacer.replaceRaw(this.title, replacements), - ComponentReplacer.replaceRaw(this.subTitle, replacements), + ComponentReplacer.replace(this.title, replacements), + ComponentReplacer.replace(this.subTitle, replacements), this.times ); } - public static @NotNull SendableMessage message(@NotNull RawComponent title, @NotNull RawComponent subTitle, int fadeIn, int stay, int fadeOut) { + public static @NotNull SendableMessage message(@NotNull Component title, @NotNull Component subTitle, int fadeIn, int stay, int fadeOut) { return SendableMessage.of(new TitleHolder(title, subTitle, TitleHolder.times(fadeIn, stay, fadeOut))); } public static @NotNull SendableMessage message(@NotNull String title, @NotNull String subTitle, int fadeIn, int stay, int fadeOut) { - return TitleHolder.message(MiniComponent.of(title), MiniComponent.of(subTitle), fadeIn, stay, fadeOut); + return TitleHolder.message(GlobalAdventureSerializer.deserialize(title), GlobalAdventureSerializer.deserialize(subTitle), fadeIn, stay, fadeOut); } public static @NotNull Builder builder() { @@ -75,33 +75,33 @@ public void send(@Nullable Locale locale, @NotNull Viewer viewer, @NotNull Repla public static class Builder { - private RawComponent title = RawComponent.EMPTY; - private RawComponent subTitle = RawComponent.EMPTY; + private Component title = Component.empty(); + private Component subTitle = Component.empty(); private Times times = TitleHolder.times(10, 70, 20); private Builder() { } @Contract("_ -> this") - public Builder title(@NotNull RawComponent title) { + public Builder title(@NotNull Component title) { this.title = title; return this; } @Contract("_ -> this") public Builder title(@NotNull String title) { - return this.title(MiniComponent.of(title)); + return this.title(GlobalAdventureSerializer.deserialize(title)); } @Contract("_ -> this") - public Builder subTitle(@NotNull RawComponent subTitle) { + public Builder subTitle(@NotNull Component subTitle) { this.subTitle = subTitle; return this; } @Contract("_ -> this") public Builder subTitle(@NotNull String subTitle) { - return this.subTitle(MiniComponent.of(subTitle)); + return this.subTitle(GlobalAdventureSerializer.deserialize(subTitle)); } @Contract("_ -> this") diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/ComponentReplacer.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/ComponentReplacer.java deleted file mode 100644 index 199eb0a..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/ComponentReplacer.java +++ /dev/null @@ -1,53 +0,0 @@ -package dev.peri.yetanothermessageslibrary.replace; - -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; -import java.util.Locale; -import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public final class ComponentReplacer { - - private ComponentReplacer() { - } - - @Contract(pure = true, value = "_, null, _ -> null") - public static Component replace(@Nullable Locale locale, @Nullable Component text, @NotNull Replaceable... replacements) { - if (text == null) { - return null; - } - - for (Replaceable replacement : replacements) { - text = replacement.replace(text); - } - return text; - } - - @Contract(pure = true, value = "null, _ -> null") - public static Component replace(@Nullable Component text, @NotNull Replaceable... replacements) { - return replace(null, text, replacements); - } - - @Contract(pure = true) - public static @NotNull Component replace(@Nullable Locale locale, @NotNull RawComponent text, @NotNull Replaceable... replacements) { - return replace(locale, text.getComponent(), replacements); - } - - @Contract(pure = true) - public static @NotNull Component replace(@NotNull RawComponent text, @NotNull Replaceable... replacements) { - return replace(null, text, replacements); - } - - @Contract(pure = true) - public static @NotNull RawComponent replaceRaw(@NotNull RawComponent text, @NotNull Replaceable... replacements) { - String rawText = text.getRaw(); - Component rawComponent = text.getComponent(); - - return new RawComponent( - StringReplacer.replace(rawText, replacements), - ComponentReplacer.replace(rawComponent, replacements) - ); - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/Replacement.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/Replacement.java deleted file mode 100644 index 63199a4..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/Replacement.java +++ /dev/null @@ -1,58 +0,0 @@ -package dev.peri.yetanothermessageslibrary.replace.replacement; - -import dev.peri.yetanothermessageslibrary.adventure.AdventureHelper; -import dev.peri.yetanothermessageslibrary.replace.Replaceable; -import dev.peri.yetanothermessageslibrary.replace.StringReplacer; -import java.util.Locale; -import java.util.function.Supplier; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextReplacementConfig; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class Replacement implements Replaceable { - - private final String from; - - protected Replacement(@NotNull String from) { - this.from = from; - } - - public @NotNull String getFrom() { - return this.from; - } - - public abstract @NotNull String getTo(); - - @Contract(pure = true) - public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { - return text.replace(this.getFrom(), this.getTo()); - } - - @Contract(pure = true) - @Override - public @NotNull Component replace(@Nullable Locale locale, @NotNull Component text) { - return text.replaceText(TextReplacementConfig.builder() - .matchLiteral(this.getFrom()) - .replacement(AdventureHelper.legacyToComponent(this.getTo())) - .build()); - } - - public static @NotNull SimpleReplacement of(@NotNull String from, @Nullable Object to) { - return new SimpleReplacement(from, to); - } - - public static @NotNull SimpleReplacement of(@NotNull String from, @Nullable String to, @NotNull Replacement... replacements) { - return of(from, StringReplacer.replace(to, replacements)); - } - - public static @NotNull SupplierReplacement of(@NotNull String from, @NotNull Supplier<@Nullable Object> to) { - return new SupplierReplacement(from, to); - } - - public static @NotNull SupplierReplacement of(@NotNull String from, @NotNull Supplier<@Nullable Object> to, @NotNull Replacement... replacements) { - return new SupplierReplacement(from, to, replacements); - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleReplacement.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleReplacement.java deleted file mode 100644 index fc903da..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleReplacement.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.peri.yetanothermessageslibrary.replace.replacement; - -import java.util.Objects; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SimpleReplacement extends Replacement { - - private final String to; - - protected SimpleReplacement(@NotNull String from, @Nullable Object to) { - super(from); - this.to = Objects.toString(to); - } - - @Override - public @NotNull String getTo() { - return this.to; - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SupplierReplacement.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SupplierReplacement.java deleted file mode 100644 index 0008d6c..0000000 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SupplierReplacement.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.peri.yetanothermessageslibrary.replace.replacement; - -import dev.peri.yetanothermessageslibrary.replace.StringReplacer; -import java.util.Objects; -import java.util.function.Supplier; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SupplierReplacement extends Replacement { - - private final Supplier to; - private final Replacement[] replacements; - - protected SupplierReplacement(@NotNull String from, @NotNull Supplier<@Nullable Object> to, @NotNull Replacement[] replacements) { - super(from); - this.to = to; - this.replacements = replacements; - } - - protected SupplierReplacement(@NotNull String from, @NotNull Supplier<@Nullable Object> to) { - this(from, to, new Replacement[0]); - } - - @Override - public @NotNull String getTo() { - return StringReplacer.replace(Objects.toString(this.to.get()), this.replacements); - } - -} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/viewer/Viewer.java b/core/src/main/java/dev/peri/yetanothermessageslibrary/viewer/Viewer.java index 82869a9..f3e6161 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/viewer/Viewer.java +++ b/core/src/main/java/dev/peri/yetanothermessageslibrary/viewer/Viewer.java @@ -35,7 +35,11 @@ public boolean isConsole() { } public void sendChatMessage(@NotNull Collection messages) { - messages.forEach(this.audience::sendMessage); + messages.forEach(this::sendChatMessage); + } + + public void sendChatMessage(@NotNull Component message) { + this.audience.sendMessage(message); } public void sendActionBar(@NotNull Component message) { diff --git a/example/build.gradle b/example/build.gradle index a6138db..672f967 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -17,7 +17,7 @@ dependencies { compileOnly "org.spigotmc:spigot-api:1.19.2-R0.1-SNAPSHOT" // YetAnotherMessagesLibrary - def yamlVersion = "6.5.1" + def yamlVersion = "7.0.0-SNAPSHOT" implementation "dev.peri.yetanothermessageslibrary:core:${yamlVersion}" implementation "dev.peri.yetanothermessageslibrary:platform-bukkit:${yamlVersion}" implementation "dev.peri.yetanothermessageslibrary:repository-okaeri:${yamlVersion}" @@ -25,7 +25,6 @@ dependencies { // Adventure def adventureVersion = "4.14.0" implementation "net.kyori:adventure-api:${adventureVersion}" - implementation "net.kyori:adventure-text-serializer-legacy:${adventureVersion}" implementation "net.kyori:adventure-text-minimessage:${adventureVersion}" implementation "net.kyori:adventure-platform-bukkit:4.3.1" diff --git a/example/src/main/java/dev/peri/yetanothermessageslibrary/example/ExamplePlugin.java b/example/src/main/java/dev/peri/yetanothermessageslibrary/example/ExamplePlugin.java index decb3a5..a6bc810 100644 --- a/example/src/main/java/dev/peri/yetanothermessageslibrary/example/ExamplePlugin.java +++ b/example/src/main/java/dev/peri/yetanothermessageslibrary/example/ExamplePlugin.java @@ -2,7 +2,8 @@ import dev.peri.yetanothermessageslibrary.BukkitMessageService; import dev.peri.yetanothermessageslibrary.SendableMessageService; -import dev.peri.yetanothermessageslibrary.config.serdes.SerdesMessages; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; +import dev.peri.yetanothermessageslibrary.config.serdes.YAMLSerdes; import dev.peri.yetanothermessageslibrary.example.complex.ExampleMessageDispatcher; import dev.peri.yetanothermessageslibrary.example.complex.ExampleMessageService; import dev.peri.yetanothermessageslibrary.example.config.MessageConfiguration; @@ -15,11 +16,14 @@ import java.io.File; import java.util.Locale; import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; public class ExamplePlugin extends JavaPlugin { + private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); + private final File englishMessageFile = new File(this.getDataFolder(), "en.yml"); private final File polishMessageFile = new File(this.getDataFolder(), "pl.yml"); @@ -35,6 +39,9 @@ public class ExamplePlugin extends JavaPlugin { public void onEnable() { this.adventure = BukkitAudiences.create(this); + // Register global serializer (used for e.g. by string replacements) + GlobalAdventureSerializer.globalSerializer(MINI_MESSAGE); + // Simple way this.simpleMessageService = new BukkitMessageService<>(this, this.adventure); this.simpleMessageService.registerDefaultRepository(Locale.ENGLISH, prepareMessageConfiguration(this.englishMessageFile)); @@ -60,7 +67,7 @@ public void onDisable() { private static MessageConfiguration prepareMessageConfiguration(File file) { return ConfigManager.create(MessageConfiguration.class, it -> { it.withConfigurer(new YamlBukkitConfigurer()); - it.withSerdesPack(new SerdesMessages()); + it.withSerdesPack(new YAMLSerdes()); it.withBindFile(file); it.saveDefaults(); diff --git a/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/BukkitMessageService.java b/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/BukkitMessageService.java index 0321767..dde6dca 100644 --- a/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/BukkitMessageService.java +++ b/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/BukkitMessageService.java @@ -10,7 +10,8 @@ import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; -public class BukkitMessageService extends SimpleSendableMessageService> { +public class BukkitMessageService + extends SimpleSendableMessageService> { public BukkitMessageService(@NotNull ViewerService viewerService) { super( @@ -26,7 +27,7 @@ public BukkitMessageService(@NotNull JavaPlugin plugin, @NotNull BukkitAudiences )); } - public static BiConsumer wrapScheduler(JavaPlugin plugin) { + public static BiConsumer wrapScheduler(@NotNull JavaPlugin plugin) { return (runnable, delay) -> plugin.getServer().getScheduler().runTaskLater(plugin, runnable, delay); } diff --git a/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/message/BukkitMessageDispatcher.java b/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/message/BukkitMessageDispatcher.java index ad4a9c7..4c5ec41 100644 --- a/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/message/BukkitMessageDispatcher.java +++ b/platform/bukkit/src/main/java/dev/peri/yetanothermessageslibrary/message/BukkitMessageDispatcher.java @@ -9,7 +9,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class BukkitMessageDispatcher> extends MessageDispatcher { +@SuppressWarnings("unchecked") +public class BukkitMessageDispatcher> + extends SimpleMessageDispatcher { public BukkitMessageDispatcher( @NotNull ViewerService viewerService, @@ -20,28 +22,21 @@ public BukkitMessageDispatcher( } @Contract(" -> this") - public D broadcast() { - this.broadcastPlayers(); - this.console(); - return (D) this; - } - - @Contract(" -> this") - public D broadcastPlayers() { + public DISPATCHER allPlayers() { this.receivers(Bukkit.getOnlinePlayers()); - return (D) this; + return (DISPATCHER) this; } @Contract(" -> this") - public D console() { + public DISPATCHER console() { this.receiver(Bukkit.getConsoleSender()); - return (D) this; + return (DISPATCHER) this; } @Contract("_ -> this") - public D permission(@NotNull String permission) { + public DISPATCHER permission(@NotNull String permission) { this.predicate(sender -> sender.hasPermission(permission)); - return (D) this; + return (DISPATCHER) this; } } diff --git a/platform/bungee/src/main/java/dev/peri/yetanothermessageslibrary/message/BungeeMessageDispatcher.java b/platform/bungee/src/main/java/dev/peri/yetanothermessageslibrary/message/BungeeMessageDispatcher.java index 31636ce..8643567 100644 --- a/platform/bungee/src/main/java/dev/peri/yetanothermessageslibrary/message/BungeeMessageDispatcher.java +++ b/platform/bungee/src/main/java/dev/peri/yetanothermessageslibrary/message/BungeeMessageDispatcher.java @@ -9,7 +9,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class BungeeMessageDispatcher> extends MessageDispatcher { +@SuppressWarnings("unchecked") +public class BungeeMessageDispatcher> + extends SimpleMessageDispatcher { public BungeeMessageDispatcher( @NotNull ViewerService viewerService, @@ -20,28 +22,21 @@ public BungeeMessageDispatcher( } @Contract(" -> this") - public D broadcast() { - this.broadcastPlayers(); - this.console(); - return (D) this; - } - - @Contract(" -> this") - public D broadcastPlayers() { + public DISPATCHER allPlayers() { this.receivers(ProxyServer.getInstance().getPlayers()); - return (D) this; + return (DISPATCHER) this; } @Contract(" -> this") - public D console() { + public DISPATCHER console() { this.receiver(ProxyServer.getInstance().getConsole()); - return (D) this; + return (DISPATCHER) this; } @Contract("_ -> this") - public D permission(@NotNull String permission) { + public DISPATCHER permission(@NotNull String permission) { this.predicate(sender -> sender.hasPermission(permission)); - return (D) this; + return (DISPATCHER) this; } } diff --git a/platform/velocity/src/main/java/dev/peri/yetanothermessageslibrary/message/VelocityMessageDispatcher.java b/platform/velocity/src/main/java/dev/peri/yetanothermessageslibrary/message/VelocityMessageDispatcher.java index d227ee3..d519389 100644 --- a/platform/velocity/src/main/java/dev/peri/yetanothermessageslibrary/message/VelocityMessageDispatcher.java +++ b/platform/velocity/src/main/java/dev/peri/yetanothermessageslibrary/message/VelocityMessageDispatcher.java @@ -9,7 +9,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class VelocityMessageDispatcher> extends MessageDispatcher { +@SuppressWarnings("unchecked") +public class VelocityMessageDispatcher> + extends SimpleMessageDispatcher { public VelocityMessageDispatcher( @NotNull ViewerService viewerService, @@ -19,29 +21,56 @@ public VelocityMessageDispatcher( super(viewerService, localeSupplier, messageSupplier); } + /** + * @deprecated use {@link #all(ProxyServer)} instead + */ + @Deprecated + @Override + public DISPATCHER all() throws UnsupportedOperationException { + return super.all(); + } + + /** + * @deprecated use {@link #allPlayers(ProxyServer)} instead + */ + @Deprecated + @Override + public DISPATCHER allPlayers() throws UnsupportedOperationException { + return super.allPlayers(); + } + + /** + * @deprecated use {@link #console(ProxyServer)} instead + */ + @Deprecated + @Override + public DISPATCHER console() throws UnsupportedOperationException { + return super.console(); + } + @Contract("_ -> this") - public D broadcast(@NotNull ProxyServer proxy) { - this.broadcastPlayers(proxy); + public DISPATCHER all(@NotNull ProxyServer proxy) { + this.allPlayers(proxy); this.console(proxy); - return (D) this; + return (DISPATCHER) this; } @Contract("_ -> this") - public D broadcastPlayers(@NotNull ProxyServer proxy) { + public DISPATCHER allPlayers(@NotNull ProxyServer proxy) { proxy.getAllPlayers().forEach(this::receiver); - return (D) this; + return (DISPATCHER) this; } @Contract("_ -> this") - public D console(@NotNull ProxyServer proxy) { + public DISPATCHER console(@NotNull ProxyServer proxy) { this.receiver(proxy.getConsoleCommandSource()); - return (D) this; + return (DISPATCHER) this; } @Contract("_ -> this") - public D permission(@NotNull String permission) { + public DISPATCHER permission(@NotNull String permission) { this.predicate(sender -> sender.hasPermission(permission)); - return (D) this; + return (DISPATCHER) this; } } diff --git a/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersMessageDispatcher.java b/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersMessageDispatcher.java new file mode 100644 index 0000000..948efa3 --- /dev/null +++ b/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersMessageDispatcher.java @@ -0,0 +1,21 @@ +package dev.peri.yetanothermessageslibrary.replace; + +import dev.peri.yetanothermessageslibrary.message.MessageDispatcher; +import eu.okaeri.placeholders.Placeholders; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public interface OkaeriPlaceholdersMessageDispatcher> + extends MessageDispatcher { + + @Contract("_ -> this") + default DISPATCHER okaeriPlaceholders(@NotNull Placeholders placeholder) { + return this.with(null, (receiver, locale, fields) -> new OkaeriPlaceholdersReplaceable(placeholder, context -> { + context.with("receiver", receiver); + context.with("locale", locale); + context.with(fields); + return context; + })); + }; + +} diff --git a/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersReplaceable.java b/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersReplaceable.java index 4fe5b78..465d68d 100644 --- a/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersReplaceable.java +++ b/replaceable/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/replace/OkaeriPlaceholdersReplaceable.java @@ -1,41 +1,45 @@ package dev.peri.yetanothermessageslibrary.replace; -import dev.peri.yetanothermessageslibrary.adventure.AdventureHelper; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; +import dev.peri.yetanothermessageslibrary.replace.replacement.ComponentReplacement; import eu.okaeri.placeholders.Placeholders; import eu.okaeri.placeholders.context.PlaceholderContext; import eu.okaeri.placeholders.message.CompiledMessage; import java.util.Locale; import java.util.function.Function; import java.util.regex.Pattern; -import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class OkaeriPlaceholdersReplaceable implements Replaceable { +@ApiStatus.Experimental +public class OkaeriPlaceholdersReplaceable extends ComponentReplacement implements StringReplaceable { private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(?[^}]+)\\}"); private final Placeholders placeholders; private final Function applyContexts; - public OkaeriPlaceholdersReplaceable(@NotNull Placeholders placeholders, @NotNull Function applyContexts) { + public OkaeriPlaceholdersReplaceable( + @NotNull Placeholders placeholders, + @NotNull Function applyContexts + ) { + super(FIELD_PATTERN); this.placeholders = placeholders; this.applyContexts = applyContexts; } @Override - public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { - return this.replacePlaceholders(locale, text); + public @NotNull TextReplacementConfig getReplacement(@Nullable Locale locale) { + return this.newReplacementBuilder() + .replacement((result, input) -> GlobalAdventureSerializer.deserialize(this.replacePlaceholders(locale, result.group()))) + .build(); } @Override - public @NotNull Component replace(@Nullable Locale locale, @NotNull Component text) { - TextReplacementConfig replacement = TextReplacementConfig.builder() - .match(FIELD_PATTERN) - .replacement((result, input) -> AdventureHelper.legacyToComponent(this.replacePlaceholders(locale, "{" + result.group() + "}"))) - .build(); - return text.replaceText(replacement); + public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { + return this.replacePlaceholders(locale, text); } private String replacePlaceholders(@Nullable Locale locale, @NotNull String text) { diff --git a/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIMessageDispatcher.java b/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIMessageDispatcher.java new file mode 100644 index 0000000..8cd6f2c --- /dev/null +++ b/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIMessageDispatcher.java @@ -0,0 +1,16 @@ +package dev.peri.yetanothermessageslibrary.replace; + +import dev.peri.yetanothermessageslibrary.message.MessageDispatcher; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Contract; + +public interface PlaceholderAPIMessageDispatcher> + extends MessageDispatcher { + + @Contract(" -> this") + default DISPATCHER placeholderAPI() { + return this.with((Class) Player.class, player -> new PlaceholderAPIReplaceable((Player) player)); + } + +} diff --git a/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIReplaceable.java b/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIReplaceable.java index 57c969e..c575e05 100644 --- a/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIReplaceable.java +++ b/replaceable/placeholderapi/src/main/java/dev/peri/yetanothermessageslibrary/replace/PlaceholderAPIReplaceable.java @@ -1,38 +1,39 @@ package dev.peri.yetanothermessageslibrary.replace; -import dev.peri.yetanothermessageslibrary.adventure.AdventureHelper; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; +import dev.peri.yetanothermessageslibrary.replace.replacement.ComponentReplacement; import java.lang.ref.WeakReference; import java.util.Locale; import java.util.regex.Pattern; import me.clip.placeholderapi.PlaceholderAPI; -import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class PlaceholderAPIReplaceable implements Replaceable { +public class PlaceholderAPIReplaceable extends ComponentReplacement implements StringReplaceable { private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); private final WeakReference playerRef; + private final TextReplacementConfig replacement; public PlaceholderAPIReplaceable(@Nullable Player player) { + super(PLACEHOLDER_PATTERN); this.playerRef = new WeakReference<>(player); + this.replacement = this.newReplacementBuilder() + .replacement((result, input) -> GlobalAdventureSerializer.deserialize(this.replacePlaceholder(result.group()))) + .build(); } @Override - public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { - return this.replacePlaceholder(text); + public @NotNull TextReplacementConfig getReplacement(@Nullable Locale locale) { + return this.replacement; } @Override - public @NotNull Component replace(@Nullable Locale locale, @NotNull Component text) { - TextReplacementConfig replacement = TextReplacementConfig.builder() - .match(PLACEHOLDER_PATTERN) - .replacement((result, input) -> AdventureHelper.legacyToComponent(this.replacePlaceholder(result.group()))) - .build(); - return text.replaceText(replacement); + public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { + return this.replacePlaceholder(text); } private String replacePlaceholder(String text) { diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/ComponentSerializer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/ComponentSerializer.java new file mode 100644 index 0000000..8f812d4 --- /dev/null +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/ComponentSerializer.java @@ -0,0 +1,33 @@ +package dev.peri.yetanothermessageslibrary.config.serdes; + +import eu.okaeri.configs.schema.GenericsDeclaration; +import eu.okaeri.configs.serdes.DeserializationData; +import eu.okaeri.configs.serdes.ObjectSerializer; +import eu.okaeri.configs.serdes.SerializationData; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.NotNull; + +public class ComponentSerializer implements ObjectSerializer { + + private final net.kyori.adventure.text.serializer.ComponentSerializer componentSerializer; + + public ComponentSerializer(@NotNull net.kyori.adventure.text.serializer.ComponentSerializer componentSerializer) { + this.componentSerializer = componentSerializer; + } + + @Override + public boolean supports(Class type) { + return Component.class.isAssignableFrom(type); + } + + @Override + public void serialize(Component object, SerializationData data, GenericsDeclaration generics) { + data.setValue(this.componentSerializer.serialize(object), String.class); + } + + @Override + public Component deserialize(DeserializationData data, GenericsDeclaration generics) { + return this.componentSerializer.deserialize(data.getValue(String.class)); + } + +} diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/ComponentTransformer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/ComponentTransformer.java deleted file mode 100644 index 554c7d2..0000000 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/ComponentTransformer.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.peri.yetanothermessageslibrary.config.serdes; - -import dev.peri.yetanothermessageslibrary.adventure.AdventureHelper; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; -import eu.okaeri.configs.schema.GenericsPair; -import eu.okaeri.configs.serdes.BidirectionalTransformer; -import eu.okaeri.configs.serdes.SerdesContext; -import net.kyori.adventure.text.Component; - -public class ComponentTransformer extends BidirectionalTransformer { - - @Override - public GenericsPair getPair() { - return this.genericsPair(RawComponent.class, Component.class); - } - - @Override - public Component leftToRight(RawComponent data, SerdesContext serdesContext) { - return data.getComponent(); - } - - @Override - public RawComponent rightToLeft(Component data, SerdesContext serdesContext) { - return new RawComponent(AdventureHelper.componentToAmpersandString(data), data); - } - -} diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/RawComponentTransformer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/RawComponentTransformer.java deleted file mode 100644 index 4686d42..0000000 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/RawComponentTransformer.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.peri.yetanothermessageslibrary.config.serdes; - -import dev.peri.yetanothermessageslibrary.adventure.MiniComponent; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; -import eu.okaeri.configs.schema.GenericsPair; -import eu.okaeri.configs.serdes.BidirectionalTransformer; -import eu.okaeri.configs.serdes.SerdesContext; - -public class RawComponentTransformer extends BidirectionalTransformer { - - @Override - public GenericsPair getPair() { - return this.genericsPair(String.class, RawComponent.class); - } - - @Override - public RawComponent leftToRight(String data, SerdesContext serdesContext) { - return MiniComponent.of(data); - } - - @Override - public String rightToLeft(RawComponent data, SerdesContext serdesContext) { - return data.getRaw(); - } - -} diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/SerdesMessages.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/YAMLSerdes.java similarity index 54% rename from repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/SerdesMessages.java rename to repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/YAMLSerdes.java index 0522b1d..504e9ef 100644 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/SerdesMessages.java +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/YAMLSerdes.java @@ -1,28 +1,40 @@ package dev.peri.yetanothermessageslibrary.config.serdes; -import dev.peri.yetanothermessageslibrary.config.serdes.holder.ActionBarHolderTransformer; +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; +import dev.peri.yetanothermessageslibrary.config.serdes.holder.ActionBarHolderSerializer; import dev.peri.yetanothermessageslibrary.config.serdes.holder.BossBarHolderSerializer; import dev.peri.yetanothermessageslibrary.config.serdes.holder.ChatSerializer; import dev.peri.yetanothermessageslibrary.config.serdes.holder.SoundHolderSerializer; import dev.peri.yetanothermessageslibrary.config.serdes.holder.TitleHolderSerializer; import eu.okaeri.configs.serdes.OkaeriSerdesPack; import eu.okaeri.configs.serdes.SerdesRegistry; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.NotNull; -public class SerdesMessages implements OkaeriSerdesPack { +public class YAMLSerdes implements OkaeriSerdesPack { + + private final net.kyori.adventure.text.serializer.ComponentSerializer componentSerializer; + + public YAMLSerdes(@NotNull net.kyori.adventure.text.serializer.ComponentSerializer componentSerializer) { + this.componentSerializer = componentSerializer; + } + + public YAMLSerdes() { + this(GlobalAdventureSerializer.globalSerializer()); + } @Override public void register(SerdesRegistry registry) { // Messages registry.register(new ChatSerializer()); - registry.register(new ActionBarHolderTransformer()); + registry.register(new ActionBarHolderSerializer()); registry.register(new TitleHolderSerializer()); registry.register(new BossBarHolderSerializer()); registry.register(new SoundHolderSerializer()); registry.register(new SendableMessageSerializer()); // Utilities - registry.register(new RawComponentTransformer()); - registry.register(new ComponentTransformer()); + registry.register(new ComponentSerializer(this.componentSerializer)); registry.register(new KeyTransformer()); } diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ActionBarHolderSerializer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ActionBarHolderSerializer.java new file mode 100644 index 0000000..bd0d249 --- /dev/null +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ActionBarHolderSerializer.java @@ -0,0 +1,27 @@ +package dev.peri.yetanothermessageslibrary.config.serdes.holder; + +import dev.peri.yetanothermessageslibrary.message.holder.impl.ActionBarHolder; +import eu.okaeri.configs.schema.GenericsDeclaration; +import eu.okaeri.configs.serdes.DeserializationData; +import eu.okaeri.configs.serdes.ObjectSerializer; +import eu.okaeri.configs.serdes.SerializationData; +import net.kyori.adventure.text.Component; + +public class ActionBarHolderSerializer implements ObjectSerializer { + + @Override + public boolean supports(Class type) { + return ActionBarHolder.class.isAssignableFrom(type); + } + + @Override + public void serialize(ActionBarHolder actionBar, SerializationData data, GenericsDeclaration generics) { + data.setValue(actionBar.getMessage(), Component.class); + } + + @Override + public ActionBarHolder deserialize(DeserializationData data, GenericsDeclaration generics) { + return new ActionBarHolder(data.getValue(Component.class)); + } + +} diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ActionBarHolderTransformer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ActionBarHolderTransformer.java deleted file mode 100644 index 6c8c0ea..0000000 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ActionBarHolderTransformer.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.peri.yetanothermessageslibrary.config.serdes.holder; - -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; -import dev.peri.yetanothermessageslibrary.message.holder.impl.ActionBarHolder; -import eu.okaeri.configs.schema.GenericsPair; -import eu.okaeri.configs.serdes.BidirectionalTransformer; -import eu.okaeri.configs.serdes.SerdesContext; - -public class ActionBarHolderTransformer extends BidirectionalTransformer { - - @Override - public GenericsPair getPair() { - return this.genericsPair(RawComponent.class, ActionBarHolder.class); - } - - @Override - public ActionBarHolder leftToRight(RawComponent data, SerdesContext serdesContext) { - return new ActionBarHolder(data); - } - - @Override - public RawComponent rightToLeft(ActionBarHolder data, SerdesContext serdesContext) { - return data.getMessage(); - } - -} diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/BossBarHolderSerializer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/BossBarHolderSerializer.java index e67dbb1..6a90b63 100644 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/BossBarHolderSerializer.java +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/BossBarHolderSerializer.java @@ -1,6 +1,5 @@ package dev.peri.yetanothermessageslibrary.config.serdes.holder; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; import dev.peri.yetanothermessageslibrary.message.holder.impl.BossBarHolder; import eu.okaeri.configs.schema.GenericsDeclaration; import eu.okaeri.configs.serdes.DeserializationData; @@ -8,6 +7,7 @@ import eu.okaeri.configs.serdes.SerializationData; import java.util.HashSet; import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; public class BossBarHolderSerializer implements ObjectSerializer { @@ -18,30 +18,30 @@ public boolean supports(Class type) { @Override public void serialize(BossBarHolder holder, SerializationData data, GenericsDeclaration generics) { - data.add("name", holder.getName()); - data.add("color", holder.getColor()); - data.add("overlay", holder.getOverlay()); + data.add("name", holder.getName(), Component.class); + data.add("color", holder.getColor(), BossBar.Color.class); + data.add("overlay", holder.getOverlay(), BossBar.Overlay.class); if (!holder.getFlags().isEmpty()) { data.addCollection("flags", holder.getFlags(), BossBar.Flag.class); } if (holder.getProgress() >= 0) { - data.add("progress", holder.getProgress()); + data.add("progress", holder.getProgress(), float.class); } if (holder.getStay() >= 0) { - data.add("stay", holder.getStay()); + data.add("stay", holder.getStay(), int.class); } if (holder.clearOtherBars()) { - data.add("clear-other-bars", true); + data.add("clear-other-bars", true, boolean.class); } } @Override public BossBarHolder deserialize(DeserializationData data, GenericsDeclaration generics) { - return BossBarHolder.builder(data.get("name", RawComponent.class)) + return BossBarHolder.builder(data.get("name", Component.class)) .progress(data.containsKey("progress") ? data.get("progress", float.class) : 1) .color(data.containsKey("color") ? data.get("color", BossBar.Color.class) : BossBar.Color.PINK) .overlay(data.containsKey("overlay") ? data.get("overlay", BossBar.Overlay.class) : BossBar.Overlay.PROGRESS) diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ChatSerializer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ChatSerializer.java index a88a3ac..482d0a9 100644 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ChatSerializer.java +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/ChatSerializer.java @@ -1,6 +1,5 @@ package dev.peri.yetanothermessageslibrary.config.serdes.holder; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; import dev.peri.yetanothermessageslibrary.message.holder.impl.ChatHolder; import eu.okaeri.configs.schema.GenericsDeclaration; import eu.okaeri.configs.serdes.DeserializationData; @@ -8,6 +7,7 @@ import eu.okaeri.configs.serdes.SerializationData; import java.util.ArrayList; import java.util.List; +import net.kyori.adventure.text.Component; public class ChatSerializer implements ObjectSerializer { @@ -19,7 +19,7 @@ public boolean supports(Class type) { @Override public void serialize(ChatHolder holder, SerializationData data, GenericsDeclaration generics) { boolean sendOnlyToConsole = holder.sendOnlyToConsole(); - List messages = holder.getMessages(); + List messages = holder.getMessages(); if (!sendOnlyToConsole) { Object value = messages.size() == 1 ? messages.get(0) : messages; @@ -27,25 +27,25 @@ public void serialize(ChatHolder holder, SerializationData data, GenericsDeclara return; } - data.add("console", true); + data.add("console", true, boolean.class); if (messages.size() == 1) { - data.add("message", messages.get(0)); + data.add("message", messages.get(0), Component.class); } else { - data.addCollection("message", messages, RawComponent.class); + data.addCollection("message", messages, Component.class); } } @Override public ChatHolder deserialize(DeserializationData data, GenericsDeclaration generics) { boolean onlyConsole = false; - List messages = new ArrayList<>(); + List messages = new ArrayList<>(); if (data.isValue()) { Object raw = data.getValueRaw(); if (raw instanceof String) { - messages.add(data.getValue(RawComponent.class)); + messages.add(data.getValue(Component.class)); } else if (raw instanceof List) { - messages.addAll(data.getValueAsList(RawComponent.class)); + messages.addAll(data.getValueAsList(Component.class)); } } else { onlyConsole = data.containsKey("console") @@ -54,9 +54,9 @@ public ChatHolder deserialize(DeserializationData data, GenericsDeclaration gene Object raw = data.getRaw("message"); if (raw instanceof String) { - messages.add(data.get("message", RawComponent.class)); + messages.add(data.get("message", Component.class)); } else if (raw instanceof List) { - messages.addAll(data.getAsList("message", RawComponent.class)); + messages.addAll(data.getAsList("message", Component.class)); } } diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/SoundHolderSerializer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/SoundHolderSerializer.java index 286aa75..0f1dacb 100644 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/SoundHolderSerializer.java +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/SoundHolderSerializer.java @@ -18,12 +18,12 @@ public boolean supports(Class type) { @Override public void serialize(SoundHolder holder, SerializationData data, GenericsDeclaration generics) { Sound sound = holder.getSound(); - data.add("name", sound.name().asString()); - data.add("source", sound.source()); - data.add("volume", sound.volume()); - data.add("pitch", sound.pitch()); + data.add("name", sound.name().asString(), String.class); + data.add("source", sound.source(), Sound.Source.class); + data.add("volume", sound.volume(), float.class); + data.add("pitch", sound.pitch(), float.class); if (holder.stopOtherSounds()) { - data.add("stop-other-sounds", true); + data.add("stop-other-sounds", true, boolean.class); } } diff --git a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/TitleHolderSerializer.java b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/TitleHolderSerializer.java index ac479f9..37a0391 100644 --- a/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/TitleHolderSerializer.java +++ b/repository/okaeri/src/main/java/dev/peri/yetanothermessageslibrary/config/serdes/holder/TitleHolderSerializer.java @@ -1,12 +1,12 @@ package dev.peri.yetanothermessageslibrary.config.serdes.holder; -import dev.peri.yetanothermessageslibrary.adventure.RawComponent; import dev.peri.yetanothermessageslibrary.message.holder.impl.TitleHolder; import eu.okaeri.configs.schema.GenericsDeclaration; import eu.okaeri.configs.serdes.DeserializationData; import eu.okaeri.configs.serdes.ObjectSerializer; import eu.okaeri.configs.serdes.SerializationData; import java.time.Duration; +import net.kyori.adventure.text.Component; import net.kyori.adventure.title.Title.Times; import net.kyori.adventure.util.Ticks; @@ -19,11 +19,14 @@ public boolean supports(Class type) { @Override public void serialize(TitleHolder holder, SerializationData data, GenericsDeclaration generics) { - if (!holder.getTitle().getRaw().isEmpty()) { - data.add("title", holder.getTitle().getRaw()); + Component title = holder.getTitle(); + if (!title.equals(Component.empty())) { + data.add("title", title, Component.class); } - if (!holder.getSubTitle().getRaw().isEmpty()) { - data.add("subtitle", holder.getSubTitle().getRaw()); + + Component subtitle = holder.getSubTitle(); + if (!subtitle.equals(Component.empty())) { + data.add("subtitle", subtitle, Component.class); } Times times = holder.getTimes(); @@ -32,15 +35,15 @@ public void serialize(TitleHolder holder, SerializationData data, GenericsDeclar int fadeOut = ticksFromDuration(times.fadeOut()); if (fadeIn > 0) { - data.add("fade-in", fadeIn); + data.add("fade-in", fadeIn, int.class); } if (stay > 0) { - data.add("stay", stay); + data.add("stay", stay, int.class); } if (fadeOut > 0) { - data.add("fade-out", fadeOut); + data.add("fade-out", fadeOut, int.class); } } @@ -49,11 +52,11 @@ public TitleHolder deserialize(DeserializationData data, GenericsDeclaration gen TitleHolder.Builder builder = TitleHolder.builder(); if (data.containsKey("title")) { - builder.title(data.get("title", RawComponent.class)); + builder.title(data.get("title", Component.class)); } if (data.containsKey("subtitle")) { - builder.subTitle(data.get("subtitle", RawComponent.class)); + builder.subTitle(data.get("subtitle", Component.class)); } int fadeIn = 0; diff --git a/settings.gradle b/settings.gradle index a07449a..76aaac7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,6 @@ rootProject.name = 'YetAnotherMessagesLibrary' +this.setupSubproject("tools") this.setupSubproject("core") // Platforms @@ -37,10 +38,10 @@ dependencyResolutionManagement { library("velocity", "com.velocitypowered:velocity-api:3.1.1") } adventure { - String apiVersion = "4.14.0" + String apiVersion = "4.16.0" library("api", "net.kyori:adventure-api:${apiVersion}") - library("minimessage", "net.kyori:adventure-text-minimessage:${apiVersion}") library("serializer-legacy", "net.kyori:adventure-text-serializer-legacy:${apiVersion}") + library("serializer-minimessage", "net.kyori:adventure-text-minimessage:${apiVersion}") String platformVersion = "4.3.1" library("platform-bukkit", "net.kyori:adventure-platform-bukkit:${platformVersion}") diff --git a/tools/build.gradle b/tools/build.gradle new file mode 100644 index 0000000..f0bf4f3 --- /dev/null +++ b/tools/build.gradle @@ -0,0 +1,5 @@ +dependencies { + compileOnlyApi adventure.api + compileOnlyApi adventure.serializer.legacy + compileOnlyApi adventure.serializer.minimessage +} \ No newline at end of file diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/GlobalAdventureSerializer.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/GlobalAdventureSerializer.java new file mode 100644 index 0000000..ced393d --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/GlobalAdventureSerializer.java @@ -0,0 +1,91 @@ +package dev.peri.yetanothermessageslibrary.adventure; + +import dev.peri.yetanothermessageslibrary.replace.replacement.FunctionStringReplacement; +import dev.peri.yetanothermessageslibrary.replace.replacement.SimpleStringReplacement; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.ComponentSerializer; +import org.jetbrains.annotations.NotNull; + +/** + * Simple utility class to provide global access to adventure serializer. + *

    + * This class is used mostly by string replacements ({@link SimpleStringReplacement}, {@link FunctionStringReplacement}) + * and some of {@link dev.peri.yetanothermessageslibrary.message.holder.SendableHolder} implementations. + */ +public final class GlobalAdventureSerializer { + + private static ComponentSerializer GLOBAL_SERIALIZER = new ComponentSerializer() { + @Override + public @NotNull Component deserialize(@NotNull String input) { + return Component.text(input); + } + + @Override + public @NotNull String serialize(@NotNull Component component) { + throw new UnsupportedOperationException("Register global serializer to serialize components"); + } + }; + + private GlobalAdventureSerializer() { + } + + static { + boolean isNativeLegacySerializer = false; + boolean isNativeMiniMessageSerializer = false; + + try { + Class.forName("net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer"); + isNativeLegacySerializer = true; + } catch (ClassNotFoundException ignored) { + } + + try { + Class.forName("net.kyori.adventure.text.serializer.minimessage.MiniMessage"); + isNativeMiniMessageSerializer = true; + } catch (ClassNotFoundException ignored) { + } + + if (isNativeLegacySerializer) { + NativeLegacySerializer.init(); + } else if (isNativeMiniMessageSerializer) { + NativeMiniMessageSerializer.init(); + } + } + + public static @NotNull ComponentSerializer globalSerializer() { + return GLOBAL_SERIALIZER; + } + + public static void globalSerializer(@NotNull ComponentSerializer globalSerializer) { + GLOBAL_SERIALIZER = Objects.requireNonNull(globalSerializer, "globalSerializer cannot be null"); + } + + public static @NotNull Component deserialize(@NotNull String input) { + return GLOBAL_SERIALIZER.deserialize(input); + } + + public static @NotNull List deserialize(@NotNull List input) { + return input.stream().map(GlobalAdventureSerializer::deserialize).collect(Collectors.toList()); + } + + public static @NotNull List deserialize(@NotNull String... input) { + return deserialize(Arrays.asList(input)); + } + + public static @NotNull Component[] deserializeArray(@NotNull List input) { + return deserialize(input).toArray(new Component[0]); + } + + public static @NotNull Component[] deserializeArray(@NotNull String... input) { + return deserialize(input).toArray(new Component[0]); + } + + public static @NotNull String serialize(@NotNull Component component) { + return GLOBAL_SERIALIZER.serialize(component); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/NativeLegacySerializer.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/NativeLegacySerializer.java new file mode 100644 index 0000000..970cfa9 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/NativeLegacySerializer.java @@ -0,0 +1,14 @@ +package dev.peri.yetanothermessageslibrary.adventure; + +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +final class NativeLegacySerializer { + + private NativeLegacySerializer() { + } + + static void init() { + GlobalAdventureSerializer.globalSerializer(LegacyComponentSerializer.legacySection()); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/NativeMiniMessageSerializer.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/NativeMiniMessageSerializer.java new file mode 100644 index 0000000..71597e8 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/adventure/NativeMiniMessageSerializer.java @@ -0,0 +1,14 @@ +package dev.peri.yetanothermessageslibrary.adventure; + +import net.kyori.adventure.text.minimessage.MiniMessage; + +final class NativeMiniMessageSerializer { + + private NativeMiniMessageSerializer() { + } + + static void init() { + GlobalAdventureSerializer.globalSerializer(MiniMessage.miniMessage()); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/ComponentReplacer.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/ComponentReplacer.java new file mode 100644 index 0000000..588a365 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/ComponentReplacer.java @@ -0,0 +1,69 @@ +package dev.peri.yetanothermessageslibrary.replace; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class ComponentReplacer { + + private ComponentReplacer() { + } + + @Contract(pure = true, value = "_, null, _ -> null") + public static Component replace(@Nullable Locale locale, @Nullable Component text, @NotNull Iterable replacements) { + if (text == null) { + return null; + } + + for (Replaceable replacement : replacements) { + text = replacement.replace(locale, text); + } + return text; + } + + @Contract(pure = true, value = "null, _, -> null") + public static Component replace(@Nullable Component text, @NotNull Iterable replacements) { + return replace(null, text, replacements); + } + + @Contract(pure = true, value = "_, null, _ -> null") + public static Component replace(@Nullable Locale locale, @Nullable Component text, @NotNull Replaceable... replacements) { + return replace(locale, text, Arrays.asList(replacements)); + } + + @Contract(pure = true, value = "null, _, -> null") + public static Component replace(@Nullable Component text, @NotNull Replaceable... replacements) { + return replace(null, text, replacements); + } + + @Contract(pure = true) + public static @NotNull List replace(@Nullable Locale locale, @NotNull Iterable text, @NotNull Iterable replacements) { + List result = new ArrayList<>(); + for (Component line : text) { + result.add(replace(locale, line, replacements)); + } + return result; + } + + @Contract(pure = true) + public static @NotNull List replace(@NotNull Iterable text, @NotNull Collection replacements) { + return replace(null, text, replacements); + } + + @Contract(pure = true) + public static @NotNull List replace(@Nullable Locale locale, @NotNull Iterable text, @NotNull Replaceable... replacements) { + return replace(locale, text, Arrays.asList(replacements)); + } + + @Contract(pure = true) + public static @NotNull List replace(@NotNull Iterable text, @NotNull Replaceable... replacements) { + return replace(null, text, replacements); + } + +} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/Replaceable.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/Replaceable.java similarity index 70% rename from core/src/main/java/dev/peri/yetanothermessageslibrary/replace/Replaceable.java rename to tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/Replaceable.java index d7cc572..40f562d 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/Replaceable.java +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/Replaceable.java @@ -7,12 +7,6 @@ public interface Replaceable { - @NotNull String replace(@Nullable Locale locale, @NotNull String text); - - default @NotNull String replace(@NotNull String text) { - return this.replace(null, text); - } - @NotNull Component replace(@Nullable Locale locale, @NotNull Component text); default @NotNull Component replace(@NotNull Component text) { diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplaceable.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplaceable.java new file mode 100644 index 0000000..ae0da7c --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplaceable.java @@ -0,0 +1,15 @@ +package dev.peri.yetanothermessageslibrary.replace; + +import java.util.Locale; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface StringReplaceable extends Replaceable { + + @NotNull String replace(@Nullable Locale locale, @NotNull String text); + + default @NotNull String replace(@NotNull String text) { + return this.replace(null, text); + } + +} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplacer.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplacer.java similarity index 60% rename from core/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplacer.java rename to tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplacer.java index d8cbe02..b37bfd2 100644 --- a/core/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplacer.java +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/StringReplacer.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.Locale; import org.jetbrains.annotations.Contract; @@ -15,35 +14,34 @@ private StringReplacer() { } @Contract(pure = true, value = "_, null, _, -> null") - public static String replace(@Nullable Locale locale, @Nullable String text, @NotNull Collection replacements) { + public static String replace(@Nullable Locale locale, @Nullable String text, @NotNull Iterable replacements) { if (text == null || text.isEmpty()) { return text; } - for (Replaceable replacement : replacements) { + for (StringReplaceable replacement : replacements) { text = replacement.replace(locale, text); } - return text; } @Contract(pure = true, value = "null, _, -> null") - public static String replace(@Nullable String text, @NotNull Collection replacements) { + public static String replace(@Nullable String text, @NotNull Iterable replacements) { return replace(null, text, replacements); } @Contract(pure = true, value = "_, null, _, -> null") - public static String replace(@Nullable Locale locale, @Nullable String text, @NotNull Replaceable... replacements) { + public static String replace(@Nullable Locale locale, @Nullable String text, @NotNull StringReplaceable... replacements) { return replace(locale, text, Arrays.asList(replacements)); } @Contract(pure = true, value = "null, _, -> null") - public static String replace(@Nullable String text, @NotNull Replaceable... replacements) { + public static String replace(@Nullable String text, @NotNull StringReplaceable... replacements) { return replace(null, text, replacements); } @Contract(pure = true) - public static @NotNull List replace(@Nullable Locale locale, @NotNull List text, @NotNull Replaceable... replacements) { + public static @NotNull List replace(@Nullable Locale locale, @NotNull Iterable text, @NotNull Iterable replacements) { List result = new ArrayList<>(); for (String line : text) { result.add(replace(locale, line, replacements)); @@ -52,8 +50,18 @@ public static String replace(@Nullable String text, @NotNull Replaceable... repl } @Contract(pure = true) - public static @NotNull List replace(@NotNull List text, @NotNull Replaceable... replacements) { + public static @NotNull List replace(@NotNull Iterable text, @NotNull Iterable replacements) { return replace(null, text, replacements); } + @Contract(pure = true) + public static @NotNull List replace(@NotNull Iterable text, @NotNull StringReplaceable... replacements) { + return replace(null, text, Arrays.asList(replacements)); + } + + @Contract(pure = true) + public static @NotNull List replace(@Nullable Locale locale, @NotNull Iterable text, @NotNull StringReplaceable... replacements) { + return replace(locale, text, Arrays.asList(replacements)); + } + } diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/ComponentReplacement.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/ComponentReplacement.java new file mode 100644 index 0000000..6dbf489 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/ComponentReplacement.java @@ -0,0 +1,22 @@ +package dev.peri.yetanothermessageslibrary.replace.replacement; + +import java.util.Locale; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextReplacementConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class ComponentReplacement extends Replacement { + + protected ComponentReplacement(@NotNull Object placeholder) { + super(placeholder); + } + + public abstract @NotNull TextReplacementConfig getReplacement(@Nullable Locale locale); + + @Override + public @NotNull Component replace(@Nullable Locale locale, @NotNull Component text) { + return text.replaceText(this.getReplacement(locale)); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/FunctionReplacement.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/FunctionReplacement.java new file mode 100644 index 0000000..b23a812 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/FunctionReplacement.java @@ -0,0 +1,31 @@ +package dev.peri.yetanothermessageslibrary.replace.replacement; + +import java.util.Locale; +import java.util.function.Function; +import java.util.function.Supplier; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.TextReplacementConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class FunctionReplacement extends ComponentReplacement { + + private final Function<@Nullable Locale, ? extends @NotNull ComponentLike> replacementFunction; + + protected FunctionReplacement(@NotNull Object placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull ComponentLike> replacementFunction) { + super(placeholder); + this.replacementFunction = replacementFunction; + } + + protected FunctionReplacement(@NotNull Object placeholder, @NotNull Supplier replacementSupplier) { + this(placeholder, locale -> replacementSupplier.get()); + } + + @Override + public @NotNull TextReplacementConfig getReplacement(@Nullable Locale locale) { + return this.newReplacementBuilder() + .replacement(this.replacementFunction.apply(locale)) + .build(); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/FunctionStringReplacement.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/FunctionStringReplacement.java new file mode 100644 index 0000000..a0f52b0 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/FunctionStringReplacement.java @@ -0,0 +1,30 @@ +package dev.peri.yetanothermessageslibrary.replace.replacement; + +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; +import dev.peri.yetanothermessageslibrary.replace.StringReplaceable; +import java.util.Locale; +import java.util.function.Function; +import java.util.function.Supplier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class FunctionStringReplacement extends FunctionReplacement implements StringReplaceable { + + private final Function<@Nullable Locale, ? extends @NotNull String> replacementFunction; + + protected FunctionStringReplacement(@NotNull Object placeholder, @NotNull Function<@Nullable Locale, @NotNull String> replacementFunction) { + super(placeholder, locale -> GlobalAdventureSerializer.deserialize(replacementFunction.apply(locale))); + this.replacementFunction = replacementFunction; + } + + protected FunctionStringReplacement(@NotNull Object placeholder, @NotNull Supplier<@NotNull String> replacementSupplier) { + super(placeholder, locale -> GlobalAdventureSerializer.deserialize(replacementSupplier.get())); + this.replacementFunction = locale -> replacementSupplier.get(); + } + + @Override + public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { + return this.getPlaceholderType().replace(text, this.getPlaceholder(), this.replacementFunction.apply(locale)); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/Replacement.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/Replacement.java new file mode 100644 index 0000000..2b86808 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/Replacement.java @@ -0,0 +1,155 @@ +package dev.peri.yetanothermessageslibrary.replace.replacement; + +import dev.peri.yetanothermessageslibrary.replace.Replaceable; +import dev.peri.yetanothermessageslibrary.util.TriFunction; +import dev.peri.yetanothermessageslibrary.util.Validate; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.TextReplacementConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class Replacement implements Replaceable { + + private final PlaceholderType placeholderType; + private final Object placeholder; + + protected Replacement(@NotNull Object placeholder) { + PlaceholderType placeholderType = PlaceholderType.findType(placeholder.getClass()); + Validate.isTrue(placeholderType != null, "placeholder must be a String or Pattern"); + this.placeholderType = placeholderType; + this.placeholder = placeholder; + } + + /** + * @return the type of placeholder (String or Pattern) + */ + protected final @NotNull Replacement.PlaceholderType getPlaceholderType() { + return this.placeholderType; + } + + /** + * @return a new TextReplacementConfig.Builder that matches the placeholder + */ + protected final @NotNull TextReplacementConfig.Builder newReplacementBuilder() { + return this.placeholderType.newReplacementBuilder(this.placeholder); + } + + /** + * @return the placeholder object to match (String or Pattern) + */ + protected final @NotNull Object getPlaceholder() { + return this.placeholder; + } + + protected enum PlaceholderType { + + STRING( + String.class, + (text, placeholder, replacement) -> text.replace((String) placeholder, replacement), + replacement -> TextReplacementConfig.builder().matchLiteral((String) replacement) + ), + REGEX( + Pattern.class, + (text, placeholder, replacement) -> ((Pattern) placeholder).matcher(text).replaceAll(replacement), + replacement -> TextReplacementConfig.builder().match((Pattern) replacement) + ); + + private static final Map, PlaceholderType> PLACEHOLDERS_MAP; + + static { + Map, PlaceholderType> map = new HashMap<>(); + for (PlaceholderType placeholderType : PlaceholderType.values()) { + map.put(placeholderType.getClazz(), placeholderType); + } + PLACEHOLDERS_MAP = Collections.unmodifiableMap(map); + } + + private final Class clazz; + private final TriFunction replacer; + private final Function replacementBuilderFactory; + + PlaceholderType( + @NotNull Class clazz, + @NotNull TriFunction<@NotNull String, @NotNull Object, @NotNull String, @NotNull String> replacer, + @NotNull Function<@NotNull Object, TextReplacementConfig.Builder> replacementBuilderFactory + ) { + this.clazz = clazz; + this.replacer = replacer; + this.replacementBuilderFactory = replacementBuilderFactory; + } + + private @NotNull Class getClazz() { + return this.clazz; + } + + public @NotNull String replace(@NotNull String text, @NotNull Object placeholder, @NotNull String replacement) { + return this.replacer.apply(text, placeholder, replacement); + } + + public @NotNull TextReplacementConfig.Builder newReplacementBuilder(@NotNull Object placeholder) { + return this.replacementBuilderFactory.apply(placeholder); + } + + public static @Nullable Replacement.PlaceholderType findType(@NotNull Class clazz) { + return PLACEHOLDERS_MAP.get(clazz); + } + + } + + public static @NotNull SimpleStringReplacement string(@NotNull String placeholder, @NotNull Object replacement) { + return new SimpleStringReplacement(placeholder, Objects.toString(replacement)); + } + + public static @NotNull SimpleStringReplacement string(@NotNull Pattern placeholder, @NotNull Object replacement) { + return new SimpleStringReplacement(placeholder, Objects.toString(replacement)); + } + + public static @NotNull FunctionStringReplacement string(@NotNull String placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull Object> replacementFunction) { + return new FunctionStringReplacement(placeholder, locale -> Objects.toString(replacementFunction.apply(locale))); + } + + public static @NotNull FunctionStringReplacement string(@NotNull Pattern placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull Object> replacementFunction) { + return new FunctionStringReplacement(placeholder, locale -> Objects.toString(replacementFunction.apply(locale))); + } + + public static @NotNull FunctionStringReplacement string(@NotNull String placeholder, @NotNull Supplier replacementSupplier) { + return new FunctionStringReplacement(placeholder, locale -> Objects.toString(replacementSupplier.get())); + } + + public static @NotNull FunctionStringReplacement string(@NotNull Pattern placeholder, @NotNull Supplier replacementSupplier) { + return new FunctionStringReplacement(placeholder, locale -> Objects.toString(replacementSupplier.get())); + } + + public static @NotNull SimpleReplacement component(@NotNull String placeholder, @NotNull ComponentLike replacement) { + return new SimpleReplacement(placeholder, replacement); + } + + public static @NotNull SimpleReplacement component(@NotNull Pattern placeholder, @NotNull ComponentLike replacement) { + return new SimpleReplacement(placeholder, replacement); + } + + public static @NotNull FunctionReplacement component(@NotNull String placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull ComponentLike> replacementFunction) { + return new FunctionReplacement(placeholder, replacementFunction); + } + + public static @NotNull FunctionReplacement component(@NotNull Pattern placeholder, @NotNull Function<@Nullable Locale, ? extends @NotNull ComponentLike> replacementFunction) { + return new FunctionReplacement(placeholder, replacementFunction); + } + + public static @NotNull FunctionReplacement component(@NotNull String placeholder, @NotNull Supplier replacementSupplier) { + return new FunctionReplacement(placeholder, replacementSupplier); + } + + public static @NotNull FunctionReplacement component(@NotNull Pattern placeholder, @NotNull Supplier replacementSupplier) { + return new FunctionReplacement(placeholder, replacementSupplier); + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleReplacement.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleReplacement.java new file mode 100644 index 0000000..6c67ee0 --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleReplacement.java @@ -0,0 +1,25 @@ +package dev.peri.yetanothermessageslibrary.replace.replacement; + +import java.util.Locale; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.TextReplacementConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SimpleReplacement extends ComponentReplacement { + + private final TextReplacementConfig replacement; + + protected SimpleReplacement(@NotNull Object placeholder, @NotNull ComponentLike replacement) { + super(placeholder); + this.replacement = this.newReplacementBuilder() + .replacement(replacement) + .build(); + } + + @Override + public @NotNull TextReplacementConfig getReplacement(@Nullable Locale locale) { + return this.replacement; + } + +} diff --git a/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleStringReplacement.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleStringReplacement.java new file mode 100644 index 0000000..beed8dd --- /dev/null +++ b/tools/src/main/java/dev/peri/yetanothermessageslibrary/replace/replacement/SimpleStringReplacement.java @@ -0,0 +1,23 @@ +package dev.peri.yetanothermessageslibrary.replace.replacement; + +import dev.peri.yetanothermessageslibrary.adventure.GlobalAdventureSerializer; +import dev.peri.yetanothermessageslibrary.replace.StringReplaceable; +import java.util.Locale; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SimpleStringReplacement extends SimpleReplacement implements StringReplaceable { + + private final String replacement; + + protected SimpleStringReplacement(@NotNull Object placeholder, @NotNull String replacement) { + super(placeholder, GlobalAdventureSerializer.deserialize(replacement)); + this.replacement = replacement; + } + + @Override + public @NotNull String replace(@Nullable Locale locale, @NotNull String text) { + return this.getPlaceholderType().replace(text, this.getPlaceholder(), this.replacement); + } + +} diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/util/TriFunction.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/util/TriFunction.java similarity index 100% rename from core/src/main/java/dev/peri/yetanothermessageslibrary/util/TriFunction.java rename to tools/src/main/java/dev/peri/yetanothermessageslibrary/util/TriFunction.java diff --git a/core/src/main/java/dev/peri/yetanothermessageslibrary/util/Validate.java b/tools/src/main/java/dev/peri/yetanothermessageslibrary/util/Validate.java similarity index 100% rename from core/src/main/java/dev/peri/yetanothermessageslibrary/util/Validate.java rename to tools/src/main/java/dev/peri/yetanothermessageslibrary/util/Validate.java