-
Notifications
You must be signed in to change notification settings - Fork 24
Native Support for Adventure Library #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
zvyap
wants to merge
20
commits into
Exlll:dev
Choose a base branch
from
zvyap:master
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
a16c29a
Implemented adventure library support as additional module
zvyap 5943851
Optimize imports
zvyap 857be59
Make paper & velocity module depend on adventure on compile
zvyap dbb4807
Fix comment formatted by IDE
zvyap 0b47e1e
Fix tests failed due to windows os
zvyap 9683ceb
Added javadocs
zvyap 4081dcf
Updated readme
zvyap 50a1adf
Fix PR requested changes
zvyap e6dd5bd
Change MiniMessage detection pattern to more strict
zvyap 1f81d39
Make sound source generate dynamically
zvyap 2e6490a
Format code to 80 chars per line
zvyap 60883de
Prefix all top level file
zvyap c5ff729
Make sound serializer regex respect DELIMINATOR
zvyap ddf147e
Update README.md for miss type
zvyap 5347252
Update JavaDocs for grammer error by AI
zvyap 6add010
Fix readme class name
zvyap 35c6c5f
Merge branch 'master' of https://github.com/zvyap/ConfigLib
zvyap 0350ec4
Fix issue mention by copilot
zvyap e016dad
Add test and fix TranslatableComponent round trip issue
zvyap 2aeee87
Fix requested change
zvyap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| plugins { | ||
| `core-config` | ||
| `libs-config` | ||
| } | ||
|
|
||
| val adventureVersion = "4.26.1" | ||
|
|
||
| dependencies { | ||
| api(project(":configlib-core")) | ||
| compileOnly("net.kyori:adventure-api:$adventureVersion") | ||
| compileOnly("net.kyori:adventure-text-minimessage:$adventureVersion") | ||
| compileOnly("net.kyori:adventure-text-serializer-legacy:$adventureVersion") | ||
| compileOnly("net.kyori:adventure-text-serializer-gson:$adventureVersion") | ||
| compileOnly("net.kyori:adventure-text-serializer-plain:${adventureVersion}") | ||
|
|
||
| testImplementation(project(":configlib-yaml")) | ||
| testImplementation("net.kyori:adventure-api:$adventureVersion") | ||
| testImplementation("net.kyori:adventure-text-minimessage:$adventureVersion") | ||
| testImplementation("net.kyori:adventure-text-serializer-legacy:$adventureVersion") | ||
| testImplementation("net.kyori:adventure-text-serializer-gson:$adventureVersion") | ||
| testImplementation("net.kyori:adventure-text-serializer-plain:${adventureVersion}") | ||
| } | ||
64 changes: 64 additions & 0 deletions
64
configlib-adventure/src/main/java/de/exlll/configlib/AdventureComponentFormat.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| package de.exlll.configlib; | ||
|
|
||
| import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; | ||
|
|
||
| import java.util.function.Predicate; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| /** | ||
| * Represents the different text formats supported for Adventure Component | ||
| * serialization. | ||
| */ | ||
| public enum AdventureComponentFormat { | ||
| /** | ||
| * MiniMessage format with tags like {@code <red>} or {@code <bold>}. | ||
| */ | ||
| MINI_MESSAGE(Patterns.MINI_MESSAGE_PATTERN.asPredicate()), | ||
| /** | ||
| * Translation key format for translatable components. | ||
| */ | ||
| TRANSLATION_KEY(input -> true), // translation keys can be any format | ||
| /** | ||
zvyap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * Legacy format using ampersand ({@code &}) as the color code prefix. | ||
| */ | ||
| LEGACY_AMPERSAND(input -> | ||
| input.indexOf(LegacyComponentSerializer.AMPERSAND_CHAR) != -1), | ||
| /** | ||
| * Legacy format using section symbol ({@code §}) as the color code prefix. | ||
| */ | ||
| LEGACY_SECTION(input -> | ||
| input.indexOf(LegacyComponentSerializer.SECTION_CHAR) != -1), | ||
| /** | ||
| * Minecraft JSON format for components. | ||
| */ | ||
| MINECRAFT_JSON(input -> { | ||
| input = input.trim(); | ||
| return input.startsWith("{") && input.endsWith("}"); | ||
| }); | ||
|
|
||
| // Hack to avoid compiler error while singleton pattern initialization | ||
| private static class Patterns { | ||
| // Pattern to detect any <tag> in a string | ||
| static final Pattern MINI_MESSAGE_PATTERN = | ||
| Pattern.compile("<[a-zA-Z0-9_:-]+(?::[^<>]+)?>"); | ||
| } | ||
|
|
||
| private final Predicate<String> inputPredicate; | ||
|
|
||
| AdventureComponentFormat(Predicate<String> inputPredicate) { | ||
| this.inputPredicate = inputPredicate; | ||
| } | ||
|
|
||
| /** | ||
| * Checks if the given input string matches this format. | ||
| * | ||
| * @param input the input string to check | ||
| * @return true if the input matches this format, false otherwise | ||
| */ | ||
| public boolean matches(String input) { | ||
| if (input == null) { | ||
| return false; | ||
| } | ||
| return inputPredicate.test(input); | ||
| } | ||
| } | ||
105 changes: 105 additions & 0 deletions
105
configlib-adventure/src/main/java/de/exlll/configlib/AdventureComponentSerializer.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| package de.exlll.configlib; | ||
|
|
||
| import net.kyori.adventure.text.Component; | ||
| import net.kyori.adventure.text.TranslatableComponent; | ||
| import net.kyori.adventure.text.minimessage.MiniMessage; | ||
| import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; | ||
| import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; | ||
| import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Serializer for Adventure {@link Component} objects. | ||
| * Supports multiple formats including MiniMessage, legacy, and JSON. | ||
| */ | ||
| public final class AdventureComponentSerializer implements Serializer<Component, String> { | ||
| private final AdventureComponentFormat serializeFormat; | ||
| private final List<AdventureComponentFormat> deserializeOrder; | ||
|
|
||
| /** | ||
| * Creates a new ComponentSerializer with separate format orders for | ||
| * serialization and deserialization. | ||
| * | ||
| * @param serializeFormat the format to use when serializing | ||
| * @param deserializeOrder the order of formats to try when deserializing | ||
| */ | ||
| public AdventureComponentSerializer(AdventureComponentFormat serializeFormat, | ||
| List<AdventureComponentFormat> deserializeOrder) { | ||
| this.serializeFormat = serializeFormat; | ||
| this.deserializeOrder = List.copyOf(deserializeOrder); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new ComponentSerializer using the same format order for | ||
| * both serialization and deserialization. | ||
| * | ||
| * @param serializeFormat the format to use for serialization | ||
| * @param deserializeFormats the formats to use for deserialization, in order of | ||
| * preference | ||
| */ | ||
| public AdventureComponentSerializer(AdventureComponentFormat serializeFormat, | ||
| AdventureComponentFormat... deserializeFormats) { | ||
| this(serializeFormat, deserializeFormats.length == 0 | ||
| ? List.of(serializeFormat) | ||
| : Arrays.asList(deserializeFormats)); | ||
| } | ||
|
|
||
| @Override | ||
| public String serialize(Component element) { | ||
| if (element == null) { | ||
| return null; | ||
| } | ||
|
|
||
| return serialize(element, serializeFormat); | ||
| } | ||
|
|
||
| @Override | ||
| public Component deserialize(String element) { | ||
| if (element == null) { | ||
| return null; | ||
| } | ||
|
|
||
| for (AdventureComponentFormat format : deserializeOrder) { | ||
| if (!format.matches(element)) { | ||
| continue; | ||
| } | ||
|
|
||
| return deserialize(element, format); | ||
| } | ||
Exlll marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Fallback to MiniMessage | ||
| return MiniMessage.miniMessage().deserialize(element); | ||
| } | ||
|
|
||
| private String serialize(Component component, AdventureComponentFormat format) { | ||
| return switch (format) { | ||
| case MINI_MESSAGE -> MiniMessage.miniMessage().serialize(component); | ||
| case LEGACY_AMPERSAND -> | ||
| LegacyComponentSerializer.legacyAmpersand().serialize(component); | ||
| case LEGACY_SECTION -> | ||
| LegacyComponentSerializer.legacySection().serialize(component); | ||
| case MINECRAFT_JSON -> GsonComponentSerializer.gson().serialize(component); | ||
| case TRANSLATION_KEY -> | ||
| component instanceof TranslatableComponent translatableComponent | ||
| ? translatableComponent.key() | ||
| : PlainTextComponentSerializer.plainText().serialize(component); | ||
| }; | ||
zvyap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| private Component deserialize(String string, AdventureComponentFormat format) { | ||
| return switch (format) { | ||
| case MINI_MESSAGE -> | ||
| MiniMessage.miniMessage().deserialize(string); | ||
| case LEGACY_AMPERSAND -> | ||
| LegacyComponentSerializer.legacyAmpersand().deserialize(string); | ||
| case LEGACY_SECTION -> | ||
| LegacyComponentSerializer.legacySection().deserialize(string); | ||
| case MINECRAFT_JSON -> | ||
| GsonComponentSerializer.gson().deserialize(string); | ||
| case TRANSLATION_KEY -> | ||
| Component.translatable(string); | ||
| }; | ||
| } | ||
| } | ||
58 changes: 58 additions & 0 deletions
58
configlib-adventure/src/main/java/de/exlll/configlib/AdventureConfigLib.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package de.exlll.configlib; | ||
|
|
||
| import net.kyori.adventure.key.Key; | ||
| import net.kyori.adventure.sound.Sound; | ||
| import net.kyori.adventure.text.Component; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Utility class providing default serializers for Adventure library types. | ||
| */ | ||
| public final class AdventureConfigLib { | ||
| // Use MiniMessage as the default format since MiniMessage covered all | ||
| // component type | ||
| private static final List<AdventureComponentFormat> DEFAULT_FORMAT_ORDER = List.of( | ||
| AdventureComponentFormat.MINI_MESSAGE | ||
| ); | ||
|
|
||
| private AdventureConfigLib() { | ||
| } | ||
|
|
||
| /** | ||
| * Adds default Adventure serializers to the configuration builder. | ||
| * | ||
| * @param builder the configuration properties builder | ||
| * @param <B> the builder type | ||
| * @return the builder with default serializers added | ||
| */ | ||
| public static <B extends ConfigurationProperties.Builder<B>> | ||
| ConfigurationProperties.Builder<B> addDefaults( | ||
| ConfigurationProperties.Builder<B> builder) { | ||
| return addDefaults(builder, DEFAULT_FORMAT_ORDER.get(0), DEFAULT_FORMAT_ORDER); | ||
| } | ||
|
|
||
| /** | ||
| * Adds default Adventure serializers to the configuration builder with custom | ||
| * format orders. | ||
| * | ||
| * @param builder the configuration properties builder | ||
| * @param serializeFormat the format to use when serializing | ||
| * components | ||
| * @param deserializeOrder the order of formats to try when deserializing | ||
| * components | ||
| * @param <B> the builder type | ||
| * @return the builder with default serializers added | ||
| */ | ||
| public static <B extends ConfigurationProperties.Builder<B>> | ||
| ConfigurationProperties.Builder<B> addDefaults( | ||
| ConfigurationProperties.Builder<B> builder, | ||
| AdventureComponentFormat serializeFormat, | ||
| List<AdventureComponentFormat> deserializeOrder) { | ||
| builder.addSerializer(Component.class, | ||
| new AdventureComponentSerializer(serializeFormat, deserializeOrder)); | ||
| builder.addSerializer(Key.class, new AdventureKeySerializer()); | ||
| builder.addSerializer(Sound.class, new AdventureSoundSerializer()); | ||
| return builder; | ||
| } | ||
| } |
51 changes: 51 additions & 0 deletions
51
configlib-adventure/src/main/java/de/exlll/configlib/AdventureKeySerializer.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package de.exlll.configlib; | ||
|
|
||
| import net.kyori.adventure.key.Key; | ||
|
|
||
| import java.util.OptionalInt; | ||
|
|
||
| /** | ||
| * Serializer for Adventure {@link Key} objects. | ||
| */ | ||
| public final class AdventureKeySerializer implements Serializer<Key, String> { | ||
|
|
||
| private final String defaultNamespace; | ||
|
|
||
| /** | ||
| * Creates a new KeySerializer with the specified default namespace. | ||
| * | ||
| * @param defaultNamespace the default namespace to use when deserializing keys | ||
| * without a namespace | ||
| * @throws IllegalArgumentException if the namespace is invalid | ||
| */ | ||
| public AdventureKeySerializer(String defaultNamespace) { | ||
| this.defaultNamespace = defaultNamespace; | ||
| OptionalInt result = Key.checkNamespace(defaultNamespace); | ||
| if (result.isPresent()) { | ||
| throw new IllegalArgumentException( | ||
| "Invalid namespace at index " + result.getAsInt() + ": " | ||
| + defaultNamespace); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new KeySerializer using Adventure's default namespace (minecraft). | ||
| */ | ||
| public AdventureKeySerializer() { | ||
| this.defaultNamespace = null; // Use Adventure's default namespace | ||
| } | ||
|
|
||
| @Override | ||
| public String serialize(Key element) { | ||
| return element.asString(); | ||
| } | ||
|
|
||
| @Override | ||
| public Key deserialize(String element) { | ||
| if (this.defaultNamespace == null) { | ||
| return Key.key(element); | ||
| } | ||
|
|
||
zvyap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return Key.key(this.defaultNamespace, element); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.